| # Copyright 2019 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. |
| """Generates HTML file with all dependencies from a js_unittest build target.""" |
| |
| import os |
| import sys |
| from argparse import ArgumentParser |
| |
| _HTML_FILE = r"""<!DOCTYPE html> |
| <html> |
| <script> |
| // Basic include checker. |
| window.addEventListener('error', function(e) { |
| if ((e.target instanceof HTMLScriptElement)) { |
| console.log('ERROR loading <script> element (does it exist?):\n\t' + |
| e.srcElement.src + '\n\tIncluded from: ' + |
| e.srcElement.baseURI); |
| } |
| }, true /* useCapture */); |
| </script> |
| <body> |
| """ |
| |
| _SCRIPT = r'<script src="%s"></script>' |
| _IMPORT = r'<link rel="import" href="%s">' |
| |
| _HTML_FOOTER = r""" |
| </body> |
| </html> |
| """ |
| |
| |
| def _process_deps(unique_deps, html_import, target_name): |
| """Processes all deps strings, yielding each HTML tag to include the dep. |
| |
| Args: |
| unique_deps: Iterator of strings, for all deps to be processed. |
| html_import: Boolean: Enables the use of HTMLImport for the main Polymer |
| element being tested. |
| target_name: Current test target name, used to infer the main Polymer |
| element for HTMLImport. element_unitest => element.js/element.html. |
| |
| Returns: |
| Iterator of strings, each string is a HTML tag <script> or <link>. |
| """ |
| for dep in unique_deps: |
| # Special case for jstemplate which has multiple files but we server all of |
| # them combined from chrome://resources/js/jstemplate_compiled.js |
| if '/jstemplate/' in dep: |
| if '/jstemplate.js' in dep: |
| yield ('<script src=' |
| '"chrome://resources/js/jstemplate_compiled.js"></script>') |
| # just ignore other files files from /jstemplate/ |
| continue |
| |
| # Map file_manager files: |
| dep = dep.replace('ui/file_manager/', |
| 'chrome://file_manager_test/ui/file_manager/', 1) |
| # WebUI files (both Polymer and non-Polymer): |
| dep = dep.replace('ui/webui/resources/', 'chrome://resources/', 1) |
| |
| # Polymer Files: |
| dep = dep.replace('third_party/polymer/', 'chrome://resources/polymer/', 1) |
| dep = dep.replace('components-chromium/', '', 1) |
| |
| # Remove the relative because all replaces above map to an absolute path in |
| # chrome://* and this URL scheme doesn't allow "..". |
| dep = dep.replace('../', '') |
| |
| # Find the file being tested eg: element_unittest => element.js |
| implementation_file = target_name.replace('_unittest', '.js') |
| |
| # If it should use HTMLImport the main element JS file shouldn't be |
| # included, instead we <link rel=import> its HTML file which in turn |
| # includes the JS file. Note that all other JS deps are included as |
| # <script>. |
| if html_import and dep.endswith(implementation_file): |
| dep = dep.replace('.js', '.html') |
| yield _IMPORT % (dep) |
| else: |
| # Normal dep, just return the <script src="dep.js"> |
| yield _SCRIPT % (dep) |
| |
| |
| def _process(deps, output_filename, mocks, html_import, target_name): |
| """Generates the HTML file with all JS dependencies for JS unittest. |
| |
| Args: |
| deps: List of strings for each dependency path. |
| output_filename: String, HTML file name that will be generated. |
| mocks: List of strings, JS file names that will be included in the bottom to |
| overwrite JS implementation from deps. |
| html_import: Boolean, indicate if HTMLImport should be used for testing |
| Polymer elements. |
| target_name: Current test target name, used to infer the main Polymer |
| element for HTMLImport. element_unitest => element.js/element.html. |
| """ |
| |
| with open(output_filename, 'w') as out: |
| out.write(_HTML_FILE) |
| for dep in _process_deps(mocks, html_import, target_name): |
| out.write(dep + '\n') |
| for dep in _process_deps(deps, html_import, target_name): |
| out.write(dep + '\n') |
| |
| out.write(_HTML_FOOTER) |
| |
| |
| def main(): |
| parser = ArgumentParser() |
| parser.add_argument( |
| '-s', '--src_path', help='Path to //src/ directory', required=True) |
| parser.add_argument( |
| '-i', |
| '--input', |
| help='Input dependency file generated by js_library.py', |
| required=True) |
| parser.add_argument( |
| '-o', |
| '--output', |
| help='Generated html output with flattened dependencies', |
| required=True) |
| parser.add_argument( |
| '-m', |
| '--mocks', |
| nargs='*', |
| default=[], |
| help='List of additional js files to load before others') |
| parser.add_argument('-t', '--target_name', help='Test target name') |
| parser.add_argument( |
| '--html_import', |
| action='store_true', |
| help='Enable HTMLImports, used for Polymer elements') |
| args = parser.parse_args() |
| |
| # Append closure path to sys.path to be able to import js_unit_test. |
| sys.path.append(os.path.join(args.src_path, 'third_party/closure_compiler')) |
| from js_binary import CrawlDepsTree |
| |
| deps, _ = CrawlDepsTree([args.input]) |
| |
| return _process(deps, args.output, args.mocks, args.html_import, |
| args.target_name) |
| |
| |
| if __name__ == '__main__': |
| main() |