# 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(""" """ file_contents[os.path.normpath('/py_vulcanize/py_vulcanize.html')] = """ """ file_contents[os.path.normpath('/components/widget.html')] = """ """ 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 '' 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')] = """ """ 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')] = """ """ 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()