From cc5d3b75e2635cb9618a7b57f200162ab602c2ef Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Wed, 14 Dec 2022 19:48:57 +0000 Subject: [PATCH] refactor: update `zone.js` and tests to work with ESM (#48521) * Adjusts tests to no longer rely on CommonJS features. Switches them to ESM * Updates test initialization files to not double-initialize Jasmine now that bootstrap files are loaded after Jasmine. The `jasmine.boot` setup was hacky from `rules_nodejs` and will break in the future regardless if we e.g. use `rules_js` with actual unmodified `jasmine`. PR Close #48521 --- .circleci/config.yml | 23 +- packages/zone.js/.gitignore | 1 + packages/zone.js/lib/BUILD.bazel | 3 +- packages/zone.js/package.json | 7 +- .../scripts/closure/closure_compiler.sh | 2 +- .../zone.js/scripts/closure/closure_flagfile | 4 +- packages/zone.js/test/BUILD.bazel | 74 +-- packages/zone.js/test/closure/BUILD.bazel | 15 + packages/zone.js/test/closure/zone.closure.ts | 2 +- packages/zone.js/test/common/Error.spec.ts | 2 +- packages/zone.js/test/common/Promise.spec.ts | 25 -- packages/zone.js/test/node/fs.spec.ts | 11 +- packages/zone.js/test/node/http.spec.ts | 3 +- .../test/node_bluebird_entry_point.init.ts | 4 - .../zone.js/test/node_entry_point.init.ts | 8 - .../node_entry_point_no_patch_clock.init.ts | 36 -- .../zone.js/test/node_error_disable_policy.ts | 10 + ...e_error_disable_policy_entry_point.init.ts | 6 +- .../test/node_error_entry_point.init.ts | 8 - .../zone.js/test/node_error_lazy_policy.ts | 10 + ...node_error_lazy_policy_entry_point.init.ts | 6 +- .../test/npm_package/npm_package.spec.ts | 7 +- ...promise-adapter.js => promise-adapter.mjs} | 11 +- packages/zone.js/test/promise/promise-test.js | 10 - .../zone.js/test/promise/promise-test.mjs | 11 + .../test/promise/promise.finally.spec.js | 392 ---------------- .../test/promise/promise.finally.spec.mjs | 425 ++++++++++++++++++ packages/zone.js/test/typings/tsconfig.json | 19 +- packages/zone.js/test/typings/type.test.ts | 3 +- .../test/zone-spec/clock-tests/BUILD.bazel | 58 +++ .../clock-tests/enable-clock-patch.ts} | 3 +- .../fake-async-patched-clock.spec.ts | 67 +++ .../fake-async-unpatched-clock.spec.ts | 115 +++++ .../zone-spec/clock-tests/patched.init.ts | 10 + .../zone-spec/clock-tests/unpatched.init.ts | 9 + .../test/zone-spec/fake-async-test.spec.ts | 175 +------- packages/zone.js/tsconfig.json | 10 +- packages/zone.js/yarn.lock | 5 - tools/defaults.bzl | 4 +- 39 files changed, 826 insertions(+), 768 deletions(-) create mode 100644 packages/zone.js/test/closure/BUILD.bazel delete mode 100644 packages/zone.js/test/node_entry_point_no_patch_clock.init.ts create mode 100644 packages/zone.js/test/node_error_disable_policy.ts create mode 100644 packages/zone.js/test/node_error_lazy_policy.ts rename packages/zone.js/test/promise/{promise-adapter.js => promise-adapter.mjs} (61%) delete mode 100644 packages/zone.js/test/promise/promise-test.js create mode 100644 packages/zone.js/test/promise/promise-test.mjs delete mode 100644 packages/zone.js/test/promise/promise.finally.spec.js create mode 100644 packages/zone.js/test/promise/promise.finally.spec.mjs create mode 100644 packages/zone.js/test/zone-spec/clock-tests/BUILD.bazel rename packages/zone.js/test/{test-env-setup-jasmine-no-patch-clock.ts => zone-spec/clock-tests/enable-clock-patch.ts} (66%) create mode 100644 packages/zone.js/test/zone-spec/clock-tests/fake-async-patched-clock.spec.ts create mode 100644 packages/zone.js/test/zone-spec/clock-tests/fake-async-unpatched-clock.spec.ts create mode 100644 packages/zone.js/test/zone-spec/clock-tests/patched.init.ts create mode 100644 packages/zone.js/test/zone-spec/clock-tests/unpatched.init.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index 9bf2636cb35..62080b7cbca 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -612,15 +612,30 @@ jobs: - custom_attach_workspace - init_environment - install_java + + - run: | + yarn bazel build -- \ + //packages/zone.js/bundles:zone.umd.js \ + //packages/zone.js:npm_package \ + //packages/zone.js/test/closure:closure_js \ + //packages/zone.js:zone_externs + + - run: | + mkdir -p packages/zone.js/build/ + mkdir -p packages/zone.js/build/test/ + mkdir -p packages/zone.js/test/ + + cp dist/bin/packages/zone.js/bundles/zone.umd.js packages/zone.js/build/zone.umd.js + cp dist/bin/packages/zone.js/npm_package/bundles/zone-mix.umd.js ./packages/zone.js/test/extra/ + cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/ + cp dist/bin/packages/zone.js/test/closure/zone.closure.mjs ./packages/zone.js/build/test/zone.closure.mjs + cp dist/bin/packages/zone.js/zone_externs.js ./packages/zone.js/build/zone_externs.js + # Install - run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive --cache-folder ~/.cache/yarn # Run zone.js tools tests - run: yarn --cwd packages/zone.js promisetest - run: yarn --cwd packages/zone.js promisefinallytest - - run: yarn bazel build //packages/zone.js:npm_package && - cp dist/bin/packages/zone.js/npm_package/bundles/zone-mix.umd.js ./packages/zone.js/test/extra/ && - cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/ && - cp dist/bin/packages/zone.js/npm_package/bundles/zone.umd.js ./packages/zone.js/build/test/closure/zone.js - run: yarn --cwd packages/zone.js jest:test - run: yarn --cwd packages/zone.js jest:nodetest - run: yarn --cwd packages/zone.js electrontest diff --git a/packages/zone.js/.gitignore b/packages/zone.js/.gitignore index 378eac25d31..16133cbab81 100644 --- a/packages/zone.js/.gitignore +++ b/packages/zone.js/.gitignore @@ -1 +1,2 @@ +/node_modules/ build diff --git a/packages/zone.js/lib/BUILD.bazel b/packages/zone.js/lib/BUILD.bazel index 43040c3439f..44930472a40 100644 --- a/packages/zone.js/lib/BUILD.bazel +++ b/packages/zone.js/lib/BUILD.bazel @@ -1,4 +1,4 @@ -load("@npm//@bazel/concatjs:index.bzl", "ts_library") +load("//tools:defaults.bzl", "ts_library") package(default_visibility = ["//visibility:public"]) @@ -27,6 +27,5 @@ ts_library( "@npm//@types/jasmine", "@npm//@types/node", "@npm//rxjs", - "@npm//tslib", ], ) diff --git a/packages/zone.js/package.json b/packages/zone.js/package.json index f5066c70c8e..e2d5ebfb0d0 100644 --- a/packages/zone.js/package.json +++ b/packages/zone.js/package.json @@ -20,16 +20,15 @@ "jest-environment-node": "^29.0.3", "mocha": "^10.0.0", "mock-require": "3.0.3", - "promises-aplus-tests": "^2.1.2", - "typescript": "~4.9.3" + "promises-aplus-tests": "^2.1.2" }, "scripts": { "closuretest": "./scripts/closure/closure_compiler.sh", "electrontest": "cd test/extra && node electron.js", "jest:test": "jest --config ./test/jest/jest.config.js ./test/jest/jest.spec.js", "jest:nodetest": "jest --config ./test/jest/jest.node.config.js ./test/jest/jest.spec.js", - "promisetest": "tsc -p . && node ./test/promise/promise-test.js", - "promisefinallytest": "tsc -p . && mocha ./test/promise/promise.finally.spec.js" + "promisetest": "node ./test/promise/promise-test.mjs", + "promisefinallytest": "mocha ./test/promise/promise.finally.spec.mjs" }, "repository": { "type": "git", diff --git a/packages/zone.js/scripts/closure/closure_compiler.sh b/packages/zone.js/scripts/closure/closure_compiler.sh index c16a2e1739e..22edd750fc8 100755 --- a/packages/zone.js/scripts/closure/closure_compiler.sh +++ b/packages/zone.js/scripts/closure/closure_compiler.sh @@ -1,7 +1,7 @@ # compile closure test source file $(npm bin)/tsc -p . # Run the Google Closure compiler java runnable with zone externs -java -jar ./node_modules/google-closure-compiler-java/compiler.jar --flagfile './scripts/closure/closure_flagfile' --externs './lib/closure/zone_externs.js' --externs './node_modules/@externs/nodejs/v8/global.js' --process_common_js_modules +java -jar ./node_modules/google-closure-compiler-java/compiler.jar --flagfile './scripts/closure/closure_flagfile' --externs './build/zone_externs.js' --externs './node_modules/@externs/nodejs/v8/global.js' --process_common_js_modules # the names of Zone exposed API should be kept correctly with zone externs, test program should exit with 0. node build/closure/zone-closure-bundle.js diff --git a/packages/zone.js/scripts/closure/closure_flagfile b/packages/zone.js/scripts/closure/closure_flagfile index c068c3c1381..b07b374f5d1 100644 --- a/packages/zone.js/scripts/closure/closure_flagfile +++ b/packages/zone.js/scripts/closure/closure_flagfile @@ -1,6 +1,6 @@ --compilation_level ADVANCED_OPTIMIZATIONS --js_output_file "build/closure/zone-closure-bundle.js" --rewrite_polyfills false ---js "build/test/closure/zone.js" ---js "build/test/closure/zone.closure.js" +--js "build/zone.umd.js" +--js "build/test/zone.closure.mjs" --formatting PRETTY_PRINT diff --git a/packages/zone.js/test/BUILD.bazel b/packages/zone.js/test/BUILD.bazel index 37b7d38093e..e2c728ab8d5 100644 --- a/packages/zone.js/test/BUILD.bazel +++ b/packages/zone.js/test/BUILD.bazel @@ -1,7 +1,7 @@ -load("//tools:defaults.bzl", "jasmine_node_test", "ts_library") +load("//tools:defaults.bzl", "jasmine_node_test", "ts_library", "zone_compatible_jasmine_node_test") load("//packages/zone.js/test:karma_test.bzl", "karma_test") -package(default_visibility = ["//:__pkg__"]) +package(default_visibility = ["//:__subpackages__"]) exports_files([ "assets/sample.json", @@ -67,14 +67,8 @@ ts_library( ts_library( name = "test_node_lib", testonly = True, - srcs = glob(["node/*.ts"]) + [ - "node-env-setup.ts", - "test-env-setup-jasmine-no-patch-clock.ts", - ], + srcs = glob(["node/*.ts"]), deps = [ - ":common_spec_env", - ":common_spec_srcs", - ":common_spec_util", "//packages/zone.js/lib", "@npm//@types/shelljs", "@npm//@types/systemjs", @@ -87,28 +81,12 @@ ts_library( ts_library( name = "node_entry_point", testonly = True, - srcs = ["node_entry_point.init.ts"], - deps = [ - ":common_spec_env", - ":common_spec_srcs", - ":common_spec_util", - "//packages/zone.js/lib", - "@npm//@types/shelljs", - "@npm//@types/systemjs", - "@npm//rxjs", - "@npm//shelljs", - "@npm//systemjs", + srcs = [ + "node-env-setup.ts", + "node_entry_point.init.ts", ], -) - -ts_library( - name = "node_entry_point_no_patch_clock", - testonly = True, - srcs = ["node_entry_point_no_patch_clock.init.ts"], deps = [ ":common_spec_env", - ":common_spec_srcs", - ":common_spec_util", "//packages/zone.js/lib", "@npm//@types/shelljs", "@npm//@types/systemjs", @@ -145,13 +123,12 @@ ts_library( ts_library( name = "node_error_disable_policy_entry_point", testonly = True, - srcs = ["node_error_disable_policy_entry_point.init.ts"], + srcs = [ + "node_error_disable_policy.ts", + "node_error_disable_policy_entry_point.init.ts", + ], deps = [ - ":common_spec_env", - ":common_spec_util", - ":error_spec_srcs", ":node_error_entry_point", - "//packages/zone.js/lib", ], ) @@ -161,8 +138,6 @@ ts_library( srcs = ["node_error_entry_point.init.ts"], deps = [ ":common_spec_env", - ":common_spec_util", - ":error_spec_srcs", "//packages/zone.js/lib", ], ) @@ -170,33 +145,25 @@ ts_library( ts_library( name = "node_error_lazy_policy_entry_point", testonly = True, - srcs = ["node_error_lazy_policy_entry_point.init.ts"], + srcs = [ + "node_error_lazy_policy.ts", + "node_error_lazy_policy_entry_point.init.ts", + ], deps = [ - ":common_spec_env", - ":common_spec_util", - ":error_spec_srcs", ":node_error_entry_point", - "//packages/zone.js/lib", ], ) -jasmine_node_test( +zone_compatible_jasmine_node_test( name = "test_node", bootstrap = [":node_entry_point"], deps = [ + ":common_spec_srcs", ":test_node_lib", ], ) -jasmine_node_test( - name = "test_node_no_jasmine_clock", - bootstrap = [":node_entry_point_no_patch_clock"], - deps = [ - ":test_node_lib", - ], -) - -jasmine_node_test( +zone_compatible_jasmine_node_test( name = "test_node_bluebird", bootstrap = [":node_bluebird_entry_point"], deps = [ @@ -207,11 +174,17 @@ jasmine_node_test( jasmine_node_test( name = "test_node_error_disable_policy", bootstrap = [":node_error_disable_policy_entry_point"], + deps = [ + ":error_spec_srcs", + ], ) jasmine_node_test( name = "test_node_error_lazy_policy", bootstrap = [":node_error_lazy_policy_entry_point"], + deps = [ + ":error_spec_srcs", + ], ) ts_library( @@ -219,6 +192,7 @@ ts_library( testonly = True, srcs = ["npm_package/npm_package.spec.ts"], deps = [ + "@npm//@bazel/runfiles", "@npm//@types/shelljs", ], ) diff --git a/packages/zone.js/test/closure/BUILD.bazel b/packages/zone.js/test/closure/BUILD.bazel new file mode 100644 index 00000000000..c3347709484 --- /dev/null +++ b/packages/zone.js/test/closure/BUILD.bazel @@ -0,0 +1,15 @@ +load("//tools:defaults.bzl", "ts_library") + +ts_library( + name = "closure", + testonly = True, + srcs = ["zone.closure.ts"], + deps = ["//packages/zone.js/lib:zone_d_ts"], +) + +filegroup( + name = "closure_js", + testonly = True, + srcs = [":closure"], + output_group = "es6_sources", +) diff --git a/packages/zone.js/test/closure/zone.closure.ts b/packages/zone.js/test/closure/zone.closure.ts index 464fb334d3b..35f877d6f2e 100644 --- a/packages/zone.js/test/closure/zone.closure.ts +++ b/packages/zone.js/test/closure/zone.closure.ts @@ -5,7 +5,7 @@ * 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 './zone.js'; +import '../zone.umd.js'; const testClosureFunction = () => { const logs: string[] = []; // call all Zone exposed functions diff --git a/packages/zone.js/test/common/Error.spec.ts b/packages/zone.js/test/common/Error.spec.ts index ed377237e06..0cb95adffd8 100644 --- a/packages/zone.js/test/common/Error.spec.ts +++ b/packages/zone.js/test/common/Error.spec.ts @@ -308,7 +308,7 @@ describe('ZoneAwareError', () => { hasZoneStack = zoneAwareFrames.filter(f => frames[i].indexOf(f) !== -1).length > 0; } if (!hasZoneStack) { - console.log('stack', err.originalStack); + console.log('stack', hasZoneStack, frames, err.originalStack); } expect(hasZoneStack).toBe(true); } else { diff --git a/packages/zone.js/test/common/Promise.spec.ts b/packages/zone.js/test/common/Promise.spec.ts index 7fd34dcff8a..ea33929daf7 100644 --- a/packages/zone.js/test/common/Promise.spec.ts +++ b/packages/zone.js/test/common/Promise.spec.ts @@ -63,31 +63,6 @@ describe( log = []; }); - xit('should allow set es6 Promise after load ZoneAwarePromise', (done) => { - const ES6Promise = require('es6-promise').Promise; - const NativePromise = global[zoneSymbol('Promise')]; - - try { - global['Promise'] = ES6Promise; - Zone.assertZonePatched(); - expect(global[zoneSymbol('Promise')]).toBe(ES6Promise); - const promise = Promise.resolve(0); - console.log('promise', promise); - promise - .then(value => { - expect(value).toBe(0); - done(); - }) - .catch(error => { - fail(error); - }); - } finally { - global['Promise'] = NativePromise; - Zone.assertZonePatched(); - expect(global[zoneSymbol('Promise')]).toBe(NativePromise); - } - }); - it('should pretend to be a native code', () => { expect(String(Promise).indexOf('[native code]') >= 0).toBe(true); }); diff --git a/packages/zone.js/test/node/fs.spec.ts b/packages/zone.js/test/node/fs.spec.ts index ed0797d8be5..13f59d9b2ac 100644 --- a/packages/zone.js/test/node/fs.spec.ts +++ b/packages/zone.js/test/node/fs.spec.ts @@ -7,7 +7,10 @@ */ import {closeSync, exists, fstatSync, openSync, read, unlink, unlinkSync, unwatchFile, watch, watchFile, write, writeFile} from 'fs'; -import * as util from 'util'; +import url from 'url'; +import util from 'util'; + +const currentFile = url.fileURLToPath(import.meta.url); describe('nodejs file system', () => { describe('async method patch test', () => { @@ -94,7 +97,7 @@ describe('nodejs file system', () => { describe('util.promisify', () => { it('fs.exists should work with util.promisify', (done: DoneFn) => { const promisifyExists = util.promisify(exists); - promisifyExists(__filename) + promisifyExists(currentFile) .then( r => { expect(r).toBe(true); @@ -107,7 +110,7 @@ describe('util.promisify', () => { it('fs.read should work with util.promisify', (done: DoneFn) => { const promisifyRead = util.promisify(read); - const fd = openSync(__filename, 'r'); + const fd = openSync(currentFile, 'r'); const stats = fstatSync(fd); const bufferSize = stats.size; const chunkSize = 512; @@ -129,7 +132,7 @@ describe('util.promisify', () => { it('fs.write should work with util.promisify', (done: DoneFn) => { const promisifyWrite = util.promisify(write); - const dest = __filename + 'write'; + const dest = currentFile + 'write'; const fd = openSync(dest, 'a'); const stats = fstatSync(fd); const chunkSize = 512; diff --git a/packages/zone.js/test/node/http.spec.ts b/packages/zone.js/test/node/http.spec.ts index 74b70095383..848bf3957a0 100644 --- a/packages/zone.js/test/node/http.spec.ts +++ b/packages/zone.js/test/node/http.spec.ts @@ -5,7 +5,8 @@ * 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 */ -const http = require('http'); +import http from 'http'; + describe('http test', () => { it('http.request should be patched as eventTask', (done) => { const server = http.createServer((req: any, res: any) => { diff --git a/packages/zone.js/test/node_bluebird_entry_point.init.ts b/packages/zone.js/test/node_bluebird_entry_point.init.ts index 34d40fdac9c..df873a09f83 100644 --- a/packages/zone.js/test/node_bluebird_entry_point.init.ts +++ b/packages/zone.js/test/node_bluebird_entry_point.init.ts @@ -8,17 +8,14 @@ // Must be loaded before zone loads, so that zone can detect WTF. import './test_fake_polyfill'; - // Setup tests for Zone without microtask support import '../lib/zone'; import '../lib/common/promise'; import '../lib/common/to-string'; import '../lib/node/node'; // Setup test environment -require('@bazel/jasmine').boot(); import './test-env-setup-jasmine'; import './wtf_mock'; - import '../lib/zone-spec/async-test'; import '../lib/zone-spec/fake-async-test'; import '../lib/zone-spec/long-stack-trace'; @@ -27,7 +24,6 @@ import '../lib/zone-spec/sync-test'; import '../lib/zone-spec/task-tracking'; import '../lib/zone-spec/wtf'; import '../lib/rxjs/rxjs'; - import '../lib/testing/promise-testing'; const globalErrors = (jasmine as any).GlobalErrors; diff --git a/packages/zone.js/test/node_entry_point.init.ts b/packages/zone.js/test/node_entry_point.init.ts index d9d183078b7..fe3bc516caa 100644 --- a/packages/zone.js/test/node_entry_point.init.ts +++ b/packages/zone.js/test/node_entry_point.init.ts @@ -16,18 +16,10 @@ // Must be loaded before zone loads, so that zone can detect WTF. import './node-env-setup'; import './test_fake_polyfill'; - // Setup tests for Zone without microtask support import '../lib/node/rollup-main'; - -require('@bazel/jasmine').boot(); // Zone symbol prefix is set to '__zone_symbol2__' in node-env-setup.ts. import './test-env-setup-jasmine'; -if (typeof global !== 'undefined' && - (global as any)['__zone_symbol_test__fakeAsyncAutoFakeAsyncWhenClockPatched'] !== false) { - (global as any)['__zone_symbol_test__fakeAsyncAutoFakeAsyncWhenClockPatched'] = true; -} - import './wtf_mock'; import '../lib/testing/zone-testing'; import '../lib/zone-spec/task-tracking'; diff --git a/packages/zone.js/test/node_entry_point_no_patch_clock.init.ts b/packages/zone.js/test/node_entry_point_no_patch_clock.init.ts deleted file mode 100644 index 538374b7dc3..00000000000 --- a/packages/zone.js/test/node_entry_point_no_patch_clock.init.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @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 - */ -/** - * @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 - */ - -// Must be loaded before zone loads, so that zone can detect WTF. -import './node-env-setup'; -import './test_fake_polyfill'; - -// Setup tests for Zone without microtask support -import '../lib/node/rollup-main'; -require('@bazel/jasmine').boot(); -import './test-env-setup-jasmine-no-patch-clock'; -// Zone symbol prefix is set to '__zone_symbol2__' in node-env-setup.ts. -if (typeof global !== 'undefined' && - (global as any)['__zone_symbol_test__fakeAsyncAutoFakeAsyncWhenClockPatched'] !== false) { - (global as any)['__zone_symbol_test__fakeAsyncAutoFakeAsyncWhenClockPatched'] = true; -} - -import './wtf_mock'; -import '../lib/testing/zone-testing'; -import '../lib/zone-spec/task-tracking'; -import '../lib/zone-spec/wtf'; -import '../lib/rxjs/rxjs'; -import '../lib/rxjs/rxjs-fake-async'; -import '../lib/jasmine/jasmine'; diff --git a/packages/zone.js/test/node_error_disable_policy.ts b/packages/zone.js/test/node_error_disable_policy.ts new file mode 100644 index 00000000000..43a512b6d34 --- /dev/null +++ b/packages/zone.js/test/node_error_disable_policy.ts @@ -0,0 +1,10 @@ +/** + * @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 + */ + +process.env['errorpolicy'] = (global as any)['__Zone_Error_ZoneJsInternalStackFrames_policy'] = + 'disable'; diff --git a/packages/zone.js/test/node_error_disable_policy_entry_point.init.ts b/packages/zone.js/test/node_error_disable_policy_entry_point.init.ts index e11dfdd13ce..4d3435bee3b 100644 --- a/packages/zone.js/test/node_error_disable_policy_entry_point.init.ts +++ b/packages/zone.js/test/node_error_disable_policy_entry_point.init.ts @@ -6,6 +6,6 @@ * found in the LICENSE file at https://angular.io/license */ -process.env['errorpolicy'] = (global as any)['__Zone_Error_ZoneJsInternalStackFrames_policy'] = - 'disable'; -import './node_error_entry_point'; +// Note: Make sure to define the policy before loading the basic entry point. +import './node_error_disable_policy'; +import './node_error_entry_point.init'; diff --git a/packages/zone.js/test/node_error_entry_point.init.ts b/packages/zone.js/test/node_error_entry_point.init.ts index a3602d36b9c..651ec727c20 100644 --- a/packages/zone.js/test/node_error_entry_point.init.ts +++ b/packages/zone.js/test/node_error_entry_point.init.ts @@ -8,18 +8,11 @@ // Must be loaded before zone loads, so that zone can detect WTF. import './test_fake_polyfill'; - // Setup tests for Zone without microtask support import '../lib/zone'; import '../lib/common/promise'; import '../lib/common/to-string'; - -process.env['errorpolicy'] = (global as any)['__Zone_Error_ZoneJsInternalStackFrames_policy'] = - 'disable'; -// Setup test environment -require('@bazel/jasmine').boot(); import './test-env-setup-jasmine'; - import './wtf_mock'; import '../lib/common/error-rewrite'; import '../lib/node/node'; @@ -31,5 +24,4 @@ import '../lib/zone-spec/sync-test'; import '../lib/zone-spec/task-tracking'; import '../lib/zone-spec/wtf'; import '../lib/rxjs/rxjs'; - import '../lib/testing/promise-testing'; diff --git a/packages/zone.js/test/node_error_lazy_policy.ts b/packages/zone.js/test/node_error_lazy_policy.ts new file mode 100644 index 00000000000..0031c78480c --- /dev/null +++ b/packages/zone.js/test/node_error_lazy_policy.ts @@ -0,0 +1,10 @@ +/** + * @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 + */ + +process.env['errorpolicy'] = (global as any)['__Zone_Error_ZoneJsInternalStackFrames_policy'] = + 'lazy'; diff --git a/packages/zone.js/test/node_error_lazy_policy_entry_point.init.ts b/packages/zone.js/test/node_error_lazy_policy_entry_point.init.ts index acf37d60fa5..c088d77168c 100644 --- a/packages/zone.js/test/node_error_lazy_policy_entry_point.init.ts +++ b/packages/zone.js/test/node_error_lazy_policy_entry_point.init.ts @@ -6,6 +6,6 @@ * found in the LICENSE file at https://angular.io/license */ -process.env['errorpolicy'] = (global as any)['__Zone_Error_ZoneJsInternalStackFrames_policy'] = - 'lazy'; -import './node_error_entry_point'; +// Note: Make sure to define the policy before loading the basic entry point. +import './node_error_lazy_policy'; +import './node_error_entry_point.init'; diff --git a/packages/zone.js/test/npm_package/npm_package.spec.ts b/packages/zone.js/test/npm_package/npm_package.spec.ts index 6092014a7c7..daedd47df77 100644 --- a/packages/zone.js/test/npm_package/npm_package.spec.ts +++ b/packages/zone.js/test/npm_package/npm_package.spec.ts @@ -5,8 +5,9 @@ * 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 * as path from 'path'; -import * as shx from 'shelljs'; +import {runfiles} from '@bazel/runfiles'; +import path from 'path'; +import shx from 'shelljs'; function checkInSubFolder(subFolder: string, testFn: Function) { shx.cd(subFolder); @@ -16,7 +17,7 @@ function checkInSubFolder(subFolder: string, testFn: Function) { describe('Zone.js npm_package', () => { beforeEach(() => { - shx.cd(path.dirname(require.resolve('angular/packages/zone.js/npm_package/package.json'))); + shx.cd(path.dirname(runfiles.resolve('angular/packages/zone.js/npm_package/package.json'))); }); describe('misc root files', () => { describe('README.md', () => { diff --git a/packages/zone.js/test/promise/promise-adapter.js b/packages/zone.js/test/promise/promise-adapter.mjs similarity index 61% rename from packages/zone.js/test/promise/promise-adapter.js rename to packages/zone.js/test/promise/promise-adapter.mjs index 22e31addc52..e901283a026 100644 --- a/packages/zone.js/test/promise/promise-adapter.js +++ b/packages/zone.js/test/promise/promise-adapter.mjs @@ -1,6 +1,7 @@ -require('../../build/lib/node/rollup-main'); +import '../../build/zone.umd.js'; + Zone[Zone.__symbol__('ignoreConsoleErrorUncaughtError')] = true; -module.exports.deferred = function() { +const deferred = function () { const p = {}; p.promise = new Promise((resolve, reject) => { p.resolve = resolve; @@ -9,10 +10,12 @@ module.exports.deferred = function() { return p; }; -module.exports.resolved = (val) => { +const resolved = (val) => { return Promise.resolve(val); }; -module.exports.rejected = (reason) => { +const rejected = (reason) => { return Promise.reject(reason); }; + +export default {deferred, resolved, rejected}; diff --git a/packages/zone.js/test/promise/promise-test.js b/packages/zone.js/test/promise/promise-test.js deleted file mode 100644 index c9ab27ad360..00000000000 --- a/packages/zone.js/test/promise/promise-test.js +++ /dev/null @@ -1,10 +0,0 @@ -const promisesAplusTests = require('promises-aplus-tests'); -const adapter = require('./promise-adapter'); -promisesAplusTests(adapter, {reporter: 'dot'}, function(err) { - if (err) { - console.error(err); - process.exit(1); - } else { - process.exit(0); - } -}); diff --git a/packages/zone.js/test/promise/promise-test.mjs b/packages/zone.js/test/promise/promise-test.mjs new file mode 100644 index 00000000000..88cc2ec241e --- /dev/null +++ b/packages/zone.js/test/promise/promise-test.mjs @@ -0,0 +1,11 @@ +import promisesAplusTests from 'promises-aplus-tests'; +import adapter from './promise-adapter.mjs'; + +promisesAplusTests(adapter, {reporter: 'dot'}, function (err) { + if (err) { + console.error(err); + process.exit(1); + } else { + process.exit(0); + } +}); diff --git a/packages/zone.js/test/promise/promise.finally.spec.js b/packages/zone.js/test/promise/promise.finally.spec.js deleted file mode 100644 index 5d08e7a4974..00000000000 --- a/packages/zone.js/test/promise/promise.finally.spec.js +++ /dev/null @@ -1,392 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var adapter = require('./promise-adapter'); -var P = global[Zone.__symbol__('Promise')]; - -var someRejectionReason = {message: 'some rejection reason'}; -var anotherReason = {message: 'another rejection reason'}; -process.on('unhandledRejection', function(reason, promise) { - console.log('unhandledRejection', reason); -}); - -describe('mocha promise sanity check', () => { - it('passes with a resolved promise', () => { - return P.resolve(3); - }); - - it('passes with a rejected then resolved promise', () => { - return P.reject(someRejectionReason).catch(x => 'this should be resolved'); - }); - - var ifPromiseIt = P === Promise ? it : it.skip; - ifPromiseIt('is the native Promise', () => { - assert.equal(P, Promise); - }); -}); - -describe('onFinally', () => { - describe('no callback', () => { - specify('from resolved', (done) => { - adapter.resolved(3) - .then((x) => { - assert.strictEqual(x, 3); - return x; - }) - .finally() - .then( - function onFulfilled(x) { - assert.strictEqual(x, 3); - done(); - }, - function onRejected() { - done(new Error('should not be called')); - }); - }); - - specify('from rejected', (done) => { - adapter.rejected(someRejectionReason) - .catch((e) => { - assert.strictEqual(e, someRejectionReason); - throw e; - }) - .finally() - .then( - function onFulfilled() { - done(new Error('should not be called')); - }, - function onRejected(reason) { - assert.strictEqual(reason, someRejectionReason); - done(); - }); - }); - }); - - describe('throws an exception', () => { - specify('from resolved', (done) => { - adapter.resolved(3) - .then((x) => { - assert.strictEqual(x, 3); - return x; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - throw someRejectionReason; - }) - .then( - function onFulfilled() { - done(new Error('should not be called')); - }, - function onRejected(reason) { - assert.strictEqual(reason, someRejectionReason); - done(); - }); - }); - - specify('from rejected', (done) => { - adapter.rejected(anotherReason) - .finally(function onFinally() { - assert(arguments.length === 0); - throw someRejectionReason; - }) - .then( - function onFulfilled() { - done(new Error('should not be called')); - }, - function onRejected(reason) { - assert.strictEqual(reason, someRejectionReason); - done(); - }); - }); - }); - - describe('returns a non-promise', () => { - specify('from resolved', (done) => { - adapter.resolved(3) - .then((x) => { - assert.strictEqual(x, 3); - return x; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - return 4; - }) - .then( - function onFulfilled(x) { - assert.strictEqual(x, 3); - done(); - }, - function onRejected() { - done(new Error('should not be called')); - }); - }); - - specify('from rejected', (done) => { - adapter.rejected(anotherReason) - .catch((e) => { - assert.strictEqual(e, anotherReason); - throw e; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - throw someRejectionReason; - }) - .then( - function onFulfilled() { - done(new Error('should not be called')); - }, - function onRejected(e) { - assert.strictEqual(e, someRejectionReason); - done(); - }); - }); - }); - - describe('returns a pending-forever promise', () => { - specify('from resolved', (done) => { - var timeout; - adapter.resolved(3) - .then((x) => { - assert.strictEqual(x, 3); - return x; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - timeout = setTimeout(done, 0.1e3); - return new P(() => {}); // forever pending - }) - .then( - function onFulfilled(x) { - clearTimeout(timeout); - done(new Error('should not be called')); - }, - function onRejected() { - clearTimeout(timeout); - done(new Error('should not be called')); - }); - }); - - specify('from rejected', (done) => { - var timeout; - adapter.rejected(someRejectionReason) - .catch((e) => { - assert.strictEqual(e, someRejectionReason); - throw e; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - timeout = setTimeout(done, 0.1e3); - return new P(() => {}); // forever pending - }) - .then( - function onFulfilled(x) { - clearTimeout(timeout); - done(new Error('should not be called')); - }, - function onRejected() { - clearTimeout(timeout); - done(new Error('should not be called')); - }); - }); - }); - - describe('returns an immediately-fulfilled promise', () => { - specify('from resolved', (done) => { - adapter.resolved(3) - .then((x) => { - assert.strictEqual(x, 3); - return x; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - return adapter.resolved(4); - }) - .then( - function onFulfilled(x) { - assert.strictEqual(x, 3); - done(); - }, - function onRejected() { - done(new Error('should not be called')); - }); - }); - - specify('from rejected', (done) => { - adapter.rejected(someRejectionReason) - .catch((e) => { - assert.strictEqual(e, someRejectionReason); - throw e; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - return adapter.resolved(4); - }) - .then( - function onFulfilled() { - done(new Error('should not be called')); - }, - function onRejected(e) { - assert.strictEqual(e, someRejectionReason); - done(); - }); - }); - }); - - describe('returns an immediately-rejected promise', () => { - specify('from resolved ', (done) => { - adapter.resolved(3) - .then((x) => { - assert.strictEqual(x, 3); - return x; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - return adapter.rejected(4); - }) - .then( - function onFulfilled(x) { - done(new Error('should not be called')); - }, - function onRejected(e) { - assert.strictEqual(e, 4); - done(); - }); - }); - - specify('from rejected', (done) => { - const newReason = {}; - adapter.rejected(someRejectionReason) - .catch((e) => { - assert.strictEqual(e, someRejectionReason); - throw e; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - return adapter.rejected(newReason); - }) - .then( - function onFulfilled(x) { - done(new Error('should not be called')); - }, - function onRejected(e) { - assert.strictEqual(e, newReason); - done(); - }); - }); - }); - - describe('returns a fulfilled-after-a-second promise', () => { - specify('from resolved', (done) => { - var timeout; - adapter.resolved(3) - .then((x) => { - assert.strictEqual(x, 3); - return x; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - timeout = setTimeout(done, 1.5e3); - return new P((resolve) => { - setTimeout(() => resolve(4), 1e3); - }); - }) - .then( - function onFulfilled(x) { - clearTimeout(timeout); - assert.strictEqual(x, 3); - done(); - }, - function onRejected() { - clearTimeout(timeout); - done(new Error('should not be called')); - }); - }); - - specify('from rejected', (done) => { - var timeout; - adapter.rejected(3) - .catch((e) => { - assert.strictEqual(e, 3); - throw e; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - timeout = setTimeout(done, 1.5e3); - return new P((resolve) => { - setTimeout(() => resolve(4), 1e3); - }); - }) - .then( - function onFulfilled() { - clearTimeout(timeout); - done(new Error('should not be called')); - }, - function onRejected(e) { - clearTimeout(timeout); - assert.strictEqual(e, 3); - done(); - }); - }); - }); - - describe('returns a rejected-after-a-second promise', () => { - specify('from resolved', (done) => { - var timeout; - adapter.resolved(3) - .then((x) => { - assert.strictEqual(x, 3); - return x; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - timeout = setTimeout(done, 1.5e3); - return new P((resolve, reject) => { - setTimeout(() => reject(4), 1e3); - }); - }) - .then( - function onFulfilled() { - clearTimeout(timeout); - done(new Error('should not be called')); - }, - function onRejected(e) { - clearTimeout(timeout); - assert.strictEqual(e, 4); - done(); - }); - }); - - specify('from rejected', (done) => { - var timeout; - adapter.rejected(someRejectionReason) - .catch((e) => { - assert.strictEqual(e, someRejectionReason); - throw e; - }) - .finally(function onFinally() { - assert(arguments.length === 0); - timeout = setTimeout(done, 1.5e3); - return new P((resolve, reject) => { - setTimeout(() => reject(anotherReason), 1e3); - }); - }) - .then( - function onFulfilled() { - clearTimeout(timeout); - done(new Error('should not be called')); - }, - function onRejected(e) { - clearTimeout(timeout); - assert.strictEqual(e, anotherReason); - done(); - }); - }); - }); - - specify('has the correct property descriptor', () => { - var descriptor = Object.getOwnPropertyDescriptor(Promise.prototype, 'finally'); - - assert.strictEqual(descriptor.writable, true); - assert.strictEqual(descriptor.configurable, true); - }); -}); \ No newline at end of file diff --git a/packages/zone.js/test/promise/promise.finally.spec.mjs b/packages/zone.js/test/promise/promise.finally.spec.mjs new file mode 100644 index 00000000000..cfe32221405 --- /dev/null +++ b/packages/zone.js/test/promise/promise.finally.spec.mjs @@ -0,0 +1,425 @@ +'use strict'; + +import assert from 'assert'; +import adapter from './promise-adapter.mjs'; + +var P = global[Zone.__symbol__('Promise')]; + +var someRejectionReason = {message: 'some rejection reason'}; +var anotherReason = {message: 'another rejection reason'}; +process.on('unhandledRejection', function (reason, promise) { + console.log('unhandledRejection', reason); +}); + +describe('mocha promise sanity check', () => { + it('passes with a resolved promise', () => { + return P.resolve(3); + }); + + it('passes with a rejected then resolved promise', () => { + return P.reject(someRejectionReason).catch((x) => 'this should be resolved'); + }); + + var ifPromiseIt = P === Promise ? it : it.skip; + ifPromiseIt('is the native Promise', () => { + assert.equal(P, Promise); + }); +}); + +describe('onFinally', () => { + describe('no callback', () => { + specify('from resolved', (done) => { + adapter + .resolved(3) + .then((x) => { + assert.strictEqual(x, 3); + return x; + }) + .finally() + .then( + function onFulfilled(x) { + assert.strictEqual(x, 3); + done(); + }, + function onRejected() { + done(new Error('should not be called')); + } + ); + }); + + specify('from rejected', (done) => { + adapter + .rejected(someRejectionReason) + .catch((e) => { + assert.strictEqual(e, someRejectionReason); + throw e; + }) + .finally() + .then( + function onFulfilled() { + done(new Error('should not be called')); + }, + function onRejected(reason) { + assert.strictEqual(reason, someRejectionReason); + done(); + } + ); + }); + }); + + describe('throws an exception', () => { + specify('from resolved', (done) => { + adapter + .resolved(3) + .then((x) => { + assert.strictEqual(x, 3); + return x; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + throw someRejectionReason; + }) + .then( + function onFulfilled() { + done(new Error('should not be called')); + }, + function onRejected(reason) { + assert.strictEqual(reason, someRejectionReason); + done(); + } + ); + }); + + specify('from rejected', (done) => { + adapter + .rejected(anotherReason) + .finally(function onFinally() { + assert(arguments.length === 0); + throw someRejectionReason; + }) + .then( + function onFulfilled() { + done(new Error('should not be called')); + }, + function onRejected(reason) { + assert.strictEqual(reason, someRejectionReason); + done(); + } + ); + }); + }); + + describe('returns a non-promise', () => { + specify('from resolved', (done) => { + adapter + .resolved(3) + .then((x) => { + assert.strictEqual(x, 3); + return x; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + return 4; + }) + .then( + function onFulfilled(x) { + assert.strictEqual(x, 3); + done(); + }, + function onRejected() { + done(new Error('should not be called')); + } + ); + }); + + specify('from rejected', (done) => { + adapter + .rejected(anotherReason) + .catch((e) => { + assert.strictEqual(e, anotherReason); + throw e; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + throw someRejectionReason; + }) + .then( + function onFulfilled() { + done(new Error('should not be called')); + }, + function onRejected(e) { + assert.strictEqual(e, someRejectionReason); + done(); + } + ); + }); + }); + + describe('returns a pending-forever promise', () => { + specify('from resolved', (done) => { + var timeout; + adapter + .resolved(3) + .then((x) => { + assert.strictEqual(x, 3); + return x; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + timeout = setTimeout(done, 0.1e3); + return new P(() => {}); // forever pending + }) + .then( + function onFulfilled(x) { + clearTimeout(timeout); + done(new Error('should not be called')); + }, + function onRejected() { + clearTimeout(timeout); + done(new Error('should not be called')); + } + ); + }); + + specify('from rejected', (done) => { + var timeout; + adapter + .rejected(someRejectionReason) + .catch((e) => { + assert.strictEqual(e, someRejectionReason); + throw e; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + timeout = setTimeout(done, 0.1e3); + return new P(() => {}); // forever pending + }) + .then( + function onFulfilled(x) { + clearTimeout(timeout); + done(new Error('should not be called')); + }, + function onRejected() { + clearTimeout(timeout); + done(new Error('should not be called')); + } + ); + }); + }); + + describe('returns an immediately-fulfilled promise', () => { + specify('from resolved', (done) => { + adapter + .resolved(3) + .then((x) => { + assert.strictEqual(x, 3); + return x; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + return adapter.resolved(4); + }) + .then( + function onFulfilled(x) { + assert.strictEqual(x, 3); + done(); + }, + function onRejected() { + done(new Error('should not be called')); + } + ); + }); + + specify('from rejected', (done) => { + adapter + .rejected(someRejectionReason) + .catch((e) => { + assert.strictEqual(e, someRejectionReason); + throw e; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + return adapter.resolved(4); + }) + .then( + function onFulfilled() { + done(new Error('should not be called')); + }, + function onRejected(e) { + assert.strictEqual(e, someRejectionReason); + done(); + } + ); + }); + }); + + describe('returns an immediately-rejected promise', () => { + specify('from resolved ', (done) => { + adapter + .resolved(3) + .then((x) => { + assert.strictEqual(x, 3); + return x; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + return adapter.rejected(4); + }) + .then( + function onFulfilled(x) { + done(new Error('should not be called')); + }, + function onRejected(e) { + assert.strictEqual(e, 4); + done(); + } + ); + }); + + specify('from rejected', (done) => { + const newReason = {}; + adapter + .rejected(someRejectionReason) + .catch((e) => { + assert.strictEqual(e, someRejectionReason); + throw e; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + return adapter.rejected(newReason); + }) + .then( + function onFulfilled(x) { + done(new Error('should not be called')); + }, + function onRejected(e) { + assert.strictEqual(e, newReason); + done(); + } + ); + }); + }); + + describe('returns a fulfilled-after-a-second promise', () => { + specify('from resolved', (done) => { + var timeout; + adapter + .resolved(3) + .then((x) => { + assert.strictEqual(x, 3); + return x; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + timeout = setTimeout(done, 1.5e3); + return new P((resolve) => { + setTimeout(() => resolve(4), 1e3); + }); + }) + .then( + function onFulfilled(x) { + clearTimeout(timeout); + assert.strictEqual(x, 3); + done(); + }, + function onRejected() { + clearTimeout(timeout); + done(new Error('should not be called')); + } + ); + }); + + specify('from rejected', (done) => { + var timeout; + adapter + .rejected(3) + .catch((e) => { + assert.strictEqual(e, 3); + throw e; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + timeout = setTimeout(done, 1.5e3); + return new P((resolve) => { + setTimeout(() => resolve(4), 1e3); + }); + }) + .then( + function onFulfilled() { + clearTimeout(timeout); + done(new Error('should not be called')); + }, + function onRejected(e) { + clearTimeout(timeout); + assert.strictEqual(e, 3); + done(); + } + ); + }); + }); + + describe('returns a rejected-after-a-second promise', () => { + specify('from resolved', (done) => { + var timeout; + adapter + .resolved(3) + .then((x) => { + assert.strictEqual(x, 3); + return x; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + timeout = setTimeout(done, 1.5e3); + return new P((resolve, reject) => { + setTimeout(() => reject(4), 1e3); + }); + }) + .then( + function onFulfilled() { + clearTimeout(timeout); + done(new Error('should not be called')); + }, + function onRejected(e) { + clearTimeout(timeout); + assert.strictEqual(e, 4); + done(); + } + ); + }); + + specify('from rejected', (done) => { + var timeout; + adapter + .rejected(someRejectionReason) + .catch((e) => { + assert.strictEqual(e, someRejectionReason); + throw e; + }) + .finally(function onFinally() { + assert(arguments.length === 0); + timeout = setTimeout(done, 1.5e3); + return new P((resolve, reject) => { + setTimeout(() => reject(anotherReason), 1e3); + }); + }) + .then( + function onFulfilled() { + clearTimeout(timeout); + done(new Error('should not be called')); + }, + function onRejected(e) { + clearTimeout(timeout); + assert.strictEqual(e, anotherReason); + done(); + } + ); + }); + }); + + specify('has the correct property descriptor', () => { + var descriptor = Object.getOwnPropertyDescriptor(Promise.prototype, 'finally'); + + assert.strictEqual(descriptor.writable, true); + assert.strictEqual(descriptor.configurable, true); + }); +}); diff --git a/packages/zone.js/test/typings/tsconfig.json b/packages/zone.js/test/typings/tsconfig.json index 852aed6002f..f18ffef5a8f 100644 --- a/packages/zone.js/test/typings/tsconfig.json +++ b/packages/zone.js/test/typings/tsconfig.json @@ -4,24 +4,15 @@ "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "experimentalDecorators": true, - "module": "commonjs", - "moduleResolution": "node", "outDir": "./build", "rootDir": ".", - "target": "ES2015", + "target": "es2020", + "module": "Node16", + "moduleResolution": "node", "noEmitOnError": false, "stripInternal": false, "strict": true, - "lib": [ - "es5", - "dom", - "es2015.collection", - "es2015.iterable", - "es2015.promise", - ], + "lib": ["es5", "dom", "es2015.collection", "es2015.iterable", "es2015.promise"] }, - "files": [ - "./type.test.ts", - "./node_modules/zone.js/zone.d.ts" - ], + "files": ["./type.test.ts", "./node_modules/zone.js/zone.d.ts"] } diff --git a/packages/zone.js/test/typings/type.test.ts b/packages/zone.js/test/typings/type.test.ts index d013f40f0b4..653ad83fc9a 100644 --- a/packages/zone.js/test/typings/type.test.ts +++ b/packages/zone.js/test/typings/type.test.ts @@ -1,5 +1,6 @@ +import 'zone.js/bundles/zone.umd'; + import * as domino from 'domino'; -require('zone.js/bundles/zone.umd'); // Zone public API should be included Zone.current.fork({name: 'testZone'}).run(() => {}); diff --git a/packages/zone.js/test/zone-spec/clock-tests/BUILD.bazel b/packages/zone.js/test/zone-spec/clock-tests/BUILD.bazel new file mode 100644 index 00000000000..a5744cf367f --- /dev/null +++ b/packages/zone.js/test/zone-spec/clock-tests/BUILD.bazel @@ -0,0 +1,58 @@ +load("//tools:defaults.bzl", "jasmine_node_test", "ts_library") + +ts_library( + name = "patched_init", + testonly = True, + srcs = [ + "enable-clock-patch.ts", + "patched.init.ts", + ], + deps = [ + "//packages/zone.js/test:node_entry_point", + ], +) + +ts_library( + name = "test_patched_lib", + testonly = True, + srcs = [ + "fake-async-patched-clock.spec.ts", + ], + deps = [ + "//packages/zone.js/lib:zone_d_ts", + ], +) + +ts_library( + name = "unpatched_init", + testonly = True, + srcs = [ + "unpatched.init.ts", + ], + deps = [ + "//packages/zone.js/test:node_entry_point", + ], +) + +ts_library( + name = "test_unpatched_lib", + testonly = True, + srcs = [ + "fake-async-unpatched-clock.spec.ts", + ], + deps = [ + "//packages/zone.js/lib:zone_d_ts", + ], +) + +jasmine_node_test( + name = "test_patched", + bootstrap = [":patched_init"], + deps = [":test_patched_lib"], +) + +jasmine_node_test( + name = "test_unpatched", + bootstrap = [":unpatched_init"], + deps = [":test_unpatched_lib"], +) diff --git a/packages/zone.js/test/test-env-setup-jasmine-no-patch-clock.ts b/packages/zone.js/test/zone-spec/clock-tests/enable-clock-patch.ts similarity index 66% rename from packages/zone.js/test/test-env-setup-jasmine-no-patch-clock.ts rename to packages/zone.js/test/zone-spec/clock-tests/enable-clock-patch.ts index f0864c33334..db90d261365 100644 --- a/packages/zone.js/test/test-env-setup-jasmine-no-patch-clock.ts +++ b/packages/zone.js/test/zone-spec/clock-tests/enable-clock-patch.ts @@ -5,4 +5,5 @@ * 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 */ -(global as any)[(global as any).Zone.__symbol__('fakeAsyncAutoFakeAsyncWhenClockPatched')] = false; + +(global as any)['__zone_symbol_test__fakeAsyncAutoFakeAsyncWhenClockPatched'] = true; diff --git a/packages/zone.js/test/zone-spec/clock-tests/fake-async-patched-clock.spec.ts b/packages/zone.js/test/zone-spec/clock-tests/fake-async-patched-clock.spec.ts new file mode 100644 index 00000000000..2c142c9be8d --- /dev/null +++ b/packages/zone.js/test/zone-spec/clock-tests/fake-async-patched-clock.spec.ts @@ -0,0 +1,67 @@ +/** + * @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 + */ + +describe('fake async unpatched clock tests', () => { + let spy: any; + + beforeEach(() => { + spy = jasmine.createSpy('timer'); + jasmine.clock().install(); + }); + + afterEach(() => { + jasmine.clock().uninstall(); + }); + + it('should check date type correctly', () => { + const d: any = new Date(); + expect(d instanceof Date).toBe(true); + }); + + it('should get date diff correctly', () => { + const start = Date.now(); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + }); + it('should tick correctly', () => { + const start = Date.now(); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + }); + + it('should mock date correctly', () => { + const baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + const start = Date.now(); + expect(start).toBe(baseTime.getTime()); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + expect(end).toBe(baseTime.getTime() + 100); + }); + + it('should handle new Date correctly', () => { + const baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + const start = new Date(); + expect(start.getTime()).toBe(baseTime.getTime()); + jasmine.clock().tick(100); + const end = new Date(); + expect(end.getTime() - start.getTime()).toBe(100); + expect(end.getTime()).toBe(baseTime.getTime() + 100); + }); + + it('should handle setTimeout correctly', () => { + setTimeout(spy, 100); + expect(spy).not.toHaveBeenCalled(); + jasmine.clock().tick(100); + expect(spy).toHaveBeenCalled(); + }); +}) diff --git a/packages/zone.js/test/zone-spec/clock-tests/fake-async-unpatched-clock.spec.ts b/packages/zone.js/test/zone-spec/clock-tests/fake-async-unpatched-clock.spec.ts new file mode 100644 index 00000000000..dbf5d73b9b1 --- /dev/null +++ b/packages/zone.js/test/zone-spec/clock-tests/fake-async-unpatched-clock.spec.ts @@ -0,0 +1,115 @@ +/** + * @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 + */ + +// Note: We uninstall the clock before starting the tests. This is necessary because +// ZoneJS is loaded after Jasmine has captured the global timing functions. Jasmine +// now doesn't allow `clock().install` because Zone modified e.g. `setTimeout`. +// Uninstalling results in Jasmine resetting to the original NodeJS globals. +// This is fine for this test as it doesn't rely on e.g. patched `setTimeout`. +// https://github.com/jasmine/jasmine/blob/169a2a8ad23a7e5cb12be0a2df02ea4337b9811a/src/core/Clock.js#L17. +jasmine.clock().uninstall(); + +describe('fake async unpatched clock tests', () => { + const fakeAsync = (Zone as any)[Zone.__symbol__('fakeAsyncTest')].fakeAsync; + let spy: any; + + beforeEach(() => { + spy = jasmine.createSpy('timer'); + jasmine.clock().install(); + }); + + afterEach(() => { + jasmine.clock().uninstall(); + }); + + it('should check date type correctly', fakeAsync(() => { + const d: any = new Date(); + expect(d instanceof Date).toBe(true); + })); + + it('should check date type correctly without fakeAsync', () => { + const d: any = new Date(); + expect(d instanceof Date).toBe(true); + }); + + it('should tick correctly', fakeAsync(() => { + jasmine.clock().mockDate(); + const start = Date.now(); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + })); + + it('should tick correctly without fakeAsync', () => { + jasmine.clock().mockDate(); + const start = Date.now(); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + }); + + it('should mock date correctly', fakeAsync(() => { + const baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + const start = Date.now(); + expect(start).toBe(baseTime.getTime()); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + expect(end).toBe(baseTime.getTime() + 100); + expect(new Date().getFullYear()).toEqual(2013); + })); + + it('should mock date correctly without fakeAsync', () => { + const baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + const start = Date.now(); + expect(start).toBe(baseTime.getTime()); + jasmine.clock().tick(100); + const end = Date.now(); + expect(end - start).toBe(100); + expect(end).toBe(baseTime.getTime() + 100); + expect(new Date().getFullYear()).toEqual(2013); + }); + + it('should handle new Date correctly', fakeAsync(() => { + const baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + const start = new Date(); + expect(start.getTime()).toBe(baseTime.getTime()); + jasmine.clock().tick(100); + const end = new Date(); + expect(end.getTime() - start.getTime()).toBe(100); + expect(end.getTime()).toBe(baseTime.getTime() + 100); + })); + + it('should handle new Date correctly without fakeAsync', () => { + const baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + const start = new Date(); + expect(start.getTime()).toBe(baseTime.getTime()); + jasmine.clock().tick(100); + const end = new Date(); + expect(end.getTime() - start.getTime()).toBe(100); + expect(end.getTime()).toBe(baseTime.getTime() + 100); + }); + + it('should handle setTimeout correctly', fakeAsync(() => { + setTimeout(spy, 100); + expect(spy).not.toHaveBeenCalled(); + jasmine.clock().tick(100); + expect(spy).toHaveBeenCalled(); + })); + + it('should handle setTimeout correctly without fakeAsync', () => { + setTimeout(spy, 100); + expect(spy).not.toHaveBeenCalled(); + jasmine.clock().tick(100); + expect(spy).toHaveBeenCalled(); + }); +}) diff --git a/packages/zone.js/test/zone-spec/clock-tests/patched.init.ts b/packages/zone.js/test/zone-spec/clock-tests/patched.init.ts new file mode 100644 index 00000000000..26a12f2886d --- /dev/null +++ b/packages/zone.js/test/zone-spec/clock-tests/patched.init.ts @@ -0,0 +1,10 @@ +/** + * @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 './enable-clock-patch'; +import '../../node_entry_point.init'; diff --git a/packages/zone.js/test/zone-spec/clock-tests/unpatched.init.ts b/packages/zone.js/test/zone-spec/clock-tests/unpatched.init.ts new file mode 100644 index 00000000000..09b7d1ec815 --- /dev/null +++ b/packages/zone.js/test/zone-spec/clock-tests/unpatched.init.ts @@ -0,0 +1,9 @@ +/** + * @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 '../../node_entry_point.init'; diff --git a/packages/zone.js/test/zone-spec/fake-async-test.spec.ts b/packages/zone.js/test/zone-spec/fake-async-test.spec.ts index a6a289f5806..d44ae005e5e 100644 --- a/packages/zone.js/test/zone-spec/fake-async-test.spec.ts +++ b/packages/zone.js/test/zone-spec/fake-async-test.spec.ts @@ -25,13 +25,6 @@ function emptyRun() { (supportNode as any).message = 'support node'; -function supportClock() { - const _global: any = typeof window === 'undefined' ? global : window; - return typeof jasmine.clock === 'function' && - _global[zoneSymbol('fakeAsyncAutoFakeAsyncWhenClockPatched')]; -} - -(supportClock as any).message = 'support patch clock'; describe('FakeAsyncTestZoneSpec', () => { let FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; @@ -1067,173 +1060,7 @@ describe('FakeAsyncTestZoneSpec', () => { }); }); - describe( - 'fakeAsyncTest should work without patch jasmine.clock', - ifEnvSupports( - () => { - return !supportClock() && supportNode(); - }, - () => { - const fakeAsync = (Zone as any)[Zone.__symbol__('fakeAsyncTest')].fakeAsync; - let spy: any; - beforeEach(() => { - spy = jasmine.createSpy('timer'); - jasmine.clock().install(); - }); - - afterEach(() => { - jasmine.clock().uninstall(); - }); - - it('should check date type correctly', fakeAsync(() => { - const d: any = new Date(); - expect(d instanceof Date).toBe(true); - })); - - it('should check date type correctly without fakeAsync', () => { - const d: any = new Date(); - expect(d instanceof Date).toBe(true); - }); - - it('should tick correctly', fakeAsync(() => { - jasmine.clock().mockDate(); - const start = Date.now(); - jasmine.clock().tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - })); - - it('should tick correctly without fakeAsync', () => { - jasmine.clock().mockDate(); - const start = Date.now(); - jasmine.clock().tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - }); - - it('should mock date correctly', fakeAsync(() => { - const baseTime = new Date(2013, 9, 23); - jasmine.clock().mockDate(baseTime); - const start = Date.now(); - expect(start).toBe(baseTime.getTime()); - jasmine.clock().tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - expect(end).toBe(baseTime.getTime() + 100); - expect(new Date().getFullYear()).toEqual(2013); - })); - - it('should mock date correctly without fakeAsync', () => { - const baseTime = new Date(2013, 9, 23); - jasmine.clock().mockDate(baseTime); - const start = Date.now(); - expect(start).toBe(baseTime.getTime()); - jasmine.clock().tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - expect(end).toBe(baseTime.getTime() + 100); - expect(new Date().getFullYear()).toEqual(2013); - }); - - it('should handle new Date correctly', fakeAsync(() => { - const baseTime = new Date(2013, 9, 23); - jasmine.clock().mockDate(baseTime); - const start = new Date(); - expect(start.getTime()).toBe(baseTime.getTime()); - jasmine.clock().tick(100); - const end = new Date(); - expect(end.getTime() - start.getTime()).toBe(100); - expect(end.getTime()).toBe(baseTime.getTime() + 100); - })); - - it('should handle new Date correctly without fakeAsync', () => { - const baseTime = new Date(2013, 9, 23); - jasmine.clock().mockDate(baseTime); - const start = new Date(); - expect(start.getTime()).toBe(baseTime.getTime()); - jasmine.clock().tick(100); - const end = new Date(); - expect(end.getTime() - start.getTime()).toBe(100); - expect(end.getTime()).toBe(baseTime.getTime() + 100); - }); - - it('should handle setTimeout correctly', fakeAsync(() => { - setTimeout(spy, 100); - expect(spy).not.toHaveBeenCalled(); - jasmine.clock().tick(100); - expect(spy).toHaveBeenCalled(); - })); - - it('should handle setTimeout correctly without fakeAsync', () => { - setTimeout(spy, 100); - expect(spy).not.toHaveBeenCalled(); - jasmine.clock().tick(100); - expect(spy).toHaveBeenCalled(); - }); - }, - emptyRun)); - - describe('fakeAsyncTest should patch jasmine.clock', ifEnvSupports(supportClock, () => { - let spy: any; - beforeEach(() => { - spy = jasmine.createSpy('timer'); - jasmine.clock().install(); - }); - - afterEach(() => { - jasmine.clock().uninstall(); - }); - - it('should check date type correctly', () => { - const d: any = new Date(); - expect(d instanceof Date).toBe(true); - }); - - it('should get date diff correctly', () => { - const start = Date.now(); - jasmine.clock().tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - }); - - it('should tick correctly', () => { - const start = Date.now(); - jasmine.clock().tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - }); - - it('should mock date correctly', () => { - const baseTime = new Date(2013, 9, 23); - jasmine.clock().mockDate(baseTime); - const start = Date.now(); - expect(start).toBe(baseTime.getTime()); - jasmine.clock().tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - expect(end).toBe(baseTime.getTime() + 100); - }); - - it('should handle new Date correctly', () => { - const baseTime = new Date(2013, 9, 23); - jasmine.clock().mockDate(baseTime); - const start = new Date(); - expect(start.getTime()).toBe(baseTime.getTime()); - jasmine.clock().tick(100); - const end = new Date(); - expect(end.getTime() - start.getTime()).toBe(100); - expect(end.getTime()).toBe(baseTime.getTime() + 100); - }); - - it('should handle setTimeout correctly', () => { - setTimeout(spy, 100); - expect(spy).not.toHaveBeenCalled(); - jasmine.clock().tick(100); - expect(spy).toHaveBeenCalled(); - }); - }, emptyRun)); - - describe('fakeAsyncTest should patch rxjs scheduler', ifEnvSupports(supportClock, () => { + describe('fakeAsyncTest should patch rxjs scheduler', ifEnvSupports(() => isNode, () => { let FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; let testZoneSpec: any; let fakeAsyncTestZone: Zone; diff --git a/packages/zone.js/tsconfig.json b/packages/zone.js/tsconfig.json index ba2007a0191..e65084cdbeb 100644 --- a/packages/zone.js/tsconfig.json +++ b/packages/zone.js/tsconfig.json @@ -1,7 +1,9 @@ { "compilerOptions": { - "module": "commonjs", - "target": "es2015", + "module": "esnext", + "target": "es2020", + "moduleResolution": "node", + "esModuleInterop": true, "outDir": "build", "inlineSourceMap": true, "inlineSources": true, @@ -18,9 +20,7 @@ "es2015.symbol", "es2015.symbol.wellknown" ], - "typeRoots": [ - "node_modules/@types" - ], + "typeRoots": ["node_modules/@types"] }, "exclude": [ "node_modules", diff --git a/packages/zone.js/yarn.lock b/packages/zone.js/yarn.lock index 8f52e4af7f6..87c45895560 100644 --- a/packages/zone.js/yarn.lock +++ b/packages/zone.js/yarn.lock @@ -3379,11 +3379,6 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -typescript@~4.9.3: - version "4.9.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.3.tgz#3aea307c1746b8c384435d8ac36b8a2e580d85db" - integrity sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA== - unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" diff --git a/tools/defaults.bzl b/tools/defaults.bzl index 1027576a0c3..6b7b95c5b65 100644 --- a/tools/defaults.bzl +++ b/tools/defaults.bzl @@ -429,12 +429,12 @@ def npm_package_bin(args = [], **kwargs): # TODO(devversion): Jasmine Node tests are only bundled using `spec_bundle` # because `async/await` syntax needs to be downleveled for ZoneJS. In the # future this can be removed when ZoneJS can work with native async/await in NodeJS. -def zone_compatible_jasmine_node_test(name, external = [], deps = [], bootstrap = [], **kwargs): +def zone_compatible_jasmine_node_test(name, external = [], srcs = [], deps = [], bootstrap = [], **kwargs): spec_bundle( name = "%s_bundle" % name, # Specs from this attribute are filtered and will be executed. We # add bootstrap here for discovery of the module mappings aspect. - deps = deps + bootstrap, + deps = srcs + deps + bootstrap, bootstrap = bootstrap, external = external + ["domino", "typescript"], platform = "node",