Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 61e25fb

Browse filesBrowse files
clydinalan-agius4
authored andcommitted
fix(@angular/build): load zone.js dynamically for library unit tests
When unit testing library targets with the unit-test builder, the build target (ng-packagr) does not have a 'polyfills' configuration. This caused the builder to fall back to the 'dynamic' zone testing strategy, which only dynamically imports zone.js/testing at runtime if Zone is already defined. Since the main zone.js library was never loaded, Zone was undefined, and library tests relying on TestBed/fakeAsync failed. This commit introduces a new 'dynamic-zone' zone testing strategy. If polyfills is undefined (meaning we are running a library target) and zone.js is installed/resolvable, both zone.js and zone.js/testing are dynamically imported at startup, resolving the failure. Fixes #33477
1 parent 2d3eb7f commit 61e25fb
Copy full SHA for 61e25fb

2 files changed

+56-3Lines changed: 56 additions & 3 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎packages/angular/build/src/builders/unit-test/runners/vitest/build-options.ts‎

Copy file name to clipboardExpand all lines: packages/angular/build/src/builders/unit-test/runners/vitest/build-options.ts
+13-3Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function createTestBedInitVirtualFile(
3333
providersFile: string | undefined,
3434
projectSourceRoot: string,
3535
teardown: boolean,
36-
zoneTestingStrategy: 'none' | 'static' | 'dynamic',
36+
zoneTestingStrategy: 'none' | 'static' | 'dynamic' | 'dynamic-zone',
3737
hasLocalize: boolean,
3838
): string {
3939
let providersImport = 'const providers = [];';
@@ -53,6 +53,10 @@ function createTestBedInitVirtualFile(
5353
// It must be imported dynamically to avoid a static dependency on 'zone.js'.
5454
await import('zone.js/testing');
5555
}`;
56+
} else if (zoneTestingStrategy === 'dynamic-zone') {
57+
zoneTestingSnippet = `
58+
await import('zone.js');
59+
await import('zone.js/testing');`;
5660
}
5761

5862
// The DynamicDOMTestComponentRenderer is used to avoid stale document references
@@ -150,12 +154,12 @@ function adjustOutputHashing(hashing?: OutputHashing): OutputHashing {
150154
*
151155
* @param buildOptions The partial application builder options.
152156
* @param projectSourceRoot The root directory of the project source.
153-
* @returns The resolved zone testing strategy ('none', 'static', 'dynamic').
157+
* @returns The resolved zone testing strategy ('none', 'static', 'dynamic', 'dynamic-zone').
154158
*/
155159
function getZoneTestingStrategy(
156160
buildOptions: Partial<ApplicationBuilderInternalOptions>,
157161
projectSourceRoot: string,
158-
): 'none' | 'static' | 'dynamic' {
162+
): 'none' | 'static' | 'dynamic' | 'dynamic-zone' {
159163
if (buildOptions.polyfills?.includes('zone.js/testing')) {
160164
return 'none';
161165
}
@@ -168,6 +172,12 @@ function getZoneTestingStrategy(
168172
const projectRequire = createRequire(path.join(projectSourceRoot, 'package.json'));
169173
projectRequire.resolve('zone.js');
170174

175+
// If polyfills is undefined (e.g. library build target), load zone.js dynamically.
176+
// If polyfills is defined but doesn't include zone.js (e.g. zoneless application), do NOT load zone.js.
177+
if (buildOptions.polyfills === undefined) {
178+
return 'dynamic-zone';
179+
}
180+
171181
return 'dynamic';
172182
} catch {
173183
return 'none';
Collapse file

‎packages/angular/build/src/builders/unit-test/tests/behavior/vitest-zone-init_spec.ts‎

Copy file name to clipboardExpand all lines: packages/angular/build/src/builders/unit-test/tests/behavior/vitest-zone-init_spec.ts
+43Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,48 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => {
6767
const { result } = await harness.executeOnce();
6868
expect(result?.success).toBe(true);
6969
});
70+
71+
it('should load Zone and Zone testing support when testing a library and zone.js is installed', async () => {
72+
harness.withBuilderTarget(
73+
'build',
74+
async () => ({ success: true }),
75+
{
76+
project: 'ng-package.json',
77+
},
78+
{
79+
builderName: '@angular/build:ng-packagr',
80+
},
81+
);
82+
83+
await harness.writeFile(
84+
'ng-package.json',
85+
JSON.stringify({
86+
lib: {
87+
entryFile: 'src/public-api.ts',
88+
},
89+
}),
90+
);
91+
92+
harness.useTarget('test', {
93+
...BASE_OPTIONS,
94+
include: ['src/app.component.spec.ts'],
95+
});
96+
97+
await harness.writeFile(
98+
'src/app.component.spec.ts',
99+
`
100+
import { describe, it, expect } from 'vitest';
101+
102+
describe('Library Zone Test', () => {
103+
it('should have Zone defined', () => {
104+
expect((globalThis as any).Zone).toBeDefined();
105+
});
106+
});
107+
`,
108+
);
109+
110+
const { result } = await harness.executeOnce();
111+
expect(result?.success).toBeTrue();
112+
});
70113
});
71114
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.