Skip to content

Commit 5a58030

Browse files
applmakalexeagle
authored andcommitted
fix(karma): allow custom browsers to specify args (fixes #595)
Today, the args as specified in the various manifests of the rules_webtesting browsers never make it into the generated karma.conf.js. This results in these arguments never being used when launching Chrome, preventing customization of browsers such as window size, enabling remote debugging, or other flag-based options. This PR fixes this by reading those arguments from the manifest, and adding them to the browsers list in the generated karma.conf.js. Also, this PR includes a change to generated_file_test to allow a golden file to represent a substring of the generated output. Also Also: This PR includes a golden file test that verified that the generated karma.conf.js does read in the specified value. Furthermore, the effect of this can be verified manually via: ``` VERBOSE_LOGS=1 bazel run packages/karma/test/karma:testing_custom_chrome ``` Note the appearance of the additional flags in the new debug output.
1 parent 2923766 commit 5a58030

8 files changed

Lines changed: 100 additions & 20 deletions

File tree

.bazelci/presubmit.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ tasks:
3232
# on bazelci apt-get fails with permission denied and there is no sudo
3333
# command to switch to root.
3434
# TODO(gregmagolan): figure out how to install missing shared libs
35-
- "--test_tag_filters=-e2e,-examples,-manual,-browser:chromium-local,-browser:firefox-local,-cypress"
35+
- "--test_tag_filters=-e2e,-examples,-manual,-browser:chromium-local,-browser:firefox-local,-browser:custom_chrome,-cypress"
3636
test_targets:
3737
- "//..."
3838
# //internal/node/test:nodejs_toolchain_linux_amd64_test is a "manual" test that must be run
@@ -137,7 +137,7 @@ tasks:
137137
# on bazelci apt-get fails with permission denied and there is no sudo
138138
# command to switch to root.
139139
# TODO(gregmagolan): figure out how to install missing shared libs
140-
- "--test_tag_filters=-e2e,-examples,-manual,-browser:chromium-local,-browser:firefox-local,-cypress"
140+
- "--test_tag_filters=-e2e,-examples,-manual,-browser:chromium-local,-browser:firefox-local,-browser:custom_chrome,-cypress"
141141
test_targets:
142142
- "//..."
143143
# //internal/node/test:nodejs_toolchain_linux_amd64_test is a "manual" test that must be run
@@ -158,7 +158,7 @@ tasks:
158158
# on bazelci apt-get fails with permission denied and there is no sudo
159159
# command to switch to root.
160160
# TODO(gregmagolan): figure out how to install missing shared libs
161-
- "--test_tag_filters=-e2e,-examples,-manual,-browser:chromium-local,-browser:firefox-local,-cypress"
161+
- "--test_tag_filters=-e2e,-examples,-manual,-browser:chromium-local,-browser:firefox-local,-browser:custom_chrome,-cypress"
162162
test_targets:
163163
- "//..."
164164
ubuntu1804_e2e:

internal/generated_file_test/bin.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,23 @@ const path = require('path');
44
import * as unidiff from 'unidiff/unidiff';
55
const runfiles = require(process.env['BAZEL_NODE_RUNFILES_HELPER']);
66

7+
function findGoldenInGenerated(golden, actual) {
8+
const goldenLines = golden.split(/[\r\n]+/g).map(l => l.trim());
9+
const actualLines = actual.split(/[\r\n]+/g).map(l => l.trim());
10+
// Note: this is not the fastest subsequence algorithm.
11+
nextActualLine: for (let i = 0; i < actualLines.length; i++) {
12+
for (let j = 0; j < goldenLines.length; j++) {
13+
if (actualLines[i + j] !== goldenLines[j]) {
14+
continue nextActualLine;
15+
}
16+
}
17+
// A match!
18+
return true;
19+
}
20+
// No match.
21+
return false;
22+
}
23+
724
function main(args) {
825
const [mode, golden_no_debug, golden_debug, actual] = args;
926
const actualPath = runfiles.resolveWorkspaceRelative(actual);
@@ -23,7 +40,7 @@ function main(args) {
2340
return 0;
2441
}
2542
if (mode === '--verify') {
26-
// Generated does not match golden
43+
// Compare the generated file to the golden file.
2744
const diff = unidiff.diffLines(goldenContents, actualContents);
2845
let prettyDiff =
2946
unidiff.formatLines(diff, {aname: `[workspace]/${golden}`, bname: `[bazel-out]/${actual}`});
@@ -41,6 +58,19 @@ If the bazel-out content is correct, you can update the workspace file by runnin
4158
`);
4259
return 1;
4360
}
61+
if (mode === '--substring') {
62+
// Verify that the golden file is contained _somewhere_ in the generated
63+
// file.
64+
const diff = findGoldenInGenerated(goldenContents, actualContents);
65+
if (diff) {
66+
console.error(`Unable to find golden contents inside of the the generated file:
67+
68+
${goldenContents}
69+
`)
70+
return 1;
71+
}
72+
return 0;
73+
}
4474
throw new Error('unknown mode', mode);
4575
}
4676

internal/generated_file_test/generated_file_test.bzl

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
load("@build_bazel_rules_nodejs//internal/node:node.bzl", "nodejs_binary", "nodejs_test")
44

5-
def generated_file_test(name, generated, src, src_dbg = None, **kwargs):
5+
def generated_file_test(name, generated, src, substring_search = False, src_dbg = None, **kwargs):
66
"""Tests that a file generated by Bazel has identical content to a file in the workspace.
77
88
This is useful for testing, where a "snapshot" or "golden" file is checked in,
@@ -12,6 +12,8 @@ def generated_file_test(name, generated, src, src_dbg = None, **kwargs):
1212
name: Name of the rule.
1313
generated: a Label of the output file generated by another rule
1414
src: Label of the source file in the workspace
15+
substring_search: When true, creates a test that will fail only if the golden file is not found
16+
anywhere within the generated file. Note that the .update rule is not generated in substring mode.
1517
src_dbg: if the build uses `--compilation_mode dbg` then some rules will produce different output.
1618
In this case you can specify what the dbg version of the output should look like
1719
**kwargs: extra arguments passed to the underlying nodejs_test or nodejs_binary
@@ -27,16 +29,22 @@ def generated_file_test(name, generated, src, src_dbg = None, **kwargs):
2729
nodejs_test(
2830
name = name,
2931
entry_point = "@build_bazel_rules_nodejs//internal/generated_file_test:bundle.js",
30-
templated_args = ["--verify", loc % src, loc % src_dbg, loc % generated],
32+
templated_args = [
33+
"--substring" if substring_search else "--verify",
34+
loc % src,
35+
loc % src_dbg,
36+
loc % generated,
37+
],
3138
data = data,
3239
**kwargs
3340
)
3441

35-
nodejs_binary(
36-
name = name + ".update",
37-
testonly = True,
38-
entry_point = "@build_bazel_rules_nodejs//internal/generated_file_test:bundle.js",
39-
templated_args = ["--out", loc % src, loc % src_dbg, loc % generated],
40-
data = data,
41-
**kwargs
42-
)
42+
if not substring_search:
43+
nodejs_binary(
44+
name = name + ".update",
45+
testonly = True,
46+
entry_point = "@build_bazel_rules_nodejs//internal/generated_file_test:bundle.js",
47+
templated_args = ["--out", loc % src, loc % src_dbg, loc % generated],
48+
data = data,
49+
**kwargs
50+
)

packages/karma/karma.conf.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,13 +321,23 @@ try {
321321
webTestNamedFiles['CHROMIUM']}' in runfiles`);
322322
}
323323
}
324+
// Read any additional chrome options (as specified by the
325+
// rules_webtesting manifest).
326+
const chromeOptions = (webTestMetadata['capabilities'] || {})['goog:chromeOptions'];
327+
const additionalArgs = (chromeOptions ? chromeOptions['args'] : []).filter(arg => {
328+
// We never want to 'run' Chrome in headless mode.
329+
return arg != '--headless';
330+
});
324331
const browser = process.env['DISPLAY'] ? 'Chrome' : 'ChromeHeadless';
325332
if (!supportChromeSandboxing()) {
326333
const launcher = 'CustomChromeWithoutSandbox';
327-
conf.customLaunchers = {[launcher]: {base: browser, flags: ['--no-sandbox']}};
334+
conf.customLaunchers =
335+
{[launcher]: {base: browser, flags: ['--no-sandbox', ...additionalArgs]}};
328336
conf.browsers.push(launcher);
329337
} else {
330-
conf.browsers.push(browser);
338+
const launcher = 'CustomChrome';
339+
conf.customLaunchers = {[launcher]: {base: browser, flags: additionalArgs}};
340+
conf.browsers.push(launcher);
331341
}
332342
}
333343
if (webTestNamedFiles['FIREFOX']) {

packages/karma/karma_web_test.bzl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,7 @@ def _find_dep(ctx, suffix):
120120

121121
# Generates the karma configuration file for the rule
122122
def _write_karma_config(ctx, files, amd_names_shim):
123-
configuration = ctx.actions.declare_file(
124-
"%s.conf.js" % ctx.label.name,
125-
sibling = ctx.outputs.executable,
126-
)
123+
configuration = ctx.outputs.configuration
127124

128125
config_file = None
129126

@@ -325,6 +322,9 @@ _karma_web_test = rule(
325322
test = True,
326323
executable = True,
327324
attrs = KARMA_WEB_TEST_ATTRS,
325+
outputs = {
326+
"configuration": "%{name}.conf.js",
327+
},
328328
)
329329

330330
def karma_web_test(

packages/karma/test/karma/BUILD.bazel

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
load("@build_bazel_rules_nodejs//:index.bzl", "generated_file_test")
16+
load("@io_bazel_rules_webtesting//web:web.bzl", "custom_browser")
1517
load("//packages/karma:index.bzl", "karma_web_test_suite")
1618

1719
karma_web_test_suite(
@@ -26,6 +28,7 @@ karma_web_test_suite(
2628
browsers = [
2729
"@io_bazel_rules_webtesting//browsers:chromium-local",
2830
"@io_bazel_rules_webtesting//browsers:firefox-local",
31+
":custom_chrome",
2932
],
3033
static_files = [
3134
"unnamed-amd-module.js",
@@ -41,3 +44,16 @@ karma_web_test_suite(
4144
"requirejs-config.js",
4245
],
4346
)
47+
48+
custom_browser(
49+
name = "custom_chrome",
50+
browser = "@io_bazel_rules_webtesting//browsers:chromium-local",
51+
metadata = "custom_chrome.json",
52+
)
53+
54+
generated_file_test(
55+
name = "test_custom_chrome_karma_conf",
56+
src = "karma.conf.js.golden",
57+
generated = "testing_wrapped_test.conf.js",
58+
substring_search = True,
59+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"capabilities": {
3+
"goog:chromeOptions": {
4+
"args": [
5+
"--remote-debugging-port=9222",
6+
"--headless",
7+
"--use-gl=swiftshader-webgl"
8+
]
9+
}
10+
}
11+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const chromeOptions = (webTestMetadata['capabilities'] || {})['goog:chromeOptions'];
2+
const additionalArgs = (chromeOptions ? chromeOptions['args'] : []).filter(arg => {
3+
// We never want to 'run' Chrome in headless mode.
4+
return arg != '--headless';
5+
});

0 commit comments

Comments
 (0)