From e2638037fa93d3d2fbff1f5af08b50604189eaa7 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Wed, 26 Jan 2022 13:29:28 +0100 Subject: [PATCH] fix(jasmine): replace deprecated Jasmine APIs that have been removed in version 4 With this change we replace APIs that have been deprecated in version 4 and removed in version 4 ``` Jasmine#onComplete is deprecated. Instead of calling onComplete, set the Jasmine instance's exitOnCompletion property to false and use the promise returned from the execute method. ``` Also this addresses the breaking change in version 4 https://github.com/jasmine/jasmine/blob/main/release_notes/4.0.0.md#changes-that-affect-custom-reporters in a backward compatible manner. Closes #3289 --- e2e/BUILD.bazel | 19 ++++++- packages/jasmine/jasmine_runner.js | 90 ++++++++++++++++++++---------- 2 files changed, 78 insertions(+), 31 deletions(-) diff --git a/e2e/BUILD.bazel b/e2e/BUILD.bazel index 4567b86d62..c905ac74cd 100644 --- a/e2e/BUILD.bazel +++ b/e2e/BUILD.bazel @@ -51,15 +51,28 @@ e2e_integration_test( tags = ["no-bazelci-windows"], ) -e2e_integration_test( - name = "e2e_jasmine", +[e2e_integration_test( + name = "e2e_jasmine_%s" % jasmine_version.replace(".", "_"), npm_packages = { "//packages/jasmine:npm_package": "@bazel/jasmine", }, + # use these package.json packages instead + package_json_substitutions = { + "jasmine": jasmine_version, + "jasmine-core": jasmine_version, + }, # TODO: figure out why this fails on Windows since setting # symlink_node_modules to False in the test WORKSPACE tags = ["no-bazelci-windows"], -) + workspace_root = "jasmine", +) for jasmine_version in [ + # Old API + "2.99.x", + "3.9.x", + # New API + "4.0.x", + "3.10.x", +]] e2e_integration_test( name = "e2e_node_loader_no_preserve_symlinks", diff --git a/packages/jasmine/jasmine_runner.js b/packages/jasmine/jasmine_runner.js index 6fbbd657d6..3f7b5658b5 100644 --- a/packages/jasmine/jasmine_runner.js +++ b/packages/jasmine/jasmine_runner.js @@ -27,8 +27,10 @@ const UTF8 = { // These exit codes are handled specially by Bazel: // https://github.com/bazelbuild/bazel/blob/486206012a664ecb20bdb196a681efc9a9825049/src/main/java/com/google/devtools/build/lib/util/ExitCode.java#L44 +const BAZEL_EXIT_SUCCESS = 0; const BAZEL_EXIT_TESTS_FAILED = 3; const BAZEL_EXIT_NO_TESTS_FOUND = 4; +const BAZEL_EXIT_INTERRUPTED = 8; // Test sharding support // See https://docs.bazel.build/versions/main/test-encyclopedia.html#role-of-the-test-runner @@ -91,13 +93,6 @@ async function main(args) { .filter(f => IS_TEST_FILE.test(f)) .forEach(f => jrunner.addSpecFile(f)); - var noSpecsFound = true; - jrunner.addReporter({ - specDone: () => { - noSpecsFound = false - }, - }); - if (JUnitXmlReporter) { const testOutputFile = process.env.XML_OUTPUT_FILE; if (testOutputFile) { @@ -107,22 +102,15 @@ async function main(args) { consolidate: true, consolidateAll: true })); + + // addReporter throws away the default console reporter + // so we need to add it back + jrunner.configureDefaultReporter({}); } else { console.warn('Skipping XML Test Result: $XML_OUTPUT_FILE not found.') } } - // addReporter throws away the default console reporter - // so we need to add it back - jrunner.configureDefaultReporter({}); - - jrunner.onComplete((passed) => { - let exitCode = passed ? 0 : BAZEL_EXIT_TESTS_FAILED; - if (noSpecsFound) exitCode = BAZEL_EXIT_NO_TESTS_FOUND; - - process.exit(exitCode); - }); - if (TOTAL_SHARDS) { // Since we want to collect all the loaded specs, we have to do this after // loadSpecs() in jasmine/lib/jasmine.js @@ -133,7 +121,7 @@ async function main(args) { // Patch the inner execute function to do our filtering first. const env = jasmine.getEnv(); const originalExecute = env.execute.bind(env); - env.execute = async () => { + env.execute = () => { const allSpecs = getAllSpecs(env); // Partition the specs among the shards. // This ensures that the specs are evenly divided over the shards. @@ -144,8 +132,10 @@ async function main(args) { const end = allSpecs.length * (SHARD_INDEX + 1) / TOTAL_SHARDS; const enabledSpecs = allSpecs.slice(start, end); env.configure({specFilter: (s) => enabledSpecs.includes(s.id)}); - await originalExecute(); + + return originalExecute(); }; + // Special case! // To allow us to test sharding, always run the specs in the order they are declared if (process.env['TEST_WORKSPACE'] === 'build_bazel_rules_nodejs' && @@ -154,22 +144,66 @@ async function main(args) { } } - await jrunner.execute(); + // Jasmine versions prior to 3.10.0 should use the old API. + if (/^3\.[1-9]\.|^2\./.test(jrunner.coreVersion())) { + console.warn(`DEPRECATED: Support for Jasmine versions prior to '3.10.x' is deprecated in '@bazel/jasmine'.`); + + // Old Jasmine API. + let noSpecsFound = true; + jrunner.addReporter({ + specDone: () => { + noSpecsFound = false + }, + }); + + jrunner.onComplete((passed) => { + let exitCode = passed ? BAZEL_EXIT_SUCCESS : BAZEL_EXIT_TESTS_FAILED; + if (noSpecsFound) exitCode = BAZEL_EXIT_NO_TESTS_FOUND; + + process.exit(exitCode); + }); + + // addReporter throws away the default console reporter + // so we need to add it back + jrunner.configureDefaultReporter({}); + await jrunner.execute(); - return 0; + return BAZEL_EXIT_SUCCESS; + } + + // New Jasmine API. + jrunner.exitOnCompletion = false; + const { overallStatus, incompleteReason } = await jrunner.execute(); + + switch (overallStatus) { + case 'passed': + return BAZEL_EXIT_SUCCESS; + case 'incomplete': + return incompleteReason === 'No specs found' ? BAZEL_EXIT_NO_TESTS_FOUND : BAZEL_EXIT_INTERRUPTED; + case 'failed': + default: + return BAZEL_EXIT_TESTS_FAILED; + } } function getAllSpecs(jasmineEnv) { - var specs = []; + const specs = []; // Walk the test suite tree depth first and collect all test specs - var stack = [jasmineEnv.topSuite()]; - var currentNode; + const stack = [jasmineEnv.topSuite()]; + let currentNode; while (currentNode = stack.pop()) { - if (currentNode instanceof jasmine.Spec) { + if (!currentNode) { + continue; + } + + const { children, id } = currentNode; + if (Array.isArray(children)) { + // This is a suite. + stack.push(...children); + } else if (id) { + // This is a spec. specs.unshift(currentNode); - } else if (currentNode instanceof jasmine.Suite) { - stack = stack.concat(currentNode.children); } }