From 71e0df039c60a76ac6a27108fb879cb7c4d91954 Mon Sep 17 00:00:00 2001 From: mrmeku Date: Mon, 9 Apr 2018 00:53:31 -0600 Subject: [PATCH] feat(bazel): Initial commit of protractor_web_test_suite (#24787) Co-authored-by: Andrew Z Allen PR Close #24787 --- BUILD.bazel | 1 + WORKSPACE | 10 ++ packages/bazel/index.bzl | 2 + packages/bazel/src/protractor/BUILD.bazel | 4 + packages/bazel/src/protractor/conf.js.tmpl | 14 +++ .../bazel/src/protractor/protractor_runner.js | 23 ++++ .../protractor/protractor_web_test_suite.bzl | 107 ++++++++++++++++++ packages/bazel/test/protractor/BUILD.bazel | 14 +++ packages/bazel/test/protractor/conf.js | 29 +++++ packages/bazel/test/protractor/test.spec.ts | 20 ++++ 10 files changed, 224 insertions(+) create mode 100644 packages/bazel/src/protractor/BUILD.bazel create mode 100644 packages/bazel/src/protractor/conf.js.tmpl create mode 100644 packages/bazel/src/protractor/protractor_runner.js create mode 100644 packages/bazel/src/protractor/protractor_web_test_suite.bzl create mode 100644 packages/bazel/test/protractor/BUILD.bazel create mode 100644 packages/bazel/test/protractor/conf.js create mode 100644 packages/bazel/test/protractor/test.spec.ts diff --git a/BUILD.bazel b/BUILD.bazel index 1c040afea2..e1bbba720c 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -22,6 +22,7 @@ node_modules_filegroup( "jasmine", "minimist", "protobufjs", + "protractor", "reflect-metadata", "source-map-support", "tsickle", diff --git a/WORKSPACE b/WORKSPACE index ef86aed344..ccd1b3d331 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -11,6 +11,12 @@ http_archive( sha256 = "634206524d90dc03c52392fa3f19a16637d2bcf154910436fe1d669a0d9d7b9c", ) +http_archive( + name = "bazel_gazelle", + sha256 = "d03625db67e9fb0905bbd206fa97e32ae9da894fe234a493e7517fd25faec914", + url = "https://github.com/bazelbuild/bazel-gazelle/releases/download/0.10.1/bazel-gazelle-0.10.1.tar.gz", +) + http_archive( name = "io_bazel_rules_webtesting", url = "https://github.com/bazelbuild/rules_webtesting/archive/v0.2.0.zip", @@ -85,6 +91,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_too go_rules_dependencies() go_register_toolchains() +load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") + +gazelle_dependencies() + load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories") web_test_repositories() diff --git a/packages/bazel/index.bzl b/packages/bazel/index.bzl index 33cefabcda..247618070e 100644 --- a/packages/bazel/index.bzl +++ b/packages/bazel/index.bzl @@ -9,6 +9,8 @@ Users should not load files under "/src" load("//packages/bazel/src:ng_module.bzl", _ng_module = "ng_module") load("//packages/bazel/src/ng_package:ng_package.bzl", _ng_package = "ng_package") +load("//packages/bazel/src/protractor:protractor_web_test_suite.bzl", _protractor_web_test_suite = "protractor_web_test_suite") ng_module = _ng_module ng_package = _ng_package +protractor_web_test_suite = _protractor_web_test_suite diff --git a/packages/bazel/src/protractor/BUILD.bazel b/packages/bazel/src/protractor/BUILD.bazel new file mode 100644 index 0000000000..e3be3b819b --- /dev/null +++ b/packages/bazel/src/protractor/BUILD.bazel @@ -0,0 +1,4 @@ +exports_files([ + "conf.js.tmpl", + "protractor_runner.js", +]) diff --git a/packages/bazel/src/protractor/conf.js.tmpl b/packages/bazel/src/protractor/conf.js.tmpl new file mode 100644 index 0000000000..76dc1574db --- /dev/null +++ b/packages/bazel/src/protractor/conf.js.tmpl @@ -0,0 +1,14 @@ +const baseConf = require("BASE_CONF_IMPORT_PATH"); + +exports.config = { + ...baseConf.config, + framework: "jasmine2", + seleniumAddress: process.env.WEB_TEST_HTTP_SERVER.trim() + "/wd/hub", + specs: [ + SPEC_FILE_IMPORT_PATHS + ].map(specPath => require.resolve(specPath)), + // TODO: Allow users to specifify other browsers. + capabilities: { + browserName: "chrome" + }, +}; diff --git a/packages/bazel/src/protractor/protractor_runner.js b/packages/bazel/src/protractor/protractor_runner.js new file mode 100644 index 0000000000..095373953f --- /dev/null +++ b/packages/bazel/src/protractor/protractor_runner.js @@ -0,0 +1,23 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + * + * @fileoverview A wrapper around the protractor cli for bazel compatibility. + */ + +const launcher = require('protractor/built/launcher'); + +function main(args) { + if (!args.length) { + throw new Error('Config file argument missing'); + } + const config = require.resolve(args[0]); + launcher.init(config); +} + +if (require.main === module) { + process.exitCode = main(process.argv.slice(2)); +} diff --git a/packages/bazel/src/protractor/protractor_web_test_suite.bzl b/packages/bazel/src/protractor/protractor_web_test_suite.bzl new file mode 100644 index 0000000000..8b8de712c7 --- /dev/null +++ b/packages/bazel/src/protractor/protractor_web_test_suite.bzl @@ -0,0 +1,107 @@ +# Copyright Google Inc. All Rights Reserved. +# +# Use of this source code is governed by an MIT-style license that can be +# found in the LICENSE file at https://angular.io/license +"""Implementation of the protractor_web_test_suite rule. +""" + +load("@io_bazel_rules_webtesting//web:web.bzl", "web_test_suite") +load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary") +load("@build_bazel_rules_nodejs//internal/common:sources_aspect.bzl", "sources_aspect") +load("@build_bazel_rules_nodejs//internal/common:module_mappings.bzl", "module_mappings_runtime_aspect") + +def _modify_tsconfig_impl(ctx): + spec_file_import_paths = [] + for dep in ctx.attr.deps: + # For each transitive ES5 dependency, grab the short path + for f in dep.node_sources.to_list(): + spec_file_import_paths.append("\"{workspace}/{path}\"".format(workspace=ctx.workspace_name, path=f.short_path)) + + ctx.actions.expand_template( + template = ctx.file._conf_templ, + output = ctx.outputs._modified_conf, + substitutions = { + "BASE_CONF_IMPORT_PATH": "{workspace}/{path}".format(workspace=ctx.workspace_name, path=ctx.file.base_conf.short_path), + "SPEC_FILE_IMPORT_PATHS": ',\n '.join(spec_file_import_paths), + }) + +_modify_conf = rule( + attrs = { + "base_conf": attr.label( + doc = """conf.js file used to configure protractor.""", + allow_single_file = True, + cfg = "data", + aspects = [ + sources_aspect, + module_mappings_runtime_aspect, + ], + ), + "deps": attr.label_list( + doc = """Spec and page files used for testing.""", + allow_files = True, + cfg = "data", + aspects = [ + sources_aspect, + module_mappings_runtime_aspect, + ], + ), + "_conf_templ": attr.label( + allow_files = True, + single_file = True, + default = Label("@angular//packages/bazel/src/protractor:conf.js.tmpl"), + ), + }, + outputs = { + "_modified_conf": "%{name}.conf.js", + }, + implementation = _modify_tsconfig_impl, +) + +def protractor_web_test_suite(name, conf, deps, data = [], **kwargs): + """Runs protractor using the passed conf.js file and tests listed within deps. + + Args: + name: The name of the web_test_suite rule the macro expands into. + conf: A conf.js file to be used as a base template. The following fields of the base + config are overridden: + framework + seleniumAddress + specs + capabilities + deps: A list of dependencies containing the test files to run within protractor. + data: Any runtime files which are needed to run the test suite. + **kwargs: Any other arguements are passed directory to the expanded web_test_suite rule. + + Returns: + This macro expands into a web_test_suite rule which runs the protractor tests. + """ + + _modify_conf_name = "%s_modify_conf" % name + _modify_conf( + name = _modify_conf_name, + base_conf = conf, + deps = deps, + testonly = True, + ) + + _modified_conf = "%s.conf.js" % _modify_conf_name + + _protractor_runner_name = name + "_protractor_runner" + nodejs_binary( + name = _protractor_runner_name, + entry_point = "angular/packages/bazel/src/protractor/protractor_runner.js", + data = data + deps + [_modified_conf, "@angular//packages/bazel/src/protractor:protractor_runner.js"], + templated_args = ["$(location :%s)" % _modified_conf], + tags = ["manual"], + testonly = True, + ) + + web_test_suite( + name = name, + # TODO: Allow users to specify more browsers. Currently conf.js is hardcoded for chrome. + browsers = ["@io_bazel_rules_webtesting//browsers:chromium-local"], + data = data + deps + [conf, _modified_conf], + test = ":%s_bin" % _protractor_runner_name, + testonly = True, + **kwargs + ) diff --git a/packages/bazel/test/protractor/BUILD.bazel b/packages/bazel/test/protractor/BUILD.bazel new file mode 100644 index 0000000000..fe9ef9e9ec --- /dev/null +++ b/packages/bazel/test/protractor/BUILD.bazel @@ -0,0 +1,14 @@ +load("//packages/bazel:index.bzl", "protractor_web_test_suite") +load("@build_bazel_rules_typescript//:defs.bzl", "ts_library") + +ts_library( + name = "ts_spec", + testonly = True, + srcs = ["test.spec.ts"], +) + +protractor_web_test_suite( + name = "demo", + conf = "conf.js", + deps = [":ts_spec"], +) diff --git a/packages/bazel/test/protractor/conf.js b/packages/bazel/test/protractor/conf.js new file mode 100644 index 0000000000..2ac5a3ce80 --- /dev/null +++ b/packages/bazel/test/protractor/conf.js @@ -0,0 +1,29 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +/** + * @fileoverview A demo of what a user's conf.js file might look like. + */ +const http = require('http'); + +const PORT = 3000; + +exports.config = { + baseUrl: `http://localhost:${PORT}`, + onPrepare() { + const app = new http.Server(); + + app.on('request', (req, res) => { + res.writeHead(200, {'Content-Type': 'text/plain'}); + res.write('Hello World'); + res.end('\n'); + }); + + return new Promise(resolve => { app.listen(PORT, () => { resolve(); }); }); + } +}; diff --git a/packages/bazel/test/protractor/test.spec.ts b/packages/bazel/test/protractor/test.spec.ts new file mode 100644 index 0000000000..139fd3c98d --- /dev/null +++ b/packages/bazel/test/protractor/test.spec.ts @@ -0,0 +1,20 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + * + * @fileoverview A small demo of how to run a protractor test. + */ + +import {$, browser} from 'protractor'; + +describe('Basic test', () => { + it('should say hello world', () => { + browser.waitForAngularEnabled(false); + browser.get('/'); + + expect($('body').getText()).toContain('Hello World'); + }); +});