Skip to content

Commit

Permalink
build: set up a bootstrap script for all jasmine tests which ensures …
Browse files Browse the repository at this point in the history
…that the temp directory is cleared

Creating a bootstrap script for jasmine tests allows us to ensure automatically for all
jasmine tests that the temporary directory created for the test runs is cleaned between specs.
  • Loading branch information
josephperrott committed Sep 8, 2021
1 parent 405f2b3 commit dbc0cd7
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 11 deletions.
24 changes: 22 additions & 2 deletions ng-dev/utils/testing/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ load("//tools:defaults.bzl", "ts_library")

ts_library(
name = "testing",
srcs = glob(["*.ts"]),
visibility = ["//ng-dev:__subpackages__"],
srcs = glob(
["*.ts"],
exclude = ["bazel-env.ts"],
),
visibility = [
"//ng-dev:__subpackages__",
],
deps = [
":bazel-env",
"//ng-dev/utils",
"@npm//@types/jasmine",
"@npm//@types/node",
Expand All @@ -15,3 +21,17 @@ ts_library(
"@npm//yargs",
],
)

ts_library(
name = "bazel-env",
srcs = [
"bazel-env.ts",
],
visibility = [
"//ng-dev/utils/testing:__subpackages__",
"//tools/jasmine:__subpackages__",
],
deps = [
"@npm//@types/node",
],
)
12 changes: 12 additions & 0 deletions ng-dev/utils/testing/bazel-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {existsSync, mkdirSync, rmSync} from 'fs';
import {join} from 'path';

/**
Expand All @@ -14,3 +15,14 @@ import {join} from 'path';
* chmod, or otherwise alter [TEST_TMPDIR]," so a subdirectory path is used to be created/destroyed.
*/
export const testTmpDir: string = join(process.env['TEST_TMPDIR']!, 'dev-infra');

/**
* Prepares the temporary test directory, deleting previous contents if present. Ensures the temp
* directory exists.
*/
export function cleanTestTmpDir() {
if (existsSync(testTmpDir)) {
rmSync(testTmpDir, {recursive: true});
}
mkdirSync(testTmpDir);
}
11 changes: 2 additions & 9 deletions tools/defaults.bzl
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
load("@npm//@bazel/jasmine:index.bzl", _jasmine_node_test = "jasmine_node_test")
load("@npm//@bazel/typescript:index.bzl", _ts_library = "ts_library", _ts_project = "ts_project")
load("@npm//@bazel/esbuild:index.bzl", _esbuild = "esbuild")
load("@build_bazel_rules_nodejs//:index.bzl", "generated_file_test", _pkg_npm = "pkg_npm")
load("//tools/jasmine:jasmine.bzl", _jasmine_node_test = "jasmine_node_test")

def jasmine_node_test(name, specs = [], **kwargs):
_jasmine_node_test(
name = name,
srcs = kwargs.pop("srcs", []) + specs,
deps = kwargs.pop("deps", []),
use_direct_specs = True,
**kwargs
)
jasmine_node_test = _jasmine_node_test

def ts_project(**kwargs):
_ts_project(
Expand Down
50 changes: 50 additions & 0 deletions tools/jasmine/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("//tools:defaults.bzl", "jasmine_node_test")

ts_library(
name = "bootstrap_ts",
testonly = True,
srcs = [
"bootstrap.ts",
],
visibility = ["//visibility:public"],
deps = [
"//ng-dev/utils/testing:bazel-env",
"@npm//@bazel/jasmine",
"@npm//@types/jasmine",
],
)

alias(
name = "bootstrap_dependencies",
actual = "//ng-dev/utils/testing:bazel-env",
visibility = ["//visibility:public"],
)

filegroup(
name = "bootstrap",
testonly = True,
srcs = [":bootstrap_ts"],
output_group = "es5_sources",
visibility = ["//visibility:public"],
)

ts_library(
name = "bootstrap_test",
testonly = True,
srcs = [
"bootstrap.spec.ts",
],
deps = [
":bootstrap_ts",
"//ng-dev/utils/testing:bazel-env",
"@npm//@types/node",
],
)

jasmine_node_test(
name = "test",
specs = [
":bootstrap_test",
],
)
44 changes: 44 additions & 0 deletions tools/jasmine/bootstrap.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @license
* Copyright Google LLC 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
*/

import {readFileSync, writeFileSync} from 'fs';
import {join} from 'path';
import {testTmpDir} from '../../ng-dev/utils/testing/bazel-env';

describe('bootstraping script', () => {
// This specific describe block is explicitly testing that
jasmine.getEnv().configure({
...jasmine.getEnv().configuration(),
random: false,
});

/** A randomized string to write into the file to confirm it was removed. */
const testContent = `This is random: ${Math.random()}`;
/** The absolute path to a file within the temporary test directory. */
const testFilePath = join(testTmpDir, 'test-file');
/** The number of tests which have run within the describe block. */
let testCount = 0;

it('allows files in the temp directory to be modified', () => {
// The postfix increment operator is used to check the current value, while incrementing by 1.
expect(testCount++).toBe(0);
// Write the test content to the a file in the temporary test directory.
writeFileSync(testFilePath, testContent);

expect(readFileSync(testFilePath, {encoding: 'utf8'})).toBe(testContent);
});

it('ensures the files created in previous tests are not kept between specs', () => {
// The postfix increment operator is used to check the current value, while incrementing by 1.
expect(testCount++).toBe(1);
/** A matcher for a file not existing at the path provided. */
const errorMatcher = new RegExp(/^ENOENT\: no such file or directory, open/);

expect(() => readFileSync(testFilePath, {encoding: 'utf8'})).toThrowError(errorMatcher);
});
});
25 changes: 25 additions & 0 deletions tools/jasmine/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @license
* Copyright Google LLC 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
*/
import {cleanTestTmpDir} from '../../ng-dev/utils/testing/bazel-env';

/**
* The `boot` utility function from `@bazel/jasmine` allows initialization before the runner, with
* protections to prevent calling `boot` again.
*/
const {boot} = require('@bazel/jasmine');

// Initialize jasmine, because beforeEach and other jasmine "globals" are not defined in the
// environment until jasmine has been initialized. Since our bootstrap explicitly is meant to use
// these globals, we need to ensure that jasmine has already initialized before the major content
// of our script executes.
boot();

beforeEach(() => {
// Before each spec runs, clean the temporary test dir to prevent specs from effecting each other.
cleanTestTmpDir();
});
21 changes: 21 additions & 0 deletions tools/jasmine/jasmine.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
load("@npm//@bazel/jasmine:index.bzl", _jasmine_node_test = "jasmine_node_test")

def jasmine_node_test(name, specs = [], **kwargs):
templated_args = kwargs.pop("templated_args", []) + [
# Include our jasmime bootstrap file to be run before the jasmine runner.
"--node_options=--require=$$(rlocation $(rootpath //tools/jasmine:bootstrap))",
]

_jasmine_node_test(
name = name,
srcs = kwargs.pop("srcs", []) + specs,
use_direct_specs = True,
deps = kwargs.pop("deps", []) + [
"//tools/jasmine:bootstrap",
# Because we don't provided a bundled script, we must ensure that the dependencies for
# bootstrap are also included as dependencies.
"//tools/jasmine:bootstrap_dependencies",
],
templated_args = templated_args,
**kwargs
)

0 comments on commit dbc0cd7

Please sign in to comment.