"""Unit tests for the Paver JavaScript testing tasks."""

import ddt
from mock import patch
from paver.easy import call_task

import pavelib.js_test
from .utils import PaverTestCase


@ddt.ddt
class TestPaverJavaScriptTestTasks(PaverTestCase):
    """
    Test the Paver JavaScript testing tasks.
    """

    EXPECTED_DELETE_JAVASCRIPT_REPORT_COMMAND = u'find {platform_root}/reports/javascript -type f -delete'
    EXPECTED_INSTALL_NPM_ASSETS_COMMAND = u'install npm_assets'
    EXPECTED_COFFEE_COMMAND = (
        u'node_modules/.bin/coffee --compile `find {platform_root}/lms {platform_root}/cms '
        u'{platform_root}/common -type f -name "*.coffee"`'
    )
    EXPECTED_JS_TEST_TOOL_OPTIONS = (
        u"{platform_root}/lms/static/js_test.yml "
        u"{platform_root}/lms/static/js_test_coffee.yml "
        u"{platform_root}/cms/static/js_test.yml "
        u"{platform_root}/cms/static/js_test_squire.yml "
        u"{platform_root}/common/lib/xmodule/xmodule/js/js_test.yml "
        u"{platform_root}/common/static/js_test.yml "
        u"{platform_root}/common/static/js_test_requirejs.yml "
        u"--use-firefox "
        u"--timeout-sec 600 "
        u"--xunit-report "
        u"{platform_root}/reports/javascript/javascript_xunit.xml"
    )
    EXPECTED_COVERAGE_OPTIONS = (
        u' --coverage-xml {platform_root}/reports/javascript/coverage.xml'
    )

    EXPECTED_COMMANDS = [
        u"make report_dir",
        u'git clean -fqdx test_root/logs test_root/data test_root/staticfiles test_root/uploads',
        u"find . -name '.git' -prune -o -name '*.pyc' -exec rm {} \\;",
        u'rm -rf test_root/log/auto_screenshots/*',
        u"rm -rf /tmp/mako_[cl]ms",
    ]

    def setUp(self):
        super(TestPaverJavaScriptTestTasks, self).setUp()

        # Mock the paver @needs decorator
        self._mock_paver_needs = patch.object(pavelib.js_test.test_js, 'needs').start()
        self._mock_paver_needs.return_value = 0

        # Cleanup mocks
        self.addCleanup(self._mock_paver_needs.stop)

    @ddt.data(
        [""],
        ["--coverage"],
        ["--suite=lms"],
        ["--suite=lms --coverage"],
    )
    @ddt.unpack
    def test_test_js_run(self, options_string):
        """
        Test the "test_js_run" task.
        """
        options = self.parse_options_string(options_string)
        self.reset_task_messages()
        call_task("pavelib.js_test.test_js_run", options=options)
        self.verify_messages(options=options, dev_mode=False)

    @ddt.data(
        [""],
        ["--port=9999"],
        ["--suite=lms"],
        ["--suite=lms --port=9999"],
    )
    @ddt.unpack
    def test_test_js_dev(self, options_string):
        """
        Test the "test_js_run" task.
        """
        options = self.parse_options_string(options_string)
        self.reset_task_messages()
        call_task("pavelib.js_test.test_js_dev", options=options)
        self.verify_messages(options=options, dev_mode=True)

    def parse_options_string(self, options_string):
        """
        Parse a string containing the options for a test run
        """
        parameters = options_string.split(" ")
        suite = "all"
        if "--system=lms" in parameters:
            suite = "lms"
        elif "--system=common" in parameters:
            suite = "common"
        coverage = "--coverage" in parameters
        port = None
        if "--port=9999" in parameters:
            port = 9999
        return {
            "suite": suite,
            "coverage": coverage,
            "port": port,
        }

    def verify_messages(self, options, dev_mode):
        """
        Verify that the messages generated when running tests are as expected
        for the specified options and dev_mode.
        """
        is_coverage = options['coverage']
        port = options['port']
        expected_messages = []
        expected_messages.extend(self.EXPECTED_COMMANDS)
        if not dev_mode and not is_coverage:
            expected_messages.append(self.EXPECTED_DELETE_JAVASCRIPT_REPORT_COMMAND.format(
                platform_root=self.platform_root
            ))
        expected_messages.append(self.EXPECTED_INSTALL_NPM_ASSETS_COMMAND)
        expected_messages.append(self.EXPECTED_COFFEE_COMMAND.format(platform_root=self.platform_root))
        expected_test_tool_command = u'js-test-tool {command} {options}'.format(
            command='dev' if dev_mode else 'run',
            options=self.EXPECTED_JS_TEST_TOOL_OPTIONS.format(platform_root=self.platform_root),
        )
        if is_coverage:
            expected_test_tool_command += self.EXPECTED_COVERAGE_OPTIONS.format(platform_root=self.platform_root)
        if port:
            expected_test_tool_command += u" -p {port}".format(port=port)
        expected_messages.append(expected_test_tool_command)
        self.assertEquals(self.task_messages, expected_messages)
