* it's tricky to get out of the runfiles tree with `bazel test` as `BUILD_WORKSPACE_DIRECTORY` is not set but I employed a trick to read the `DO_NOT_BUILD_HERE` file that is one level up from `execroot` and that contains the workspace directory. This is experimental and if `bazel test //:test.debug` fails than `bazel run` is still guaranteed to work as `BUILD_WORKSPACE_DIRECTORY` will be set in that context * test //integration:bazel_test and //integration:bazel-schematics_test exclusively * run "exclusive" and "manual" bazel-in-bazel integration tests in their own CI job as they take 8m+ to execute ``` //integration:bazel-schematics_test PASSED in 317.2s //integration:bazel_test PASSED in 167.8s ``` * Skip all integration tests that are now handled by angular_integration_test except the tests that are tracked for payload size; these are: - cli-hello-world* - hello_world__closure * add & pin @babel deps as newer versions of babel break //packages/localize/src/tools/test:test @babel/core dep had to be pinned to 7.6.4 or else //packages/localize/src/tools/test:test failed. Also //packages/localize uses @babel/generator, @babel/template, @babel/traverse & @babel/types so these deps were added to package.json as they were not being hoisted anymore from @babel/core transitive. NB: integration/hello_world__systemjs_umd test must run with systemjs 0.20.0 NB: systemjs must be at 0.18.10 for legacy saucelabs job to pass NB: With Bazel 2.0, the glob for the files to test `"integration/bazel/**"` is empty if integation/bazel is in .bazelignore. This glob worked under these conditions with 1.1.0. I did not bother testing with 1.2.x as not having integration/bazel in .bazelignore is correct. PR Close #33927
		
			
				
	
	
		
			199 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Npm integration testing
 | |
| """
 | |
| 
 | |
| load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_test")
 | |
| 
 | |
| # Returns the manifest path of a file: `workspace/path/to/file`
 | |
| def _to_manifest_path(ctx, file):
 | |
|     if file.short_path.startswith("../"):
 | |
|         # Strip the ../ from short_path to external repository
 | |
|         return file.short_path[3:]
 | |
|     else:
 | |
|         # Add the repository name for short_path to local repository
 | |
|         return ctx.workspace_name + "/" + file.short_path
 | |
| 
 | |
| def _npm_integration_test_config_impl(ctx):
 | |
|     if len(ctx.files.test_files) == 0:
 | |
|         fail("No files were found to run under integration testing.")
 | |
| 
 | |
|     if ctx.attr.debug:
 | |
|         for f in ctx.files.test_files:
 | |
|             if f.is_directory:
 | |
|                 fail("In debug mode, directory test_files labels not supported.")
 | |
| 
 | |
|     commands = []
 | |
|     for c in ctx.attr.commands:
 | |
|         commands.append(ctx.expand_location(c, targets = ctx.attr.data))
 | |
| 
 | |
|     # pass --define vars to test; these are added to the environment using process.env().
 | |
|     env_vars = {}
 | |
|     for k in ctx.attr.configuration_env_vars:
 | |
|         if k in ctx.var.keys():
 | |
|             env_vars[k] = ctx.var[k]
 | |
| 
 | |
|     # Serialize configuration file for test runner
 | |
|     ctx.actions.write(
 | |
|         output = ctx.outputs.config,
 | |
|         content = """// npm_integration_test runner config generated by npm_integration_test rule
 | |
| module.exports = {{
 | |
|     testFiles: [ {TMPL_test_files} ],
 | |
|     commands: [ {TMPL_commands} ],
 | |
|     npmPackages: {{ {TMPL_npm_packages} }},
 | |
|     checkNpmPackages: [ {TMPL_check_npm_packages} ],
 | |
|     envVars: {{ {TMPL_env_vars} }},
 | |
|     debug: {TMPL_debug},
 | |
| }};
 | |
| """.format(
 | |
|             TMPL_test_files = ", ".join(["'%s'" % f.short_path for f in ctx.files.test_files]),
 | |
|             TMPL_commands = ", ".join(["'%s'" % s for s in commands]),
 | |
|             TMPL_npm_packages = ", ".join(["'%s': '%s'" % (ctx.attr.npm_packages[n], n.files.to_list()[0].short_path) for n in ctx.attr.npm_packages]),
 | |
|             TMPL_check_npm_packages = ", ".join(["'%s'" % s for s in ctx.attr.check_npm_packages]),
 | |
|             TMPL_env_vars = ", ".join(["'%s': '%s'" % (k, env_vars[k]) for k in env_vars]),
 | |
|             TMPL_debug = "true" if ctx.attr.debug else "false",
 | |
|         ),
 | |
|     )
 | |
| 
 | |
|     runfiles = [ctx.outputs.config] + ctx.files.test_files + ctx.files.npm_packages
 | |
| 
 | |
|     return [DefaultInfo(runfiles = ctx.runfiles(files = runfiles))]
 | |
| 
 | |
| _NPM_INTEGRATION_TEST_CONFIG_ATTRS = {
 | |
|     "commands": attr.string_list(
 | |
|         default = [],
 | |
|         mandatory = True,
 | |
|         doc = """The list of test commands to run. Defaults to `[]`.""",
 | |
|     ),
 | |
|     "configuration_env_vars": attr.string_list(
 | |
|         doc = """Pass these configuration environment variables to the resulting test.
 | |
|         Chooses a subset of the configuration environment variables (taken from `ctx.var`), which also
 | |
|         includes anything specified via the --define flag.
 | |
|         Note, this can lead to different results for the test.""",
 | |
|         default = [],
 | |
|     ),
 | |
|     "check_npm_packages": attr.string_list(
 | |
|         doc = """A list of npm packages that should be replaced in this test.
 | |
