##########################################################################
# This file is part of WTFramework.
#
#    WTFramework is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    WTFramework is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with WTFramework.  If not, see <http://www.gnu.org/licenses/>.
##########################################################################

from mockito import mock
from wtframework.wtf.testobjects.testcase import WatchedTestCase
import unittest2

__wtf_test_logger_var = []


class TestWatchedTestCaseWatchers(WatchedTestCase):

    def __init__(self, *args, **kwargs):
        super(TestWatchedTestCaseWatchers, self).__init__(*args, **kwargs)
        self.watcher = LoggerTestWatcher()
        self._register_watcher(self.watcher)

    def setUp(self):
        self.watcher.log.append("setUp")
        return

    def tearDown(self):
        self.watcher.log.append("tearDown")
        return

    def test_aaa_something(self):
        "Dummy test to set things up."
        self.watcher.log.append("test_aaa")
        return

    def test_bbb_something(self):
        "2nd dummp test to set things up"
        self.watcher.log.append("test_bbb")
        return

    def test_zzz_test_our_real_event_sequence(self):
        "Check the dummy test's sequence of events."

        # Keep in mind we're running a test after another test.
        expected = ['before_setup',  # generated by test_aaa
                    'setUp',
                    'before_test',
                    'test_aaa',
                    'on_test_pass',
                    'after_test',
                    'tearDown',
                    'after_teardown',
                    'before_setup',  # generated by test_bbb
                    'setUp',
                    'before_test',
                    'test_bbb',
                    'on_test_pass',
                    'after_test',
                    'tearDown',
                    'after_teardown',
                    'before_setup',  # generated by test_zzz
                    'setUp',
                    'before_test']
        print self.get_log()
        self.assertEqual(expected,
                         self.get_log())


class TestWatchedTestCase(unittest2.TestCase):

    def test_passed_test_case_runs_setup_and_cleanup(self):
        mockresult = mock(unittest2.TestResult)
        tc = TestCaseStub(methodName="runTest")
        tc.run(mockresult)

        self.assertTrue(tc.setupRan)
        self.assertTrue(tc.tearDownRan)

    def test_failed_setup_does_not_run_test_and_runs_cleanup(self):
        mockresult = mock(unittest2.TestResult)
        tc = TestCaseStub(methodName="runTest")
        tc.failSetup = True
        tc.run(mockresult)

        self.assertTrue(tc.tearDownRan)
        self.assertFalse(tc.testRan)

    def test_failed_test_does_not_complete_and_runs_cleanup(self):
        mockresult = mock(unittest2.TestResult)
        tc = TestCaseStub(methodName="runTest")
        tc.failTest = True
        tc.run(mockresult)

        self.assertTrue(tc.tearDownRan)
        self.assertTrue(tc.testRan)
        self.assertFalse(tc.testPassed)


class TestCaseStub(WatchedTestCase):
    setupRan = False
    testRan = False
    testPassed = False
    tearDownRan = False

    failSetup = False
    failTest = False

    def setUp(self):
        self.setupRan = True

        if self.failSetup:
            raise RuntimeError("test error")

    def tearDown(self):
        self.tearDownRan = True

    def runTest(self):
        self.testRan = True

        if self.failTest:
            raise RuntimeError("Failed test")

        self.testPassed = True


class LoggerTestWatcher(object):

    "This test watcher just logs actions to a list to verify order of events."

    log = []

    def before_setup(self, test_case, test_result):
        print "LoggerTestWatcher before_setup"
        self.log.append("before_setup")

    def before_test(self, test_case, test_result):
        self.log.append("before_test")

    def after_test(self, test_case, test_result):
        self.log.append("after_test")

    def after_teardown(self, test_case, test_result):
        self.log.append("after_teardown")

    def on_test_failure(self, test_case, test_result, exception):
        self.log.append("on_test_failure")

    def on_test_error(self, test_case, test_result, exception):
        self.log.append("on_test_error")

    def on_test_pass(self, test_case, test_result):
        self.log.append("on_test_pass")

    def get_log(self):
        return self.log


if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest2.main()
