Skip to content

Commit 9a50040

Browse files
committed
fix(@angular/build): show unit-test error for missing vitest browser package
When using the experimental `unit-test` builder with the `vitest` runner and the `browsers` option, an error will now be reported if the `@vitest/browser` package is not found. Previously, the tests would attempt to execute and produce a runtime error and stack trace. Now an explicit error with instructions to install the package will be printed to the console prior to building and executing the tests.
1 parent bd18065 commit 9a50040

File tree

1 file changed

+55
-22
lines changed
  • packages/angular/build/src/builders/unit-test

1 file changed

+55
-22
lines changed

packages/angular/build/src/builders/unit-test/builder.ts

+55-22
Original file line numberDiff line numberDiff line change
@@ -181,27 +181,17 @@ export async function* execute(
181181
let instance: import('vitest/node').Vitest | undefined;
182182

183183
// Setup vitest browser options if configured
184-
let browser: import('vitest/node').BrowserConfigOptions | undefined;
185-
if (normalizedOptions.browsers) {
186-
const provider = findBrowserProvider(projectSourceRoot);
187-
if (!provider) {
188-
context.logger.error(
189-
'The "browsers" option requires either "playwright" or "webdriverio" to be installed within the project.' +
190-
' Please install one of these packages and rerun the test command.',
191-
);
192-
193-
return { success: false };
194-
}
184+
const { browser, errors } = setupBrowserConfiguration(
185+
normalizedOptions.browsers,
186+
projectSourceRoot,
187+
);
188+
if (errors?.length) {
189+
errors.forEach((error) => context.logger.error(error));
195190

196-
browser = {
197-
enabled: true,
198-
provider,
199-
instances: normalizedOptions.browsers.map((browserName) => ({
200-
browser: browserName,
201-
})),
202-
};
191+
return { success: false };
203192
}
204193

194+
// Add setup file entries for TestBed initialization and project polyfills
205195
const setupFiles = ['init-testbed.js'];
206196
if (buildTargetOptions?.polyfills?.length) {
207197
setupFiles.push('polyfills.js');
@@ -252,11 +242,9 @@ export async function* execute(
252242
}
253243

254244
function findBrowserProvider(
255-
projectSourceRoot: string,
245+
projectResolver: NodeJS.RequireResolve,
256246
): import('vitest/node').BrowserBuiltinProvider | undefined {
257-
const projectResolver = createRequire(projectSourceRoot + '/').resolve;
258-
259-
// These must be installed in the project to be used
247+
// One of these must be installed in the project to use browser testing
260248
const vitestBuiltinProviders = ['playwright', 'webdriverio'] as const;
261249

262250
for (const providerName of vitestBuiltinProviders) {
@@ -267,3 +255,48 @@ function findBrowserProvider(
267255
} catch {}
268256
}
269257
}
258+
259+
function setupBrowserConfiguration(
260+
browsers: string[] | undefined,
261+
projectSourceRoot: string,
262+
): { browser?: import('vitest/node').BrowserConfigOptions; errors?: string[] } {
263+
if (browsers === undefined) {
264+
return {};
265+
}
266+
267+
const projectResolver = createRequire(projectSourceRoot + '/').resolve;
268+
let errors: string[] | undefined;
269+
270+
try {
271+
projectResolver('@vitest/browser');
272+
} catch {
273+
errors ??= [];
274+
errors.push(
275+
'The "browsers" option requires the "@vitest/browser" package to be installed within the project.' +
276+
' Please install this package and rerun the test command.',
277+
);
278+
}
279+
280+
const provider = findBrowserProvider(projectResolver);
281+
if (!provider) {
282+
errors ??= [];
283+
errors.push(
284+
'The "browsers" option requires either "playwright" or "webdriverio" to be installed within the project.' +
285+
' Please install one of these packages and rerun the test command.',
286+
);
287+
}
288+
289+
if (errors) {
290+
return { errors };
291+
}
292+
293+
const browser = {
294+
enabled: true,
295+
provider,
296+
instances: browsers.map((browserName) => ({
297+
browser: browserName,
298+
})),
299+
};
300+
301+
return { browser };
302+
}

0 commit comments

Comments
 (0)