# 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()