# -*- encoding: utf-8 -*-

__version__ = "$Revision: 11261 $"

import unittest

from utext import DefaultSuite, TestCase, TestSuite, before, after, test
from utext.asserts import *

from _common import TestTestRunnerMixin

__all__ = ["AfterTest", "BeforeTest", "DefaultSuiteTest", "TestSuiteTest",
           "AllTests"]


class _BeforeTestCase(TestCase):

    @test
    def foo(self):
        assert_true(hasattr(self, "_setup"), "setup was not called")


class _TestCaseTestBase(TestCase, TestTestRunnerMixin):

    def __init__(self, arg):
        TestCase.__init__(self, arg)
        TestTestRunnerMixin.__init__(self)

    def run_test_suite(self, cls):
        suite = TestSuite()
        suite.add_tests_from_class(cls)
        self.runTest(suite)

    def assert_one_successful_test(self, cls):
        self.run_test_suite(cls)
        self.assert_test_runs(1, 0, 0)


class _Box(object):

    def __init__(self, value=None):
        self.value = value


class AfterTest(_TestCaseTestBase):

    @test
    def decorator(self):

        o = _Box()

        class MyTestCase(TestCase):

            @after
            def teardown(self):
                o.value = True

            @test
            def foo(self):
                pass

        self.run_test_suite(MyTestCase)
        assert_true(o.value, "fixture teardown method was not called")

    @test
    def decorator__subclass_called_first(self):

        o = _Box([])

        class SuperClass(TestCase):

            @after
            def teardown_super(self):
                o.value.append("super")

        class SubClass(SuperClass):

            @after
            def teardown_sub(self):
                o.value.append("sub")

            @test
            def foo(self):
                o.value.append("test")

        self.run_test_suite(SubClass)
        assert_equals(["test", "sub", "super"], o.value)

    @test
    def name(self):

        o = _Box()

        class MyTestCase(TestCase):

            def tearDown(self):
                o.value = True

            @test
            def foo(self):
                pass

        self.run_test_suite(MyTestCase)
        assert_true(o.value, "fixture teardown method was not called")

    @test
    def after_called_if_test_fails(self):

        o = _Box()

        class MyTestCase(TestCase):

            @after
            def after_method(self):
                o.value = True

            @test
            def failing_test(self):
                fail("failing")

        self.run_test_suite(MyTestCase)
        assert_true(o.value, "after_method was not called")

    @test
    def after_in_subclass_called_if_test_fails(self):

        o = _Box()

        class SuperClass(TestCase):

            pass

        class SubClass(SuperClass):

            @after
            def after_method(self):
                o.value = True

            @test
            def failing_test(self):
                fail("failing")

        self.run_test_suite(SubClass)
        assert_true(o.value, "after_method was not called")


class BeforeTest(_TestCaseTestBase):

    @test
    def decorator(self):

        class MyTestCase(_BeforeTestCase):

            @before
            def setup(self):
                self._setup = True

        self.assert_one_successful_test(MyTestCase)

    @test
    def decorator__subclass(self):

        class SuperClass(_BeforeTestCase):

            @before
            def setup(self):
                self._setup = True

        class SubClass(SuperClass):

            pass

        self.assert_one_successful_test(SubClass)

    @test
    def decorator__subclass_called_first(self):

        class SuperClass(TestCase):

            @before
            def setup_super(self):
                self.marked = True

        class SubClass(SuperClass):

            @before
            def setup_sub(self):
                assert_true(hasattr(self, "marked"))

            @test
            def foo(self):
                pass

        self.assert_one_successful_test(SubClass)

    @test
    def name(self):

        class MyTestCase(_BeforeTestCase):

            def setUp(self):
                self._setup = True

        self.assert_one_successful_test(MyTestCase)


class DefaultSuiteTest(_TestCaseTestBase):

    def _create_empty_suite(self):
        class MySuite(DefaultSuite):
            pass
        return MySuite()

    @test
    def count_empty_suite(self):
        suite = self._create_empty_suite()
        assert_equals(0, suite.countTestCases())

    @test
    def run_empty_suite(self):
        suite = self._create_empty_suite()
        self.runTest(suite)
        self.assert_test_runs(0, 0, 0)

    def _create_suite_with_package(self):
        import _dummy as pkg
        class MySuite(DefaultSuite):
            test_packages = [pkg]
        return MySuite()

    @test
    def count_package(self):
        suite = self._create_suite_with_package()
        assert_equals(2, suite.countTestCases())

    @test
    def run_package(self):
        suite = self._create_suite_with_package()
        self.runTest(suite)
        self.assert_test_runs(1, 0, 1)

    def _create_suite_with_test_case(self):
        class MyTestCase(unittest.TestCase):
            def test_success(self): pass
            def test_error(self): raise KeyError()
        class MySuite(DefaultSuite):
            tests = [MyTestCase]
        return MySuite()

    @test
    def count_test_case(self):
        suite = self._create_suite_with_test_case()
        assert_equals(2, suite.countTestCases())

    @test
    def run_test_case(self):
        suite = self._create_suite_with_test_case()
        self.runTest(suite)
        self.assert_test_runs(1, 1, 0)


class TestSuiteTest(_TestCaseTestBase):

    @test
    def method_with_prefix(self):
        class MyTestCase(TestCase):
            def test_foo(self): pass
        self.assert_one_successful_test(MyTestCase)

    @test
    def method_with_decorator(self):
        class MyTestCase(TestCase):
            @test
            def foo(self): pass
        self.assert_one_successful_test(MyTestCase)

    @test
    def method_with_prefix_and_decorator(self):
        class MyTestCase(TestCase):
            @test
            def test_foo(self): pass
        self.assert_one_successful_test(MyTestCase)


class AllTests(DefaultSuite):

    tests = [AfterTest, BeforeTest, DefaultSuiteTest, TestSuiteTest]
