Skip to content

Commit 7999841

Browse files
committed
cherry-pick(#26390): chore: allow merging defineConfig
1 parent 56b22fa commit 7999841

File tree

5 files changed

+111
-4
lines changed

5 files changed

+111
-4
lines changed

packages/playwright-test/src/common/configLoader.ts

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,53 @@ import { addToCompilationCache } from '../transform/compilationCache';
2727
import { initializeEsmLoader } from './esmLoaderHost';
2828

2929
const kDefineConfigWasUsed = Symbol('defineConfigWasUsed');
30-
export const defineConfig = (config: any) => {
31-
config[kDefineConfigWasUsed] = true;
32-
return config;
30+
export const defineConfig = (...configs: any[]) => {
31+
let result = configs[0];
32+
for (let i = 1; i < configs.length; ++i) {
33+
const config = configs[i];
34+
result = {
35+
...result,
36+
...config,
37+
expect: {
38+
...result.expect,
39+
...config.expect,
40+
},
41+
use: {
42+
...result.use,
43+
...config.use,
44+
},
45+
webServer: [
46+
...(Array.isArray(result.webServer) ? result.webServer : (result.webServer ? [result.webServer] : [])),
47+
...(Array.isArray(config.webServer) ? config.webServer : (config.webServer ? [config.webServer] : [])),
48+
]
49+
};
50+
51+
const projectOverrides = new Map<string, any>();
52+
for (const project of config.projects || [])
53+
projectOverrides.set(project.name, project);
54+
55+
const projects = [];
56+
for (const project of result.projects || []) {
57+
const projectOverride = projectOverrides.get(project.name);
58+
if (projectOverride) {
59+
projects.push({
60+
...project,
61+
...projectOverride,
62+
use: {
63+
...project.use,
64+
...projectOverride.use,
65+
}
66+
});
67+
projectOverrides.delete(project.name);
68+
} else {
69+
projects.push(project);
70+
}
71+
}
72+
projects.push(...projectOverrides.values());
73+
result.projects = projects;
74+
}
75+
result[kDefineConfigWasUsed] = true;
76+
return result;
3377
};
3478

3579
export class ConfigLoader {

packages/playwright-test/types/test.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5022,6 +5022,9 @@ export const expect: Expect;
50225022
export function defineConfig(config: PlaywrightTestConfig): PlaywrightTestConfig;
50235023
export function defineConfig<T>(config: PlaywrightTestConfig<T>): PlaywrightTestConfig<T>;
50245024
export function defineConfig<T, W>(config: PlaywrightTestConfig<T, W>): PlaywrightTestConfig<T, W>;
5025+
export function defineConfig(config: PlaywrightTestConfig, ...configs: PlaywrightTestConfig[]): PlaywrightTestConfig;
5026+
export function defineConfig<T>(config: PlaywrightTestConfig<T>, ...configs: PlaywrightTestConfig[]): PlaywrightTestConfig<T>;
5027+
export function defineConfig<T, W>(config: PlaywrightTestConfig<T, W>, ...configs: PlaywrightTestConfig[]): PlaywrightTestConfig<T, W>;
50255028

50265029
// This is required to not export everything by default. See https://github.com/Microsoft/TypeScript/issues/19545#issuecomment-340490459
50275030
export {};

tests/library/playwright.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import { config as loadEnv } from 'dotenv';
1818
loadEnv({ path: path.join(__dirname, '..', '..', '.env'), override: true });
1919

20-
import type { Config, PlaywrightTestOptions, PlaywrightWorkerOptions, ReporterDescription } from '@playwright/test';
20+
import { type Config, type PlaywrightTestOptions, type PlaywrightWorkerOptions, type ReporterDescription } from '@playwright/test';
2121
import * as path from 'path';
2222
import type { TestModeWorkerOptions } from '../config/testModeFixtures';
2323
import type { TestModeName } from '../config/testMode';

tests/playwright-test/config.spec.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,3 +497,60 @@ test('should not allow tracesDir in launchOptions', async ({ runTSC }) => {
497497
});
498498
expect(result.exitCode).not.toBe(0);
499499
});
500+
501+
test('should merge configs', async ({ runInlineTest }) => {
502+
const result = await runInlineTest({
503+
'playwright.config.ts': `
504+
import { defineConfig, expect } from '@playwright/test';
505+
const baseConfig = defineConfig({
506+
timeout: 10,
507+
use: {
508+
foo: 1,
509+
},
510+
expect: {
511+
timeout: 11,
512+
},
513+
projects: [
514+
{
515+
name: 'A',
516+
timeout: 20,
517+
}
518+
],
519+
});
520+
const derivedConfig = defineConfig(baseConfig, {
521+
timeout: 30,
522+
use: {
523+
bar: 2,
524+
},
525+
expect: {
526+
timeout: 12,
527+
},
528+
projects: [
529+
{ name: 'B', timeout: 40 },
530+
{ name: 'A', timeout: 50 },
531+
],
532+
webServer: {
533+
command: 'echo 123',
534+
}
535+
});
536+
537+
expect(derivedConfig).toEqual(expect.objectContaining({
538+
timeout: 30,
539+
use: { foo: 1, bar: 2 },
540+
expect: { timeout: 12 },
541+
projects: [
542+
{ name: 'B', timeout: 40, use: {} },
543+
{ name: 'A', timeout: 50, use: {} }
544+
],
545+
webServer: [{
546+
command: 'echo 123',
547+
}]
548+
}));
549+
`,
550+
'a.test.ts': `
551+
import { test } from '@playwright/test';
552+
test('pass', async ({}) => {});
553+
`
554+
});
555+
expect(result.exitCode).toBe(0);
556+
});

utils/generate_types/overrides-test.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,9 @@ export const expect: Expect;
400400
export function defineConfig(config: PlaywrightTestConfig): PlaywrightTestConfig;
401401
export function defineConfig<T>(config: PlaywrightTestConfig<T>): PlaywrightTestConfig<T>;
402402
export function defineConfig<T, W>(config: PlaywrightTestConfig<T, W>): PlaywrightTestConfig<T, W>;
403+
export function defineConfig(config: PlaywrightTestConfig, ...configs: PlaywrightTestConfig[]): PlaywrightTestConfig;
404+
export function defineConfig<T>(config: PlaywrightTestConfig<T>, ...configs: PlaywrightTestConfig[]): PlaywrightTestConfig<T>;
405+
export function defineConfig<T, W>(config: PlaywrightTestConfig<T, W>, ...configs: PlaywrightTestConfig[]): PlaywrightTestConfig<T, W>;
403406

404407
// This is required to not export everything by default. See https://github.com/Microsoft/TypeScript/issues/19545#issuecomment-340490459
405408
export {};

0 commit comments

Comments
 (0)