Exemple #1
0
    def _test_runner_html(self, dev_mode=False):
        """
        Return a parsed tree of the test runner page HTML.
        """
        # Configure the renderer to use dev mode
        self.renderer = SuiteRenderer(dev_mode=dev_mode)

        # Create a mock test suite description
        desc = self._mock_desc([], [], [], 'jasmine')

        # Render the description to HTML, enabling dev mode
        html = self.renderer.render_to_string('test-suite', desc)

        # Parse the HTML
        return etree.HTML(html)
Exemple #2
0
    def test_jasmine_dev_mode_includes(self):

        # Configure the renderer to use dev mode
        self.renderer = SuiteRenderer(dev_mode=True)

        # Include the HTMLReporter instead of the JSON reporter
        jasmine_libs = ['jasmine/jasmine.js',
                        'jasmine/jasmine-html.js']
        lib_paths = ['lib1.js', 'lib2.js']
        src_paths = ['src1.js', 'src2.js']
        spec_paths = ['spec1.js', 'spec2.js']

        # Create a mock test suite description
        desc = self._mock_desc(lib_paths, src_paths, spec_paths, 'jasmine')

        # Check that we get the right script includes
        suite_includes = lib_paths + src_paths + spec_paths
        self._assert_js_includes(jasmine_libs, suite_includes, desc)
Exemple #3
0
    def setUp(self):

        # Create the renderer we will use
        self.renderer = SuiteRenderer()
