Skip to content

Commit 245f4b5

Browse files
authored
fix: allow changed to be passed in config (microsoft#34473)
1 parent 3d9a9d2 commit 245f4b5

File tree

5 files changed

+117
-5
lines changed

5 files changed

+117
-5
lines changed

packages/playwright/src/common/configLoader.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,8 @@ function validateConfig(file: string, config: Config) {
240240
}
241241

242242
if ('updateSnapshots' in config && config.updateSnapshots !== undefined) {
243-
if (typeof config.updateSnapshots !== 'string' || !['all', 'none', 'missing'].includes(config.updateSnapshots))
244-
throw errorWithFile(file, `config.updateSnapshots must be one of "all", "none" or "missing"`);
243+
if (typeof config.updateSnapshots !== 'string' || !['all', 'changed', 'missing', 'none'].includes(config.updateSnapshots))
244+
throw errorWithFile(file, `config.updateSnapshots must be one of "all", "changed", "missing" or "none"`);
245245
}
246246

247247
if ('workers' in config && config.workers !== undefined) {

packages/playwright/src/matchers/toMatchAriaSnapshot.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ import path from 'path';
3030
type ToMatchAriaSnapshotExpected = {
3131
name?: string;
3232
path?: string;
33+
timeout?: number;
3334
} | string;
3435

3536
export async function toMatchAriaSnapshot(
3637
this: ExpectMatcherState,
3738
receiver: LocatorEx,
38-
expectedParam: ToMatchAriaSnapshotExpected,
39+
expectedParam?: ToMatchAriaSnapshotExpected,
3940
options: { timeout?: number } = {},
4041
): Promise<MatcherResult<string | RegExp, string>> {
4142
const matcherName = 'toMatchAriaSnapshot';
@@ -55,9 +56,11 @@ export async function toMatchAriaSnapshot(
5556
};
5657

5758
let expected: string;
59+
let timeout: number;
5860
let expectedPath: string | undefined;
5961
if (isString(expectedParam)) {
6062
expected = expectedParam;
63+
timeout = options.timeout ?? this.timeout;
6164
} else {
6265
if (expectedParam?.name) {
6366
expectedPath = testInfo.snapshotPath(sanitizeFilePathBeforeExtension(expectedParam.name));
@@ -71,6 +74,7 @@ export async function toMatchAriaSnapshot(
7174
expectedPath = testInfo.snapshotPath(sanitizeForFilePath(trimLongString(fullTitleWithoutSpec)) + '.yml');
7275
}
7376
expected = await fs.promises.readFile(expectedPath, 'utf8').catch(() => '');
77+
timeout = expectedParam?.timeout ?? this.timeout;
7478
}
7579

7680
const generateMissingBaseline = updateSnapshots === 'missing' && !expected;
@@ -84,7 +88,6 @@ export async function toMatchAriaSnapshot(
8488
}
8589
}
8690

87-
const timeout = options.timeout ?? this.timeout;
8891
expected = unshift(expected);
8992
const { matches: pass, received, log, timedOut } = await receiver._expect('to.match.aria', { expectedValue: expected, isNot: this.isNot, timeout });
9093
const typedReceived = received as MatcherReceived | typeof kNoElementsFoundError;

packages/playwright/src/program.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ function overridesFromOptions(options: { [key: string]: any }): ConfigCLIOverrid
286286
if (['all', 'changed', 'missing', 'none'].includes(options.updateSnapshots))
287287
updateSnapshots = options.updateSnapshots;
288288
else
289-
updateSnapshots = 'updateSnapshots' in options ? 'changed' : 'missing';
289+
updateSnapshots = 'updateSnapshots' in options ? 'changed' : undefined;
290290

291291
const overrides: ConfigCLIOverrides = {
292292
forbidOnly: options.forbidOnly ? true : undefined,

tests/playwright-test/aria-snapshot-file.spec.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,60 @@ test('should generate snapshot name', async ({ runInlineTest }, testInfo) => {
152152
const snapshot2 = await fs.promises.readFile(testInfo.outputPath('__snapshots__/a.spec.ts/test-name-2.yml'), 'utf8');
153153
expect(snapshot2).toBe('- heading "hello world 2" [level=1]');
154154
});
155+
156+
for (const updateSnapshots of ['all', 'changed', 'missing', 'none']) {
157+
test(`should update snapshot with the update-snapshots=${updateSnapshots} (config)`, async ({ runInlineTest }, testInfo) => {
158+
const result = await runInlineTest({
159+
'playwright.config.ts': `
160+
export default {
161+
snapshotPathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
162+
updateSnapshots: '${updateSnapshots}',
163+
};
164+
`,
165+
'a.spec.ts': `
166+
import { test, expect } from '@playwright/test';
167+
test('test', async ({ page }) => {
168+
await page.setContent(\`<h1>New content</h1>\`);
169+
await expect(page.locator('body')).toMatchAriaSnapshot({ timeout: 1 });
170+
});
171+
`,
172+
'__snapshots__/a.spec.ts/test-1.yml': '- heading "Old content" [level=1]',
173+
});
174+
175+
const rebase = updateSnapshots === 'all' || updateSnapshots === 'changed';
176+
expect(result.exitCode).toBe(rebase ? 0 : 1);
177+
if (rebase) {
178+
const snapshotOutputPath = testInfo.outputPath('__snapshots__/a.spec.ts/test-1.yml');
179+
expect(result.output).toContain(`A snapshot is generated at`);
180+
const data = fs.readFileSync(snapshotOutputPath);
181+
expect(data.toString()).toBe('- heading "New content" [level=1]');
182+
} else {
183+
expect(result.output).toContain(`expect.toMatchAriaSnapshot`);
184+
}
185+
});
186+
}
187+
188+
test('should respect timeout', async ({ runInlineTest }, testInfo) => {
189+
const result = await runInlineTest({
190+
'playwright.config.ts': `
191+
export default {
192+
snapshotPathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
193+
};
194+
`,
195+
'test.yml': `
196+
- heading "hello world"
197+
`,
198+
'a.spec.ts': `
199+
import { test, expect } from '@playwright/test';
200+
import path from 'path';
201+
test('test', async ({ page }) => {
202+
await page.setContent(\`<h1>hello world</h1>\`);
203+
await expect(page.locator('body')).toMatchAriaSnapshot({ timeout: 1 });
204+
});
205+
`,
206+
'__snapshots__/a.spec.ts/test-1.yml': '- heading "new world" [level=1]',
207+
});
208+
209+
expect(result.exitCode).toBe(1);
210+
expect(result.output).toContain(`Timed out 1ms waiting for`);
211+
});

tests/playwright-test/golden.spec.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,36 @@ test('should update snapshot with the update-snapshots flag', async ({ runInline
341341
expect(data.toString()).toBe(ACTUAL_SNAPSHOT);
342342
});
343343

344+
for (const updateSnapshots of ['all', 'changed', 'missing', 'none']) {
345+
test(`should update snapshot with the update-snapshots=${updateSnapshots} (config)`, async ({ runInlineTest }, testInfo) => {
346+
const result = await runInlineTest({
347+
'playwright.config.ts': `export default { updateSnapshots: '${updateSnapshots}' };`,
348+
...files,
349+
'a.spec.js-snapshots/snapshot.txt': 'Hello world',
350+
'a.spec.js': `
351+
const { test, expect } = require('./helper');
352+
test('is a test', ({}) => {
353+
expect('Hello world updated').toMatchSnapshot('snapshot.txt');
354+
});
355+
`
356+
});
357+
358+
const rebase = updateSnapshots === 'all' || updateSnapshots === 'changed';
359+
expect(result.exitCode).toBe(rebase ? 0 : 1);
360+
if (rebase) {
361+
const snapshotOutputPath = testInfo.outputPath('a.spec.js-snapshots/snapshot.txt');
362+
if (updateSnapshots === 'all')
363+
expect(result.output).toContain(`${snapshotOutputPath} is not the same, writing actual.`);
364+
if (updateSnapshots === 'changed')
365+
expect(result.output).toContain(`${snapshotOutputPath} does not match, writing actual.`);
366+
const data = fs.readFileSync(snapshotOutputPath);
367+
expect(data.toString()).toBe('Hello world updated');
368+
} else {
369+
expect(result.output).toContain(`toMatchSnapshot`);
370+
}
371+
});
372+
}
373+
344374
test('should ignore text snapshot with the ignore-snapshots flag', async ({ runInlineTest }, testInfo) => {
345375
const EXPECTED_SNAPSHOT = 'Hello world';
346376
const ACTUAL_SNAPSHOT = 'Hello world updated';
@@ -1140,3 +1170,25 @@ test('should throw if a Promise was passed to toMatchSnapshot', async ({ runInli
11401170
expect(result.exitCode).toBe(0);
11411171
expect(result.passed).toBe(1);
11421172
});
1173+
1174+
1175+
test('should respect update snapshot option from config', async ({ runInlineTest }, testInfo) => {
1176+
const EXPECTED_SNAPSHOT = 'Hello world';
1177+
const ACTUAL_SNAPSHOT = 'Hello world updated';
1178+
const result = await runInlineTest({
1179+
...files,
1180+
'a.spec.js-snapshots/snapshot.txt': EXPECTED_SNAPSHOT,
1181+
'a.spec.js': `
1182+
const { test, expect } = require('./helper');
1183+
test('is a test', ({}) => {
1184+
expect('${ACTUAL_SNAPSHOT}').toMatchSnapshot('snapshot.txt');
1185+
});
1186+
`
1187+
}, { 'update-snapshots': true });
1188+
1189+
expect(result.exitCode).toBe(0);
1190+
const snapshotOutputPath = testInfo.outputPath('a.spec.js-snapshots/snapshot.txt');
1191+
expect(result.output).toContain(`${snapshotOutputPath} does not match, writing actual.`);
1192+
const data = fs.readFileSync(snapshotOutputPath);
1193+
expect(data.toString()).toBe(ACTUAL_SNAPSHOT);
1194+
});

0 commit comments

Comments
 (0)