Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
"bazel:buildifier": "find . -type f \\( -name \"*.bzl\" -or -name WORKSPACE -or -name BUILD -or -name BUILD.bazel \\) ! -path \"*/node_modules/*\" | xargs buildifier -v --warnings=attr-cfg,attr-license,attr-non-empty,attr-output-default,attr-single-file,constant-glob,ctx-args,depset-iteration,depset-union,dict-concatenation,duplicated-name,filetype,git-repository,http-archive,integer-division,load,load-on-top,native-build,native-package,output-group,package-name,package-on-top,redefined-variable,repository-name,same-origin-load,string-iteration,unused-variable,unsorted-dict-items,out-of-order-load",
"bazel:format-lint": "yarn -s bazel:buildifier --lint=warn --mode=check",
"dev-app": "ibazel run //src/dev-app:devserver",
"test": "bazel test //src/... --test_tag_filters=-e2e,-browser:firefox-local --build_tag_filters=-browser:firefox-local --build_tests_only",
"test-firefox": "bazel test //src/... --test_tag_filters=-e2e,-browser:chromium-local --build_tag_filters=-browser:chromium-local --build_tests_only",
"test": "node ./scripts/run-component-tests.js",
"test-local": "yarn -s test --local",
"test-firefox": "yarn -s test --firefox",
"lint": "yarn -s tslint && yarn -s bazel:format-lint && yarn -s ownerslint",
"e2e": "bazel test //src/... --test_tag_filters=e2e",
"deploy-dev-app": "node ./scripts/deploy-dev-app.js",
Expand Down
107 changes: 107 additions & 0 deletions scripts/run-component-tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/env node

/**
* Script that simplifies the workflow of running unit tests for a component
* using Bazel. Here are a few examples:
*
* node ./scripts/run-component-tests button | Runs Material button tests
* node ./scripts/run-component-tests overlay | Runs CDK overlay tests
* node ./scripts/run-component-tests src/cdk/a11y | Runs CDK a11y tests
* node ./scripts/run-component-tests a11y overlay | Runs CDK a11y and overlay tests
*
* Supported command line flags:
*
* --local | If specified, no browser will be launched.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this the default? Then invert the flag to something like --no-headless

Copy link
Member Author

@devversion devversion Jan 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that we do not run any browser by default? (asking because the --local flag does this and you commented on that flag).

If you meant that we run Chrome in non-headless mode by default: I don't think we have a way to launch Chrome through Bazel without headless (it seems to depend on the $DISPLAY env variable).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want the command to not pop open a browser window but to also run the tests without having to manually open the page (but you can still open the debug page if you need to)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is possible. The @bazel/karma rules decide based on the platform environment whether the browser runs in headless or non-headless mode. For me on Windows, it always runs headless.

* --firefox | Instead of Chrome being used for tests, Firefox will be used.
* --no-watch | Watch mode is enabled by default. This flag opts-out to standard Bazel.
*/

const minimist = require('minimist');
const shelljs = require('shelljs');
const chalk = require('chalk');
const path = require('path');
const args = process.argv.slice(2);

// Path to the project directory.
const projectDir = path.join(__dirname, '../');

// Path to the directory that contains all packages.
const packagesDir = path.join(projectDir, 'src/');

// List of packages where the specified component could be defined in. The script uses the
// first package that contains the component (if no package is specified explicitly).
// e.g. "button" will become "material/button", and "overlay" becomes "cdk/overlay".
const orderedGuessPackages = ['material', 'cdk', 'material-experimental', 'cdk-experimental'];

// ShellJS should exit if any command fails.
shelljs.set('-e');
shelljs.cd(projectDir);

// Extracts the supported command line options.
const {_: components, local, firefox, watch} = minimist(args, {
boolean: ['local', 'firefox', 'watch'],
default: {watch: true},
});

// Exit if no component has been specified.
if (!components.length) {
console.error(chalk.red(
'No component specified. Specify a component name, or pass a ' +
'path to the component directory.'));
process.exit(1);
}

// We can only run a single target with "--local". Running multiple targets within the
// same Karma server is not possible since each test target runs isolated from the others.
if (local && components.length > 1) {
console.error(chalk.red(
'Unable to run multiple components tests in local mode. ' +
'Only one component at a time can be run with "--local"'));
process.exit(1);
}

const bazelBinary = watch ? 'ibazel' : 'bazel';
const bazelAction = local ? 'run' : 'test';
const testTargetName =
`unit_tests_${local ? 'local' : firefox ? 'firefox-local' : 'chromium-local'}`;
const testLabels = components.map(t => `${getBazelPackageOfComponentName(t)}:${testTargetName}`);

// Runs Bazel for the determined test labels.
shelljs.exec(`yarn -s ${bazelBinary} ${bazelAction} ${testLabels.join(' ')}`);

/**
* Gets the Bazel package label for the specified component name. Throws if
* the component could not be resolved to a Bazel package.
*/
function getBazelPackageOfComponentName(name) {
// Before guessing any Bazel package, we test if the name contains the
// package name already. If so, we just use that for Bazel package.
const targetName = convertPathToBazelLabel(name);
if (targetName !== null) {
return targetName;
}
// If the name does not contain an explicit package name, we try guessing the
// package name by walking through an ordered list of possible packages and checking
// if a package contains a component with the given name. The first match will be used.
for (let guessPackage of orderedGuessPackages) {
const guessTargetName = convertPathToBazelLabel(path.join(packagesDir, guessPackage, name));
if (guessTargetName !== null) {
return guessTargetName;
}
}
throw Error(chalk.red(`Could not find test target for specified component: ` +
`${chalk.yellow(name)}. Looked in packages: ${orderedGuessPackages.join(', ')}`));
}

/** Converts a path to a Bazel label. */
function convertPathToBazelLabel(name) {
if (shelljs.test('-d', name)) {
return `//${convertPathToPosix(path.relative(projectDir, name))}`;
}
return null;
}

/** Converts an arbitrary path to a Posix path. */
function convertPathToPosix(pathName) {
return pathName.replace(/\\/g, '/');
}
2 changes: 2 additions & 0 deletions tools/defaults.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ def ng_web_test_suite(deps = [], static_css = [], bootstrap = [], tags = [], **k
"//test:angular_test_init",
] + deps,
browsers = [
# Note: when changing the browser names here, also update the "yarn test"
# script to reflect the new browser names.
"@io_bazel_rules_webtesting//browsers:chromium-local",
"@io_bazel_rules_webtesting//browsers:firefox-local",
],
Expand Down