aboutsummaryrefslogtreecommitdiff
path: root/catapult/common/py_vulcanize/py_vulcanize/html_module_unittest.py
diff options
context:
space:
mode:
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.py321
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()