From 4b4cecf88f84589fbf2cfe712f0edd84a5961798 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Thu, 24 Mar 2022 14:03:36 +0100 Subject: [PATCH] test: update tests to work with Jasmine version 4 These changes include fixes to tests, timeout and stop of architect to make tests work with Jasmine 4. One noticeable change that when we didn't stop architect through `run.stop()` this causes Bazel to timeout now. Example ``` -- Test timed out at 2022-03-24 12:07:07 UTC -- /private/var/tmp/_bazel_alanagius/5168427e57f204ca069c602aa7ed1931/sandbox/darwin-sandbox/398/execroot/angular_cli/bazel-out/darwin-fastbuild/bin/packages/angular_devkit/build_angular/build_angular_browser_test.sh.runfiles/angular_cli/packages/angular_devkit/build_angular/build_angular_browser_test.sh: line 424: 41835 Terminated: 15 "${node}" ${LAUNCHER_NODE_OPTIONS[@]+"${LAUNCHER_NODE_OPTIONS[@]}"} ${USER_NODE_OPTIONS[@]+"${USER_NODE_OPTIONS[@]}"} "${MAIN}" ${ARGS[@]+"${ARGS[@]}"} 0<&0 ``` --- lib/bootstrap-local.js | 4 +- package.json | 1 - packages/angular_devkit/benchmark/BUILD.bazel | 1 - .../angular_devkit/benchmark/src/main_spec.ts | 8 +- .../browser/specs/build-optimizer_spec.ts | 7 +- .../browser/specs/cross-origin_spec.ts | 1 + .../src/builders/browser/specs/index_spec.ts | 3 + .../browser/specs/lazy-module_spec.ts | 7 +- .../browser/specs/output-path_spec.ts | 1 + .../src/builders/browser/specs/poll_spec.ts | 8 +- .../builders/browser/specs/rebuild_spec.ts | 20 ++- .../browser/specs/replacements_spec.ts | 12 +- .../browser/specs/resolve-json-module_spec.ts | 2 + .../src/builders/browser/specs/styles_spec.ts | 2 + .../dev-server/specs/live-reload_spec.ts | 11 +- .../behavior/build_translation_watch_spec.ts | 2 +- .../dev-server/tests/options/watch_spec.ts | 6 +- .../src/builders/dev-server/tests/setup.ts | 2 +- packages/angular_devkit/core/node/BUILD.bazel | 1 - .../angular_devkit/core/node/host_spec.ts | 128 ++++++++---------- .../core/src/json/schema/prompt_spec.ts | 98 ++++++-------- .../schematics/src/sink/dryrun_spec.ts | 38 +++--- yarn.lock | 15 -- 23 files changed, 174 insertions(+), 204 deletions(-) diff --git a/lib/bootstrap-local.js b/lib/bootstrap-local.js index 82de25aed4..bcc5b006ee 100644 --- a/lib/bootstrap-local.js +++ b/lib/bootstrap-local.js @@ -16,11 +16,11 @@ const debugBuildTs = debug('ng:local:build:ts'); const child_process = require('child_process'); const fs = require('fs'); +const os = require('os'); const path = require('path'); -const temp = require('temp'); const ts = require('typescript'); -const tmpRoot = temp.mkdirSync('angular-devkit-'); +const tmpRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'angular-devkit-')); debugLocal('starting bootstrap local'); diff --git a/package.json b/package.json index c82b620816..c68e1aee43 100644 --- a/package.json +++ b/package.json @@ -202,7 +202,6 @@ "stylus-loader": "6.2.0", "symbol-observable": "4.0.0", "tar": "^6.1.6", - "temp": "^0.9.0", "terser": "5.12.1", "text-table": "0.2.0", "tree-kill": "1.2.2", diff --git a/packages/angular_devkit/benchmark/BUILD.bazel b/packages/angular_devkit/benchmark/BUILD.bazel index 84beef742f..5fde557128 100644 --- a/packages/angular_devkit/benchmark/BUILD.bazel +++ b/packages/angular_devkit/benchmark/BUILD.bazel @@ -63,7 +63,6 @@ jasmine_node_test( "@npm//pidtree", "@npm//pidusage", "@npm//source-map", - "@npm//temp", "@npm//tree-kill", "@npm//yargs-parser", ], diff --git a/packages/angular_devkit/benchmark/src/main_spec.ts b/packages/angular_devkit/benchmark/src/main_spec.ts index 3beaf32a2c..6485b39380 100644 --- a/packages/angular_devkit/benchmark/src/main_spec.ts +++ b/packages/angular_devkit/benchmark/src/main_spec.ts @@ -6,13 +6,11 @@ * found in the LICENSE file at https://angular.io/license */ -import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs'; +import { existsSync, mkdtempSync, readFileSync, realpathSync, unlinkSync, writeFileSync } from 'fs'; +import { tmpdir } from 'os'; import { basename, dirname, join } from 'path'; import { main } from './main'; -// eslint-disable-next-line import/no-extraneous-dependencies -const temp = require('temp'); - // We only care about the write method in these mocks of NodeJS.WriteStream. class MockWriteStream { lines: string[] = []; @@ -29,7 +27,7 @@ describe('benchmark binary', () => { const exitCodeOneScript = require.resolve(join(__dirname, './test/exit-code-one.js')); const benchmarkWatchScript = require.resolve(join(__dirname, './test/watch-test-cmd.js')); const watchTriggerScript = require.resolve(join(__dirname, './test/watch-test-script.js')); - const outputFileRoot = temp.mkdirSync('benchmark-binary-spec-'); + const outputFileRoot = mkdtempSync(join(realpathSync(tmpdir()), 'benchmark-binary-spec-')); const outputFile = join(outputFileRoot, 'output.log'); let stdout: MockWriteStream, stderr: MockWriteStream; diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/build-optimizer_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/build-optimizer_spec.ts index 5908c9a2d2..4c5147f53b 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/build-optimizer_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/build-optimizer_spec.ts @@ -30,11 +30,8 @@ describe('Browser Builder build optimizer', () => { it('fails if AOT is disabled', async () => { const overrides = { aot: false, buildOptimizer: true }; const run = await architect.scheduleTarget(targetSpec, overrides); - - try { - await run.result; - expect('THE ABOVE LINE SHOULD THROW').toBe(''); - } catch {} + await expectAsync(run.result).toBeRejectedWithError(); + await run.stop(); }); it('reduces bundle size', async () => { diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/cross-origin_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/cross-origin_spec.ts index b4e1b14cda..5fcdd4e2fe 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/cross-origin_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/cross-origin_spec.ts @@ -99,5 +99,6 @@ describe('Browser Builder crossOrigin', () => { const fileName = join(normalize(output.outputPath), 'runtime.js'); const content = virtualFs.fileBufferToString(await host.read(normalize(fileName)).toPromise()); expect(content).toContain('script.crossOrigin = "use-credentials"'); + await run.stop(); }); }); diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/index_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/index_spec.ts index 81af7a911a..eee3427740 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/index_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/index_spec.ts @@ -156,6 +156,7 @@ describe('Browser Builder index HTML processing', () => { `` + ``, ); + await run.stop(); }); it('uses the output value from the index option longform', async () => { @@ -202,6 +203,7 @@ describe('Browser Builder index HTML processing', () => { `` + ``, ); + await run.stop(); }); it('creates subdirectories for output value from the index option longform', async () => { @@ -248,5 +250,6 @@ describe('Browser Builder index HTML processing', () => { `` + ``, ); + await run.stop(); }); }); diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/lazy-module_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/lazy-module_spec.ts index 016632fecc..5e025a65cb 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/lazy-module_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/lazy-module_spec.ts @@ -65,7 +65,7 @@ describe('Browser Builder lazy modules', () => { const { files } = await browserBuild(architect, host, target, { aot: true }); const data = await files['src_app_lazy_lazy_module_ts.js']; - expect(data).not.toBeUndefined('Lazy module output bundle does not exist'); + expect(data).not.toBeUndefined(); expect(data).toContain('LazyModule.ɵmod'); }); }); @@ -85,7 +85,8 @@ describe('Browser Builder lazy modules', () => { const run = await architect.scheduleTarget(target, {}, { logger }); const output = await run.result; expect(output.success).toBe(false); - expect(hasMissingModuleError(logs.join())).toBe(true, 'Should show missing module error'); + expect(hasMissingModuleError(logs.join())).toBeTrue(); + await run.stop(); }); it('should show error when lazy route is invalid on watch mode AOT', async () => { @@ -98,7 +99,7 @@ describe('Browser Builder lazy modules', () => { const run = await architect.scheduleTarget(target, overrides); await run.output .pipe( - debounceTime(3000), + debounceTime(1500), tap((buildEvent) => { buildNumber++; switch (buildNumber) { diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/output-path_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/output-path_spec.ts index 2b09fe90b6..6686d0d2b8 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/output-path_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/output-path_spec.ts @@ -65,6 +65,7 @@ describe('Browser Builder output path', () => { expect(await host.exists(join(host.root(), 'dist')).toPromise()).toBe(false); expect(await host.exists(join(host.root(), 'src-link')).toPromise()).toBe(true); + await run.stop(); }); it('does not allow output path to be project root', async () => { diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/poll_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/poll_spec.ts index 24334ec1ea..7a067e0115 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/poll_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/poll_spec.ts @@ -7,8 +7,9 @@ */ import { Architect } from '@angular-devkit/architect'; -import { debounceTime, take, tap } from 'rxjs/operators'; +import { debounceTime, take, tap, timeout } from 'rxjs/operators'; import { createArchitect, host } from '../../../testing/test-utils'; +import { BUILD_TIMEOUT } from '../index'; describe('Browser Builder poll', () => { const target = { project: 'app', target: 'build' }; @@ -21,13 +22,14 @@ describe('Browser Builder poll', () => { afterEach(async () => host.restore().toPromise()); it('works', async () => { - const overrides = { watch: true, poll: 10000 }; + const overrides = { watch: true, poll: 4000 }; const intervals: number[] = []; let startTime: number | undefined; const run = await architect.scheduleTarget(target, overrides); await run.output .pipe( + timeout(BUILD_TIMEOUT), // Debounce 1s, otherwise changes are too close together and polling doesn't work. debounceTime(1000), tap((buildEvent) => { @@ -46,5 +48,7 @@ describe('Browser Builder poll', () => { const median = intervals[Math.trunc(intervals.length / 2)]; expect(median).toBeGreaterThan(3000); expect(median).toBeLessThan(12000); + + await run.stop(); }); }); diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/rebuild_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/rebuild_spec.ts index dd5ef34f7b..1146d0a036 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/rebuild_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/rebuild_spec.ts @@ -8,7 +8,7 @@ import { Architect } from '@angular-devkit/architect'; import { join, logging, normalize, virtualFs } from '@angular-devkit/core'; -import { debounceTime, take, takeWhile, tap } from 'rxjs/operators'; +import { debounceTime, take, takeWhile, tap, timeout } from 'rxjs/operators'; import { createArchitect, host, @@ -16,6 +16,7 @@ import { lazyModuleFnImport, outputPath, } from '../../../testing/test-utils'; +import { BUILD_TIMEOUT } from '../index'; describe('Browser Builder rebuilds', () => { const target = { project: 'app', target: 'build' }; @@ -78,9 +79,10 @@ describe('Browser Builder rebuilds', () => { const run = await architect.scheduleTarget(target, overrides); await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap((result) => { - expect(result.success).toBe(true, 'build should succeed'); + expect(result.success).toBeTrue(); const hasLazyChunk = host .scopedSync() .exists(normalize('dist/src_app_lazy_lazy_module_ts.js')); @@ -131,6 +133,7 @@ describe('Browser Builder rebuilds', () => { const run = await architect.scheduleTarget(target, overrides); await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap((buildEvent) => expect(buildEvent.success).toBe(true)), tap(() => host.appendToFile('src/app/app.component.css', ':host { color: blue; }')), @@ -164,6 +167,7 @@ describe('Browser Builder rebuilds', () => { const run = await architect.scheduleTarget(target, overrides, { logger }); await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap((buildEvent) => { buildNumber += 1; @@ -217,12 +221,14 @@ describe('Browser Builder rebuilds', () => { const run = await architect.scheduleTarget(target, overrides); await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap((buildEvent) => expect(buildEvent.success).toBe(true)), tap(() => host.writeMultipleFiles({ 'src/type.ts': `export type MyType = string;` })), take(2), ) .toPromise(); + await run.stop(); }); it('rebuilds on transitive type-only file changes', async () => { @@ -250,6 +256,7 @@ describe('Browser Builder rebuilds', () => { let buildNumber = 0; await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap((buildEvent) => expect(buildEvent.success).toBe(true)), tap(() => { @@ -266,6 +273,8 @@ describe('Browser Builder rebuilds', () => { take(5), ) .toPromise(); + + await run.stop(); }); it('rebuilds on transitive non node package DTS file changes', async () => { @@ -293,6 +302,7 @@ describe('Browser Builder rebuilds', () => { let buildNumber = 0; await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap((buildEvent) => expect(buildEvent.success).toBe(true)), tap(() => { @@ -304,6 +314,7 @@ describe('Browser Builder rebuilds', () => { take(2), ) .toPromise(); + await run.stop(); }); it('rebuilds after errors in JIT', async () => { @@ -318,6 +329,7 @@ describe('Browser Builder rebuilds', () => { const run = await architect.scheduleTarget(target, overrides); await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap((buildEvent) => { buildNumber++; @@ -363,6 +375,7 @@ describe('Browser Builder rebuilds', () => { const run = await architect.scheduleTarget(target, overrides, { logger }); await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap((buildEvent) => { buildNumber += 1; @@ -461,6 +474,7 @@ describe('Browser Builder rebuilds', () => { const run = await architect.scheduleTarget(target, overrides); await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap((buildEvent) => { buildNumber += 1; @@ -551,6 +565,7 @@ describe('Browser Builder rebuilds', () => { const run = await architect.scheduleTarget(target, overrides); await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap((buildEvent) => { buildNumber += 1; @@ -615,6 +630,7 @@ describe('Browser Builder rebuilds', () => { const run = await architect.scheduleTarget(target, overrides); await run.output .pipe( + timeout(BUILD_TIMEOUT), debounceTime(rebuildDebounceTime), tap(() => { const content = virtualFs.fileBufferToString( diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/replacements_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/replacements_spec.ts index 20e62bdc23..39841f9aeb 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/replacements_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/replacements_spec.ts @@ -76,10 +76,7 @@ describe('Browser Builder file replacements', () => { }; const run = await architect.scheduleTarget(target, overrides); - try { - await run.result; - expect('THE ABOVE LINE SHOULD THROW').toBe(''); - } catch {} + await expectAsync(run.result).toBeRejectedWithError(); await run.stop(); }); @@ -94,10 +91,7 @@ describe('Browser Builder file replacements', () => { }; const run = await architect.scheduleTarget(target, overrides); - try { - await run.result; - expect('THE ABOVE LINE SHOULD THROW').toBe(''); - } catch {} + await expectAsync(run.result).toBeRejectedWithError(); await run.stop(); }); @@ -214,7 +208,7 @@ describe('Browser Builder file replacements', () => { .subscribe(); const res = await stop$.toPromise(); - expect(res).not.toBe(null, 'Test timed out.'); + expect(res).toBeDefined(); expect(res).not.toContain(unexpectedError); await run.stop(); }); diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/resolve-json-module_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/resolve-json-module_spec.ts index 52ff4f9fcb..7f24650c80 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/resolve-json-module_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/resolve-json-module_spec.ts @@ -62,5 +62,7 @@ describe('Browser Builder resolve json module', () => { take(2), ) .toPromise(); + + await run.stop(); }); }); diff --git a/packages/angular_devkit/build_angular/src/builders/browser/specs/styles_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/specs/styles_spec.ts index 71a39f0f3e..6c48c0b1eb 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/specs/styles_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/specs/styles_spec.ts @@ -513,6 +513,8 @@ describe('Browser Builder styles', () => { const run2 = await architect.scheduleTarget(target, overrides); await expectAsync(run2.result).toBeResolvedTo(jasmine.objectContaining({ success: false })); + await run2.stop(); + await run.stop(); }); it('supports Protocol-relative Url', async () => { diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/specs/live-reload_spec.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/specs/live-reload_spec.ts index fe55172ebd..84d9084313 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/specs/live-reload_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/specs/live-reload_spec.ts @@ -11,7 +11,7 @@ import { Architect, BuilderRun } from '@angular-devkit/architect'; import { tags } from '@angular-devkit/core'; import { createProxyServer } from 'http-proxy'; import puppeteer, { Browser, Page } from 'puppeteer'; -import { debounceTime, switchMap, take } from 'rxjs/operators'; +import { debounceTime, finalize, switchMap, take } from 'rxjs/operators'; import { createArchitect, host } from '../../../testing/test-utils'; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -131,7 +131,6 @@ describe('Dev Server Builder live-reload', () => { let browser: Browser; let page: Page; let runs: BuilderRun[]; - let proxy: ProxyInstance | undefined; beforeAll(async () => { browser = await puppeteer.launch({ @@ -164,8 +163,6 @@ describe('Dev Server Builder live-reload', () => { }); afterEach(async () => { - proxy?.server.close(); - proxy = undefined; await host.restore().toPromise(); await page.close(); await Promise.all(runs.map((r) => r.stop())); @@ -227,6 +224,9 @@ describe('Dev Server Builder live-reload', () => { buildCount++; }), take(2), + finalize(() => { + proxy?.server.close(); + }), ) .toPromise(); }); @@ -258,6 +258,9 @@ describe('Dev Server Builder live-reload', () => { buildCount++; }), take(2), + finalize(() => { + proxy?.server.close(); + }), ) .toPromise(); }); diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_translation_watch_spec.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_translation_watch_spec.ts index aea5f2ff58..630bd63e0f 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_translation_watch_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_translation_watch_spec.ts @@ -57,7 +57,7 @@ describeBuilder(serveWebpackBrowser, DEV_SERVER_BUILDER_INFO, (harness) => { const buildCount = await harness .execute() .pipe( - timeout(BUILD_TIMEOUT * 2), + timeout(BUILD_TIMEOUT), concatMap(async ({ result }, index) => { expect(result?.success).toBe(true); diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/options/watch_spec.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/options/watch_spec.ts index 8aad6f7241..4da51b5ba0 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/options/watch_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/options/watch_spec.ts @@ -32,7 +32,7 @@ describeBuilder(serveWebpackBrowser, DEV_SERVER_BUILDER_INFO, (harness) => { await harness .execute() .pipe( - timeout(BUILD_TIMEOUT * 2), + timeout(BUILD_TIMEOUT), concatMap(async ({ result }, index) => { expect(result?.success).toBe(true); @@ -68,7 +68,7 @@ describeBuilder(serveWebpackBrowser, DEV_SERVER_BUILDER_INFO, (harness) => { const buildCount = await harness .execute() .pipe( - timeout(BUILD_TIMEOUT * 2), + timeout(BUILD_TIMEOUT), concatMap(async ({ result }, index) => { expect(result?.success).toBe(true); @@ -100,7 +100,7 @@ describeBuilder(serveWebpackBrowser, DEV_SERVER_BUILDER_INFO, (harness) => { const buildCount = await harness .execute() .pipe( - timeout(BUILD_TIMEOUT * 2), + timeout(BUILD_TIMEOUT), concatMap(async ({ result }, index) => { expect(result?.success).toBe(true); diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts index a6330da2a7..6ee0525678 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts @@ -38,7 +38,7 @@ export const BASE_OPTIONS = Object.freeze({ * Maximum time for single build/rebuild * This accounts for CI variability. */ -export const BUILD_TIMEOUT = 15_000; +export const BUILD_TIMEOUT = 25_000; /** * Cached browser builder option schema diff --git a/packages/angular_devkit/core/node/BUILD.bazel b/packages/angular_devkit/core/node/BUILD.bazel index a97bc10b24..b99e476d48 100644 --- a/packages/angular_devkit/core/node/BUILD.bazel +++ b/packages/angular_devkit/core/node/BUILD.bazel @@ -57,7 +57,6 @@ jasmine_node_test( srcs = [":node_test_lib"], deps = [ "@npm//chokidar", - "@npm//temp", # @node_module: ajv # @node_module: fast_json_stable_stringify # @node_module: magic_string diff --git a/packages/angular_devkit/core/node/host_spec.ts b/packages/angular_devkit/core/node/host_spec.ts index c4315f793a..078a881ea5 100644 --- a/packages/angular_devkit/core/node/host_spec.ts +++ b/packages/angular_devkit/core/node/host_spec.ts @@ -6,15 +6,13 @@ * found in the LICENSE file at https://angular.io/license */ -/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable import/no-extraneous-dependencies */ import { normalize, virtualFs } from '@angular-devkit/core'; import { NodeJsAsyncHost, NodeJsSyncHost } from '@angular-devkit/core/node'; import * as fs from 'fs'; -import { Observable, Subscription } from 'rxjs'; - -const temp = require('temp'); +import { tmpdir } from 'os'; +import { join } from 'path'; // TODO: replace this with an "it()" macro that's reusable globally. let linuxOnlyIt: typeof it = it; @@ -27,11 +25,11 @@ describe('NodeJsAsyncHost', () => { let host: virtualFs.Host; beforeEach(() => { - root = temp.mkdirSync('core-node-spec-'); + root = fs.mkdtempSync(join(fs.realpathSync(tmpdir()), 'core-node-spec-')); host = new virtualFs.ScopedHost(new NodeJsAsyncHost(), normalize(root)); }); - afterEach((done) => host.delete(normalize('/')).toPromise().then(done, done.fail)); + afterEach(async () => host.delete(normalize('/')).toPromise()); it('should get correct result for exists', async () => { const filePath = normalize('not-found'); @@ -42,35 +40,30 @@ describe('NodeJsAsyncHost', () => { linuxOnlyIt( 'can watch', - (done) => { - let obs: Observable; - let subscription: Subscription; + async () => { const content = virtualFs.stringToFileBuffer('hello world'); const content2 = virtualFs.stringToFileBuffer('hello world 2'); const allEvents: virtualFs.HostWatchEvent[] = []; - Promise.resolve() - .then(() => fs.mkdirSync(root + '/sub1')) - .then(() => fs.writeFileSync(root + '/sub1/file1', 'hello world')) - .then(() => { - obs = host.watch(normalize('/sub1'), { recursive: true })!; - expect(obs).not.toBeNull(); - subscription = obs.subscribe((event) => { - allEvents.push(event); - }); - }) - .then(() => new Promise((resolve) => setTimeout(resolve, 100))) - // Discard the events registered so far. - .then(() => allEvents.splice(0)) - .then(() => host.write(normalize('/sub1/sub2/file3'), content).toPromise()) - .then(() => host.write(normalize('/sub1/file2'), content2).toPromise()) - .then(() => host.delete(normalize('/sub1/file1')).toPromise()) - .then(() => new Promise((resolve) => setTimeout(resolve, 2000))) - .then(() => { - expect(allEvents.length).toBe(3); - subscription.unsubscribe(); - }) - .then(done, done.fail); + fs.mkdirSync(root + '/sub1'); + fs.writeFileSync(root + '/sub1/file1', 'hello world'); + + const obs = host.watch(normalize('/sub1'), { recursive: true }); + expect(obs).toBeDefined(); + const subscription = obs!.subscribe((event) => { + allEvents.push(event); + }); + await new Promise((resolve) => setTimeout(resolve, 100)); + + // Discard the events registered so far. + allEvents.splice(0); + await host.write(normalize('/sub1/sub2/file3'), content).toPromise(); + await host.write(normalize('/sub1/file2'), content2).toPromise(); + await host.delete(normalize('/sub1/file1')).toPromise(); + + await new Promise((resolve) => setTimeout(resolve, 2000)); + expect(allEvents.length).toBe(3); + subscription.unsubscribe(); }, 30000, ); @@ -81,7 +74,7 @@ describe('NodeJsSyncHost', () => { let host: virtualFs.SyncDelegateHost; beforeEach(() => { - root = temp.mkdirSync('core-node-spec-'); + root = fs.mkdtempSync(join(fs.realpathSync(tmpdir()), 'core-node-spec-')); host = new virtualFs.SyncDelegateHost( new virtualFs.ScopedHost(new NodeJsSyncHost(), normalize(root)), ); @@ -92,56 +85,47 @@ describe('NodeJsSyncHost', () => { linuxOnlyIt( 'can watch', - (done) => { - let obs: Observable; - let subscription: Subscription; + async () => { const content = virtualFs.stringToFileBuffer('hello world'); const content2 = virtualFs.stringToFileBuffer('hello world 2'); const allEvents: virtualFs.HostWatchEvent[] = []; - Promise.resolve() - .then(() => fs.mkdirSync(root + '/sub1')) - .then(() => fs.writeFileSync(root + '/sub1/file1', 'hello world')) - .then(() => { - obs = host.watch(normalize('/sub1'), { recursive: true })!; - expect(obs).not.toBeNull(); - subscription = obs.subscribe((event) => { - allEvents.push(event); - }); - }) - .then(() => new Promise((resolve) => setTimeout(resolve, 100))) - // Discard the events registered so far. - .then(() => allEvents.splice(0)) - .then(() => { - host.write(normalize('/sub1/sub2/file3'), content); - host.write(normalize('/sub1/file2'), content2); - host.delete(normalize('/sub1/file1')); - }) - .then(() => new Promise((resolve) => setTimeout(resolve, 2000))) - .then(() => { - expect(allEvents.length).toBe(3); - subscription.unsubscribe(); - }) - .then(done, done.fail); + fs.mkdirSync(root + '/sub1'); + fs.writeFileSync(root + '/sub1/file1', 'hello world'); + + const obs = host.watch(normalize('/sub1'), { recursive: true }); + expect(obs).toBeDefined(); + const subscription = obs!.subscribe((event) => { + allEvents.push(event); + }); + await new Promise((resolve) => setTimeout(resolve, 100)); + + // Discard the events registered so far. + allEvents.splice(0); + + host.write(normalize('/sub1/sub2/file3'), content); + host.write(normalize('/sub1/file2'), content2); + host.delete(normalize('/sub1/file1')); + await new Promise((resolve) => setTimeout(resolve, 2000)); + + expect(allEvents.length).toBe(3); + subscription.unsubscribe(); }, 30000, ); linuxOnlyIt( 'rename to a non-existing dir', - (done) => { - Promise.resolve() - .then(() => fs.mkdirSync(root + '/rename')) - .then(() => fs.writeFileSync(root + '/rename/a.txt', 'hello world')) - .then(() => { - host.rename(normalize('/rename/a.txt'), normalize('/rename/b/c/d/a.txt')); - if (fs.existsSync(root + '/rename/b/c/d/a.txt')) { - const resContent = host.read(normalize('/rename/b/c/d/a.txt')); - const content = virtualFs.fileBufferToString(resContent); - expect(content).toEqual('hello world'); - } - }) - .then(done, done.fail); + () => { + fs.mkdirSync(root + '/rename'); + fs.writeFileSync(root + '/rename/a.txt', 'hello world'); + + host.rename(normalize('/rename/a.txt'), normalize('/rename/b/c/d/a.txt')); + if (fs.existsSync(root + '/rename/b/c/d/a.txt')) { + const resContent = host.read(normalize('/rename/b/c/d/a.txt')); + const content = virtualFs.fileBufferToString(resContent); + expect(content).toEqual('hello world'); + } }, 30000, ); diff --git a/packages/angular_devkit/core/src/json/schema/prompt_spec.ts b/packages/angular_devkit/core/src/json/schema/prompt_spec.ts index 4a7091f89c..2746798f42 100644 --- a/packages/angular_devkit/core/src/json/schema/prompt_spec.ts +++ b/packages/angular_devkit/core/src/json/schema/prompt_spec.ts @@ -11,7 +11,7 @@ import { map, mergeMap } from 'rxjs/operators'; import { CoreSchemaRegistry } from './registry'; describe('Prompt Provider', () => { - it('sets properties with answer', (done) => { + it('sets properties with answer', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -19,7 +19,7 @@ describe('Prompt Provider', () => { return { [definitions[0].id]: true }; }); - registry + await registry .compile({ properties: { test: { @@ -34,11 +34,10 @@ describe('Prompt Provider', () => { expect(data.test).toBe(true); }), ) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('supports mixed schema references', (done) => { + it('supports mixed schema references', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -50,7 +49,7 @@ describe('Prompt Provider', () => { }; }); - registry + await registry .compile({ properties: { bool: { @@ -96,12 +95,11 @@ describe('Prompt Provider', () => { expect(data.obj.deep.three).toEqual('test3-answer'); }), ) - .toPromise() - .then(done, done.fail); + .toPromise(); }); describe('with shorthand', () => { - it('supports message value', (done) => { + it('supports message value', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -112,7 +110,7 @@ describe('Prompt Provider', () => { return {}; }); - registry + await registry .compile({ properties: { test: { @@ -122,11 +120,10 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('analyzes enums', (done) => { + it('analyzes enums', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -138,7 +135,7 @@ describe('Prompt Provider', () => { return {}; }); - registry + await registry .compile({ properties: { test: { @@ -149,11 +146,10 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('analyzes boolean properties', (done) => { + it('analyzes boolean properties', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -165,7 +161,7 @@ describe('Prompt Provider', () => { return {}; }); - registry + await registry .compile({ properties: { test: { @@ -175,13 +171,12 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); }); describe('with longhand', () => { - it('supports message option', (done) => { + it('supports message option', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -192,7 +187,7 @@ describe('Prompt Provider', () => { return {}; }); - registry + await registry .compile({ properties: { test: { @@ -204,11 +199,10 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('analyzes enums WITH explicit list type', (done) => { + it('analyzes enums WITH explicit list type', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -220,7 +214,7 @@ describe('Prompt Provider', () => { return { [definitions[0].id]: 'one' }; }); - registry + await registry .compile({ properties: { test: { @@ -234,11 +228,10 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('analyzes list with true multiselect option and object items', (done) => { + it('analyzes list with true multiselect option and object items', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -254,7 +247,7 @@ describe('Prompt Provider', () => { return { [definitions[0].id]: { 'value': 'one', 'label': 'one' } }; }); - registry + await registry .compile({ properties: { test: { @@ -272,11 +265,10 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('analyzes list with false multiselect option and object items', (done) => { + it('analyzes list with false multiselect option and object items', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -292,7 +284,7 @@ describe('Prompt Provider', () => { return { [definitions[0].id]: { 'value': 'one', 'label': 'one' } }; }); - registry + await registry .compile({ properties: { test: { @@ -310,11 +302,10 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('analyzes list without multiselect option and object items', (done) => { + it('analyzes list without multiselect option and object items', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -330,7 +321,7 @@ describe('Prompt Provider', () => { return { [definitions[0].id]: { 'value': 'two', 'label': 'two' } }; }); - registry + await registry .compile({ properties: { test: { @@ -347,11 +338,10 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('analyzes enums WITHOUT explicit list type', (done) => { + it('analyzes enums WITHOUT explicit list type', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -364,7 +354,7 @@ describe('Prompt Provider', () => { return {}; }); - registry + await registry .compile({ properties: { test: { @@ -377,11 +367,10 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('analyzes enums WITHOUT explicit list type and multiselect', (done) => { + it('analyzes enums WITHOUT explicit list type and multiselect', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -394,7 +383,7 @@ describe('Prompt Provider', () => { return {}; }); - registry + await registry .compile({ properties: { test: { @@ -407,11 +396,10 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('analyzes boolean properties', (done) => { + it('analyzes boolean properties', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -423,7 +411,7 @@ describe('Prompt Provider', () => { return {}; }); - registry + await registry .compile({ properties: { test: { @@ -435,11 +423,10 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); - it('allows prompt type override', (done) => { + it('allows prompt type override', async () => { const registry = new CoreSchemaRegistry(); const data: any = {}; @@ -451,7 +438,7 @@ describe('Prompt Provider', () => { return {}; }); - registry + await registry .compile({ properties: { test: { @@ -464,8 +451,7 @@ describe('Prompt Provider', () => { }, }) .pipe(mergeMap((validator) => validator(data))) - .toPromise() - .then(done, done.fail); + .toPromise(); }); }); }); diff --git a/packages/angular_devkit/schematics/src/sink/dryrun_spec.ts b/packages/angular_devkit/schematics/src/sink/dryrun_spec.ts index 7766a2e5d1..22f4b86acb 100644 --- a/packages/angular_devkit/schematics/src/sink/dryrun_spec.ts +++ b/packages/angular_devkit/schematics/src/sink/dryrun_spec.ts @@ -18,7 +18,7 @@ const host = new virtualFs.test.TestHost({ }); describe('DryRunSink', () => { - it('works when creating everything', (done) => { + it('works when creating everything', async () => { const tree = new HostCreateTree(host); tree.create('/test', 'testing 1 2'); @@ -34,21 +34,20 @@ describe('DryRunSink', () => { expect(treeFiles).toEqual(files.map(normalize)); const sink = new DryRunSink(new virtualFs.SimpleMemoryHost()); - sink.reporter - .pipe(toArray()) - .toPromise() - .then((infos) => { - expect(infos.length).toBe(4); - for (const info of infos) { - expect(info.kind).toBe('create'); - } - }) - .then(done, done.fail); - sink.commit(tree).toPromise().then(done, done.fail); + const [infos] = await Promise.all([ + sink.reporter.pipe(toArray()).toPromise(), + sink.commit(tree).toPromise(), + ]); + + expect(infos.length).toBe(4); + + for (const info of infos) { + expect(info.kind).toBe('create'); + } }); - it('works with root', (done) => { + it('works with root', async () => { const tree = new HostTree(host); tree.create('/test', 'testing 1 2'); @@ -68,14 +67,11 @@ describe('DryRunSink', () => { outputHost.write(normalize('/hello'), virtualFs.stringToFileBuffer('')).subscribe(); const sink = new DryRunSink(outputHost); - sink.reporter - .pipe(toArray()) - .toPromise() - .then((infos) => { - expect(infos.map((x) => x.kind)).toEqual(['create', 'update']); - }) - .then(done, done.fail); + const [infos] = await Promise.all([ + sink.reporter.pipe(toArray()).toPromise(), + sink.commit(tree).toPromise(), + ]); - sink.commit(tree).toPromise().then(done, done.fail); + expect(infos.map((x) => x.kind)).toEqual(['create', 'update']); }); }); diff --git a/yarn.lock b/yarn.lock index d16d20e3c1..a67378080f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9195,13 +9195,6 @@ rimraf@~2.4.0: dependencies: glob "^6.0.1" -rimraf@~2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - rollup-plugin-sourcemaps@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz#bf93913ffe056e414419607f1d02780d7ece84ed" @@ -10108,14 +10101,6 @@ tar@^6.0.2, tar@^6.1.11, tar@^6.1.2, tar@^6.1.6: mkdirp "^1.0.3" yallist "^4.0.0" -temp@^0.9.0: - version "0.9.4" - resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.4.tgz#cd20a8580cb63635d0e4e9d4bd989d44286e7620" - integrity sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA== - dependencies: - mkdirp "^0.5.1" - rimraf "~2.6.2" - terser-webpack-plugin@^5.1.3: version "5.3.1" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54"