| 
 | |
| This attribute checks that none of the npm packages lists is found in the workspace-under-test's
 | |
| package.json file unlinked to a generated npm package.
 | |
| 
 | |
| This can be used to verify that all npm package artifacts that need to be tested against are indeed
 | |
| replaced in all integration tests. For example,
 | |
| ```
 | |
| check_npm_packages = [
 | |
|     "@angular/common",
 | |
|     "@angular/compiler",
 | |
|     "@angular/compiler-cli",
 | |
|     "@angular/core",
 | |
| ],
 | |
| ```
 | |
| If an `npm_packages` replacement on any package listed is missed then the test will fail. Since listing all
 | |
| npm packages in `npm_packages` is expensive as any change will result in all integration tests re-running,
 | |
| this attribute allows a fine grained `npm_packages` per integration test with the added safety that none
 | |
| are missed for any one test.
 | |
| """,
 | |
|     ),
 | |
|     "data": attr.label_list(
 | |
|         doc = """Data dependencies for test.""",
 | |
|         allow_files = True,
 | |
|     ),
 | |
|     "debug": attr.bool(
 | |
|         doc = """Setup the test for debugging.
 | |
| 
 | |
| If set to true then the package.json replacement are done in-place instead of a tmp folder
 | |
| and the test is not run. This is used to configure the test folder for local testing and debugging.
 | |
| """,
 | |
|         default = False,
 | |
|     ),
 | |
|     "npm_packages": attr.label_keyed_string_dict(
 | |
|         doc = """A label keyed string dictionary of npm package replacements to make in the workspace-under-test's
 | |
| package.json with npm package targets. The targets should be pkg_tar tar.gz archives.
 | |
| 
 | |
| For example,
 | |
| ```
 | |
| npm_packages = {
 | |
|     "//packages/common:npm_package_archive": "@angular/common",
 | |
|     "//packages/compiler:npm_package_archive": "@angular/compiler",
 | |
|     "//packages/compiler-cli:npm_package_archive": "@angular/compiler-cli",
 | |
|     "//packages/core:npm_package_archive": "@angular/core",
 | |
| }
 | |
| ```""",
 | |
|         allow_files = True,
 | |
|     ),
 | |
|     "test_files": attr.label(
 | |
|         doc = """A filegroup of all files necessary to run the test.""",
 | |
|         allow_files = True,
 | |
|     ),
 | |
| }
 | |
| 
 | |
| _npm_integration_test_config = rule(
 | |
|     implementation = _npm_integration_test_config_impl,
 | |
|     doc = """Generates an npm_integration_test config.""",
 | |
|     attrs = _NPM_INTEGRATION_TEST_CONFIG_ATTRS,
 | |
|     outputs = {
 | |
|         "config": "%{name}.js",
 | |
|     },
 | |
| )
 | |
| 
 | |
| def npm_integration_test(name, **kwargs):
 | |
|     """Runs an npm integration test.
 | |
| 
 | |
|     See _NPM_INTEGRATION_TEST_CONFIG_ATTRS above for configuration arguments.
 | |
|     """
 | |
|     commands = kwargs.pop("commands", [])
 | |
|     configuration_env_vars = kwargs.pop("configuration_env_vars", [])
 | |
|     check_npm_packages = kwargs.pop("check_npm_packages", [])
 | |
|     npm_packages = kwargs.pop("npm_packages", {})
 | |
|     test_files = kwargs.pop("test_files", [])
 | |
|     data = kwargs.pop("data", [])
 | |
| 
 | |
|     _npm_integration_test_config(
 | |
|         name = name + ".config",
 | |
|         commands = commands,
 | |
|         configuration_env_vars = configuration_env_vars,
 | |
|         check_npm_packages = check_npm_packages,
 | |
|         data = data,
 | |
|         npm_packages = npm_packages,
 | |
|         test_files = test_files,
 | |
|         visibility = ["//visibility:private"],
 | |
|         tags = ["manual"],
 | |
|         testonly = True,
 | |
|     )
 | |
| 
 | |
|     # Config for debug target below
 | |
|     _npm_integration_test_config(
 | |
|         name = name + ".debug.config",
 | |
|         commands = commands,
 | |
|         configuration_env_vars = configuration_env_vars,
 | |
|         check_npm_packages = check_npm_packages,
 | |
|         data = data,
 | |
|         npm_packages = npm_packages,
 | |
|         test_files = test_files,
 | |
|         debug = True,
 | |
|         visibility = ["//visibility:private"],
 | |
|         tags = ["manual"],
 | |
|         testonly = True,
 | |
|     )
 | |
| 
 | |
|     tags = kwargs.pop("tags", [])
 | |
|     npm_deps = ["@npm//tmp"]
 | |
| 
 | |
|     nodejs_test(
 | |
|         name = name,
 | |
|         data = data + npm_deps + [":%s.config" % name, ":%s.config.js" % name],
 | |
|         tags = tags,
 | |
|         templated_args = ["$(location :%s.config.js)" % name],
 | |
|         entry_point = "//tools/npm_integration_test:test_runner.js",
 | |
|         **kwargs
 | |
|     )
 | |
| 
 | |
|     # Setup a .debug target that sets the debug attribute to True.
 | |
|     # This target must be run with `bazel run` so it is tagged manual.
 | |
|     nodejs_test(
 | |
|         name = name + ".debug",
 | |
|         data = data + npm_deps + [":%s.debug.config" % name, ":%s.debug.config.js" % name],
 | |
|         tags = tags + ["manual", "local"],
 | |
|         templated_args = ["$(location :%s.debug.config.js)" % name],
 | |
|         entry_point = "//tools/npm_integration_test:test_runner.js",
 | |
|         **kwargs
 | |
|     )
 |