Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export class VitestExecutor implements TestExecutor {
watch: null,
},
plugins: [
createVitestConfigPlugin({
await createVitestConfigPlugin({
browser: browserOptions.browser,
coverage,
projectName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ async function findTestEnvironment(
}
}

export function createVitestConfigPlugin(options: VitestConfigPluginOptions): VitestPlugins[0] {
export async function createVitestConfigPlugin(
options: VitestConfigPluginOptions,
): Promise<VitestPlugins[0]> {
const {
include,
browser,
Expand All @@ -69,6 +71,8 @@ export function createVitestConfigPlugin(options: VitestConfigPluginOptions): Vi
projectSourceRoot,
} = options;

const { mergeConfig } = await import('vitest/config');

return {
name: 'angular:vitest-configuration',
async config(config) {
Expand All @@ -90,17 +94,6 @@ export function createVitestConfigPlugin(options: VitestConfigPluginOptions): Vi
delete testConfig.include;
}

// The user's setup files should be appended to the CLI's setup files.
const combinedSetupFiles = [...setupFiles];
if (testConfig?.setupFiles) {
if (typeof testConfig.setupFiles === 'string') {
combinedSetupFiles.push(testConfig.setupFiles);
} else if (Array.isArray(testConfig.setupFiles)) {
combinedSetupFiles.push(...testConfig.setupFiles);
}
delete testConfig.setupFiles;
}

// Merge user-defined plugins from the Vitest config with the CLI's internal plugins.
if (config.plugins) {
const userPlugins = config.plugins.filter(
Expand All @@ -115,38 +108,49 @@ export function createVitestConfigPlugin(options: VitestConfigPluginOptions): Vi
if (userPlugins.length > 0) {
projectPlugins.push(...userPlugins);
}
delete config.plugins;
}

const projectResolver = createRequire(projectSourceRoot + '/').resolve;

const projectConfig: UserWorkspaceConfig = {
const projectDefaults: UserWorkspaceConfig = {
test: {
setupFiles,
globals: true,
// Default to `false` to align with the Karma/Jasmine experience.
isolate: false,
},
optimizeDeps: {
noDiscovery: true,
include: options.optimizeDepsInclude,
},
};

const { optimizeDeps, resolve } = config;
const projectOverrides: UserWorkspaceConfig = {
test: {
...testConfig,
name: projectName,
setupFiles: combinedSetupFiles,
include,
globals: testConfig?.globals ?? true,
// Default to `false` to align with the Karma/Jasmine experience.
isolate: testConfig?.isolate ?? false,
// CLI provider browser options override, if present
...(browser ? { browser } : {}),
// If the user has not specified an environment, use a smart default.
...(!testConfig?.environment
? { environment: await findTestEnvironment(projectResolver) }
: {}),
},
optimizeDeps: {
noDiscovery: true,
include: options.optimizeDepsInclude,
},
plugins: projectPlugins,
optimizeDeps,
resolve,
};

const projectBase = mergeConfig(projectDefaults, testConfig ? { test: testConfig } : {});
const projectConfig = mergeConfig(projectBase, projectOverrides);

return {
test: {
coverage: await generateCoverageOption(options.coverage, projectName),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...(reporters ? ({ reporters } as any) : {}),
...(browser ? { browser } : {}),
projects: [projectConfig],
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,53 +16,33 @@ import {
} from '../setup';

describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => {
xdescribe('Option: "browsers"', () => {
describe('Option: "browsers"', () => {
beforeEach(async () => {
setupApplicationTarget(harness);
});

it('should use jsdom when browsers is not provided', async () => {
it('should use DOM emulation when browsers is not provided', async () => {
harness.useTarget('test', {
...BASE_OPTIONS,
browsers: undefined,
});

const { result, logs } = await harness.executeOnce();
const { result } = await harness.executeOnce();
expect(result?.success).toBeTrue();
expectLog(logs, 'Using jsdom in Node.js for test execution.');
});

it('should fail when browsers is empty', async () => {
harness.useTarget('test', {
...BASE_OPTIONS,
browsers: [],
});

await expectAsync(harness.executeOnce()).toBeRejectedWithError(
/must NOT have fewer than 1 items/,
);
});

it('should launch a browser when provided', async () => {
it('should fail when a browser is requested but no provider is installed', async () => {
harness.useTarget('test', {
...BASE_OPTIONS,
browsers: ['chrome'],
});

const { result, logs } = await harness.executeOnce();
expect(result?.success).toBeTrue();
expectLog(logs, /Starting browser "chrome"/);
});

it('should launch a browser in headless mode when specified', async () => {
harness.useTarget('test', {
...BASE_OPTIONS,
browsers: ['chromeheadless'],
});

const { result, logs } = await harness.executeOnce();
expect(result?.success).toBeTrue();
expectLog(logs, /Starting browser "chrome" in headless mode/);
expect(result?.success).toBeFalse();
expectLog(
logs,
`The "browsers" option requires either "@vitest/browser-playwright", "@vitest/browser-webdriverio", or "@vitest/browser-preview" to be installed`,
);
});
});
});