Exemple #4
0
class SuiteRendererTest(unittest.TestCase):

    JASMINE_TEST_RUNNER_SCRIPT = dedent("""
        (function() {
            var jasmineEnv = jasmine.getEnv();
            jasmineEnv.updateInterval = 1000;

            var reporter = new jasmine.JsonReporter("js_test_tool_results", "test-suite");
            jasmineEnv.addReporter(reporter);

            jasmineEnv.specFilter = function(spec) {
                return reporter.specFilter(spec);
            };

            var currentWindowOnload = window.onload;

            window.onload = function() {
                if (currentWindowOnload) {
                    currentWindowOnload();
                }

                execJasmine();
            };

            function execJasmine() {
                try {
                    jasmineEnv.execute();
                }
                catch(err) {
                    window.js_test_tool.reportError(err);
                }
            }

            if (!window.js_test_tool) {
                window.js_test_tool = {};
                window.js_test_tool.reportError = function(err) {
                    var resultDiv = document.getElementById("js_test_tool_results");
                    var errDiv = document.getElementById("js_test_tool_error");

                    // If an error <div> is defined (e.g. not in dev mode)
                    // then write the error to that <div>
                    // so the Browser can report it
                    if (errDiv) {
                        errDiv.innerHTML = err.toString()
                        if ('stack' in err) {
                            errDiv.innerHTML += "\\n" + err.stack
                        }

                        // Signal to the browser that we're done
                        // to avoid blocking until timeout
                        resultsDiv.className = "done";
                    }

                    // Re-throw the error (e.g. for dev mode)
                    else {
                        throw err;
                    }
                }
            }

        })();
    """).strip()

    JASMINE_LOAD_FIXTURES_SCRIPT = dedent("""
        // Load fixtures if using jasmine-jquery
        if (jasmine.getFixtures) {
            jasmine.getFixtures().fixturesPath = "/suite/test-suite/include/";
        }
    """).strip()

    ALERT_STUB_SCRIPT = dedent("""
        // Stub out modal dialog alerts, which will prevent
        // us from accessing the test results in the DOM
        window.confirm = function(){return true;};
        window.alert = function(){return;};
    """).strip()

    def setUp(self):

        # Create the renderer we will use
        self.renderer = SuiteRenderer()

    def test_unicode(self):

        # Create a mock test suite description
        desc = self._mock_desc(['lib1.js', 'lib2.js'],
                               ['src1.js', 'src2.js'],
                               ['spec1.js', 'spec2.js'],
                               'jasmine')

        # Render the description as HTML
        html = self.renderer.render_to_string('test-suite', desc)

        # Expect that we get a `unicode` string
        self.assertTrue(isinstance(html, unicode))

    def test_jasmine_runner_includes(self):

        jasmine_libs = ['jasmine/jasmine.js',
                        'jasmine/jasmine-json.js']
        lib_paths = ['lib1.js', 'lib2.js']
        src_paths = ['src1.js', 'src2.js']
        spec_paths = ['spec1.js', 'spec2.js']

        # Create a mock test suite description
        desc = self._mock_desc(lib_paths, src_paths, spec_paths, 'jasmine')

        # Check that we get the right script includes
        suite_includes = lib_paths + src_paths + spec_paths
        self._assert_js_includes(jasmine_libs, suite_includes, desc)

        # Check that only "include_in_page" scripts were used
        desc.lib_paths.assert_called_with(only_in_page=True)
        desc.src_paths.assert_called_with(only_in_page=True)
        desc.spec_paths.assert_called_with(only_in_page=True)

    def test_no_lib_files(self):

        jasmine_libs = ['jasmine/jasmine.js',
                        'jasmine/jasmine-json.js']
        src_paths = ['src.js']
        spec_paths = ['spec.js']

        # Create a mock test suite description
        desc = self._mock_desc([], src_paths, spec_paths, 'jasmine')

        # Check that we get the right script includes
        suite_includes = src_paths + spec_paths
        self._assert_js_includes(jasmine_libs, suite_includes, desc)

    def test_render_jasmine_runner(self):

        # Create a test runner page
        tree = self._test_runner_html()

        # Expect that a <div> exists with the correct ID for the results
        div_id = SuiteRenderer.RESULTS_DIV_ID
        elems = tree.xpath('//div[@id="{}"]'.format(div_id))
        self.assertEqual(len(elems), 1)

        # Expect that a <div> exists for reporting JS errors
        div_id = SuiteRenderer.ERROR_DIV_ID
        elems = tree.xpath('//div[@id="{}"]'.format(div_id))
        self.assertEqual(len(elems), 1)

        # Expect that the right scripts are available
        self._assert_script(tree, self.JASMINE_TEST_RUNNER_SCRIPT, -1)
        self._assert_script(tree, self.JASMINE_LOAD_FIXTURES_SCRIPT, -2)

    def test_render_jasmine_dev_mode(self):

        # Create a test runner page in dev mode
        tree = self._test_runner_html(dev_mode=True)

        # Should get the same script, except with an HTML reporter
        # instead of the custom JSON reporter
        expected_script = self.JASMINE_TEST_RUNNER_SCRIPT.replace(
            'JsonReporter("js_test_tool_results", "test-suite")',
            'HtmlReporter()')

        # Check that we have the right script available
        self._assert_script(tree, expected_script, -1)

    def test_jasmine_dev_mode_includes(self):

        # Configure the renderer to use dev mode
        self.renderer = SuiteRenderer(dev_mode=True)

        # Include the HTMLReporter instead of the JSON reporter
        jasmine_libs = ['jasmine/jasmine.js',
                        'jasmine/jasmine-html.js']
        lib_paths = ['lib1.js', 'lib2.js']
        src_paths = ['src1.js', 'src2.js']
        spec_paths = ['spec1.js', 'spec2.js']

        # Create a mock test suite description
        desc = self._mock_desc(lib_paths, src_paths, spec_paths, 'jasmine')

        # Check that we get the right script includes
        suite_includes = lib_paths + src_paths + spec_paths
        self._assert_js_includes(jasmine_libs, suite_includes, desc)

    def test_stub_alerts(self):

        tree = self._test_runner_html()
        self._assert_script(tree, self.ALERT_STUB_SCRIPT, 0)

    def test_stub_alerts_dev_mode(self):

        tree = self._test_runner_html(dev_mode=True)
        self._assert_script(tree, self.ALERT_STUB_SCRIPT, 0)

    def test_undefined_template(self):

        # Create a mock test suite description with an invalid test runner
        desc = self._mock_desc([], [], [], 'invalid_test_runner')

        # Should get an exception that the template could not be found
        with self.assertRaises(SuiteRendererError):
            self.renderer.render_to_string('test-suite', desc)

    def test_template_render_error(self):

        # Create a mock test suite description with no includes
        desc = self._mock_desc([], [], [], 'jasmine')

        # Patch Jinja2's `render()` function
        with mock.patch.object(SuiteRenderer, 'render_template') as render_func:

            # Have the render function raise an exception
            render_func.side_effect = ValueError()

            # Expect that we get a `SuiteRendererError`
            with self.assertRaises(SuiteRendererError):
                self.renderer.render_to_string('test-suite', desc)

    def _test_runner_html(self, dev_mode=False):
        """
        Return a parsed tree of the test runner page HTML.
        """
        # Configure the renderer to use dev mode
        self.renderer = SuiteRenderer(dev_mode=dev_mode)

        # Create a mock test suite description
        desc = self._mock_desc([], [], [], 'jasmine')

        # Render the description to HTML, enabling dev mode
        html = self.renderer.render_to_string('test-suite', desc)

        # Parse the HTML
        return etree.HTML(html)

    def _assert_script(self, html_tree, expected_script, script_index):
        """
        Assert that the parsed HTML tree `html_tree` contains
        `expected_script` in a <script> tag at `script_index` (starting at 0).
        """
        # Retrieve the script elements
        script_elems = html_tree.xpath('/html/head/script')

        # Expect there are enough elements to retrieve the index
        self.assertTrue(len(script_elems) > abs(script_index))

        # Retrieve the script element
        actual_script = script_elems[script_index].text.strip()

        # Expect that we got the right script
        self.assertEqual(actual_script, expected_script)

    def _assert_js_includes(self, runner_includes, suite_includes, suite_desc):
        """
        Render `suite_desc` (a `SuiteDescription` instance or mock) to
        `html`, then asserts that the `html` contains `<script>` tags with
        `runner_includes` (files included by default, with a `/runner/` prefix)
        and `suite_includes` (files included by the test suite,
        with a `/suite/include` prefix)
        """
        # Render the description as HTML
        html = self.renderer.render_to_string('test-suite', suite_desc)

        # Parse the HTML
        tree = etree.HTML(html)

        # Retrieve all <script> inclusions
        script_elems = tree.xpath('/html/head/script')

        # Prepend the runner and suite includes
        runner_includes = [os.path.join('/runner', path)
                           for path in runner_includes]
        suite_includes = [os.path.join('/suite', 'test-suite', 'include', path)
                          for path in suite_includes]

        # Check that they match the sources we provided, in order
        all_paths = [element.get('src') for element in script_elems
                     if element.get('src') is not None]

        self.assertEqual(all_paths, runner_includes + suite_includes)

    @staticmethod
    def _mock_desc(lib_paths, src_paths, spec_paths, test_runner):
        """
        Create a mock SuiteDescription configured to return
        `lib_paths` (paths to JS dependency files)
        `src_paths` (paths to JS source files)
        `spec_paths` (paths to JS spec files)
        `test_runner` (name of the test runner, e.g. Jasmine)

        Returns the configured mock
        """
        desc = mock.MagicMock(SuiteDescription)

        desc.lib_paths.return_value = lib_paths
        desc.src_paths.return_value = src_paths
        desc.spec_paths.return_value = spec_paths
        desc.test_runner.return_value = test_runner

        return desc