diff options
Diffstat (limited to 'catapult/common/py_vulcanize/py_vulcanize/html_module_unittest.py')
-rw-r--r-- | catapult/common/py_vulcanize/py_vulcanize/html_module_unittest.py | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/catapult/common/py_vulcanize/py_vulcanize/html_module_unittest.py b/catapult/common/py_vulcanize/py_vulcanize/html_module_unittest.py new file mode 100644 index 00000000..fb4af16c --- /dev/null +++ b/catapult/common/py_vulcanize/py_vulcanize/html_module_unittest.py @@ -0,0 +1,321 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import unittest +import StringIO + +from py_vulcanize import fake_fs +from py_vulcanize import generate +from py_vulcanize import html_generation_controller +from py_vulcanize import html_module +from py_vulcanize import parse_html_deps +from py_vulcanize import project as project_module +from py_vulcanize import resource +from py_vulcanize import resource_loader as resource_loader + + +class ResourceWithFakeContents(resource.Resource): + + def __init__(self, toplevel_dir, absolute_path, fake_contents): + """A resource with explicitly provided contents. + + If the resource does not exist, then pass fake_contents=None. This will + cause accessing the resource contents to raise an exception mimicking the + behavior of regular resources.""" + super(ResourceWithFakeContents, self).__init__(toplevel_dir, absolute_path) + self._fake_contents = fake_contents + + @property + def contents(self): + if self._fake_contents is None: + raise Exception('File not found') + return self._fake_contents + + +class FakeLoader(object): + + def __init__(self, source_paths, initial_filenames_and_contents=None): + self._source_paths = source_paths + self._file_contents = {} + if initial_filenames_and_contents: + for k, v in initial_filenames_and_contents.iteritems(): + self._file_contents[k] = v + + def FindResourceGivenAbsolutePath(self, absolute_path): + candidate_paths = [] + for source_path in self._source_paths: + if absolute_path.startswith(source_path): + candidate_paths.append(source_path) + if len(candidate_paths) == 0: + return None + + # Sort by length. Longest match wins. + candidate_paths.sort(lambda x, y: len(x) - len(y)) + longest_candidate = candidate_paths[-1] + + return ResourceWithFakeContents( + longest_candidate, absolute_path, + self._file_contents.get(absolute_path, None)) + + def FindResourceGivenRelativePath(self, relative_path): + absolute_path = None + for script_path in self._source_paths: + absolute_path = os.path.join(script_path, relative_path) + if absolute_path in self._file_contents: + return ResourceWithFakeContents(script_path, absolute_path, + self._file_contents[absolute_path]) + return None + + +class ParseTests(unittest.TestCase): + + def testValidExternalScriptReferenceToRawScript(self): + parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html> + <script src="../foo.js"> + """) + + file_contents = {} + file_contents[os.path.normpath('/tmp/a/foo.js')] = """ +'i am just some raw script'; +""" + + metadata = html_module.Parse( + FakeLoader([os.path.normpath('/tmp')], file_contents), + 'a.b.start', + '/tmp/a/b/', + is_component=False, + parser_results=parse_results) + self.assertEquals([], metadata.dependent_module_names) + self.assertEquals( + ['a/foo.js'], metadata.dependent_raw_script_relative_paths) + + def testExternalScriptReferenceToModuleOutsideScriptPath(self): + parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html> + <script src="/foo.js"> + """) + + file_contents = {} + file_contents[os.path.normpath('/foo.js')] = '' + + def DoIt(): + html_module.Parse(FakeLoader([os.path.normpath('/tmp')], file_contents), + 'a.b.start', + '/tmp/a/b/', + is_component=False, + parser_results=parse_results) + self.assertRaises(Exception, DoIt) + + def testExternalScriptReferenceToFileThatDoesntExist(self): + parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html> + <script src="/foo.js"> + """) + + file_contents = {} + + def DoIt(): + html_module.Parse(FakeLoader([os.path.normpath('/tmp')], file_contents), + 'a.b.start', + '/tmp/a/b/', + is_component=False, + parser_results=parse_results) + self.assertRaises(Exception, DoIt) + + def testValidImportOfModule(self): + parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html> + <link rel="import" href="../foo.html"> + """) + + file_contents = {} + file_contents[os.path.normpath('/tmp/a/foo.html')] = """ +""" + + metadata = html_module.Parse( + FakeLoader([os.path.normpath('/tmp')], file_contents), + 'a.b.start', + '/tmp/a/b/', + is_component=False, + parser_results=parse_results) + self.assertEquals(['a.foo'], metadata.dependent_module_names) + + def testStyleSheetImport(self): + parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html> + <link rel="stylesheet" href="../foo.css"> + """) + + file_contents = {} + file_contents[os.path.normpath('/tmp/a/foo.css')] = """ +""" + metadata = html_module.Parse( + FakeLoader([os.path.normpath('/tmp')], file_contents), + 'a.b.start', + '/tmp/a/b/', + is_component=False, + parser_results=parse_results) + self.assertEquals([], metadata.dependent_module_names) + self.assertEquals(['a.foo'], metadata.style_sheet_names) + + def testUsingAbsoluteHref(self): + parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html> + <script src="/foo.js"> + """) + + file_contents = {} + file_contents[os.path.normpath('/src/foo.js')] = '' + + metadata = html_module.Parse( + FakeLoader([os.path.normpath("/tmp"), os.path.normpath("/src")], + file_contents), + "a.b.start", + "/tmp/a/b/", + is_component=False, + parser_results=parse_results) + self.assertEquals(['foo.js'], metadata.dependent_raw_script_relative_paths) + + +class HTMLModuleTests(unittest.TestCase): + + def testBasicModuleGeneration(self): + file_contents = {} + file_contents[os.path.normpath('/tmp/a/b/start.html')] = """ +<!DOCTYPE html> +<link rel="import" href="/widget.html"> +<link rel="stylesheet" href="../common.css"> +<script src="/raw_script.js"></script> +<script src="/excluded_script.js"></script> +<dom-module id="start"> + <template> + </template> + <script> + 'use strict'; + console.log('inline script for start.html got written'); + </script> +</dom-module> +""" + file_contents[os.path.normpath('/py_vulcanize/py_vulcanize.html')] = """<!DOCTYPE html> +""" + file_contents[os.path.normpath('/components/widget.html')] = """ +<!DOCTYPE html> +<link rel="import" href="/py_vulcanize.html"> +<widget name="widget.html"></widget> +<script> +'use strict'; +console.log('inline script for widget.html'); +</script> +""" + file_contents[os.path.normpath('/tmp/a/common.css')] = """ +/* /tmp/a/common.css was written */ +""" + file_contents[os.path.normpath('/raw/raw_script.js')] = """ +console.log('/raw/raw_script.js was written'); +""" + file_contents[os.path.normpath( + '/raw/components/polymer/polymer.min.js')] = """ +""" + + with fake_fs.FakeFS(file_contents): + project = project_module.Project( + [os.path.normpath('/py_vulcanize/'), + os.path.normpath('/tmp/'), + os.path.normpath('/components/'), + os.path.normpath('/raw/')]) + loader = resource_loader.ResourceLoader(project) + a_b_start_module = loader.LoadModule( + module_name='a.b.start', excluded_scripts=['\/excluded_script.js']) + load_sequence = project.CalcLoadSequenceForModules([a_b_start_module]) + + # Check load sequence names. + load_sequence_names = [x.name for x in load_sequence] + self.assertEquals(['py_vulcanize', + 'widget', + 'a.b.start'], load_sequence_names) + + # Check module_deps on a_b_start_module + def HasDependentModule(module, name): + return [x for x in module.dependent_modules + if x.name == name] + assert HasDependentModule(a_b_start_module, 'widget') + + # Check JS generation. + js = generate.GenerateJS(load_sequence) + assert 'inline script for start.html' in js + assert 'inline script for widget.html' in js + assert '/raw/raw_script.js' in js + assert 'excluded_script.js' not in js + + # Check HTML generation. + html = generate.GenerateStandaloneHTMLAsString( + load_sequence, title='', flattened_js_url='/blah.js') + assert '<dom-module id="start">' in html + assert 'inline script for widget.html' not in html + assert 'common.css' in html + + def testPolymerConversion(self): + file_contents = {} + file_contents[os.path.normpath('/tmp/a/b/my_component.html')] = """ +<!DOCTYPE html> +<dom-module id="my-component"> + <template> + </template> + <script> + 'use strict'; + Polymer ( { + is: "my-component" + }); + </script> +</dom-module> +""" + with fake_fs.FakeFS(file_contents): + project = project_module.Project([ + os.path.normpath('/py_vulcanize/'), os.path.normpath('/tmp/')]) + loader = resource_loader.ResourceLoader(project) + my_component = loader.LoadModule(module_name='a.b.my_component') + + f = StringIO.StringIO() + my_component.AppendJSContentsToFile( + f, + use_include_tags_for_scripts=False, + dir_for_include_tag_root=None) + js = f.getvalue().rstrip() + expected_js = """ + 'use strict'; + Polymer ( { + is: "my-component" + }); +""".rstrip() + self.assertEquals(expected_js, js) + + def testInlineStylesheetURLs(self): + file_contents = {} + file_contents[os.path.normpath('/tmp/a/b/my_component.html')] = """ +<!DOCTYPE html> +<style> +.some-rule { + background-image: url('../something.jpg'); +} +</style> +""" + file_contents[os.path.normpath('/tmp/a/something.jpg')] = 'jpgdata' + with fake_fs.FakeFS(file_contents): + project = project_module.Project([ + os.path.normpath('/py_vulcanize/'), os.path.normpath('/tmp/')]) + loader = resource_loader.ResourceLoader(project) + my_component = loader.LoadModule(module_name='a.b.my_component') + + computed_deps = [] + my_component.AppendDirectlyDependentFilenamesTo(computed_deps) + self.assertEquals(set(computed_deps), + set([os.path.normpath('/tmp/a/b/my_component.html'), + os.path.normpath('/tmp/a/something.jpg')])) + + f = StringIO.StringIO() + ctl = html_generation_controller.HTMLGenerationController() + my_component.AppendHTMLContentsToFile(f, ctl) + html = f.getvalue().rstrip() + # FIXME: This is apparently not used. + expected_html = """ +.some-rule { + background-image: url(data:image/jpg;base64,anBnZGF0YQ==); +} +""".rstrip() |