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 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 setUp(self): # Create the renderer we will use self.renderer = SuiteRenderer()
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