diff --git a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts index 0d862e8ff8..c187f155fd 100644 --- a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts @@ -22,7 +22,7 @@ import { escapeTemplateString, isString, sanitizeForFilePath } from 'playwright- import { kNoElementsFoundError, matcherHint } from './matcherHint'; import { EXPECTED_COLOR } from '../common/expectBundle'; -import { callLogText, sanitizeFilePathBeforeExtension, trimLongString } from '../util'; +import { callLogText, fileExistsAsync, sanitizeFilePathBeforeExtension, trimLongString } from '../util'; import { printReceivedStringContainExpectedSubstring } from './expect'; import { currentTestInfo } from '../common/globals'; @@ -79,6 +79,13 @@ export async function toMatchAriaSnapshot( } const fullTitleWithoutSpec = [...testInfo.titlePath.slice(1), ++snapshotNames.anonymousSnapshotIndex].join(' '); expectedPath = testInfo._resolveSnapshotPath(pathTemplate, defaultTemplate, [sanitizeForFilePath(trimLongString(fullTitleWithoutSpec)) + '.snapshot.yml']); + // in 1.51, we changed the default template to use .snapshot.yml extension + // for backwards compatibility, we check for the legacy .yml extension + if (!(await fileExistsAsync(expectedPath))) { + const legacyPath = testInfo._resolveSnapshotPath(pathTemplate, defaultTemplate, [sanitizeForFilePath(trimLongString(fullTitleWithoutSpec)) + '.yml']); + if (await fileExistsAsync(legacyPath)) + expectedPath = legacyPath; + } } expected = await fs.promises.readFile(expectedPath, 'utf8').catch(() => ''); timeout = expectedParam?.timeout ?? this.timeout; diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index 317465e49d..223b37f034 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -203,9 +203,10 @@ export function trimLongString(s: string, length = 100) { function findNthFromEnd(string: string, searchString: string, n: number) { let i = string.length; while (n--) { - i = string.lastIndexOf(searchString, i - 1); - if (i === -1) + const pos = string.lastIndexOf(searchString, i - 1); + if (pos === -1) break; + i = pos; } return i; } @@ -219,6 +220,7 @@ function multiExtname(filePath: string, maximum = 2): string { export function parsePathMultiExt(filePath: string, maximum = 2) { const startOfExtension = findNthFromEnd(filePath, '.', maximum); const result = path.parse(filePath.substring(0, startOfExtension) + '.ext'); + result.base = filePath.substring(0, startOfExtension); result.ext = filePath.substring(startOfExtension); return result; } @@ -414,6 +416,15 @@ function fileExists(resolved: string) { return fs.statSync(resolved, { throwIfNoEntry: false })?.isFile(); } +export async function fileExistsAsync(resolved: string) { + try { + const stat = await fs.promises.stat(resolved); + return stat.isFile(); + } catch { + return false; + } +} + function dirExists(resolved: string) { return fs.statSync(resolved, { throwIfNoEntry: false })?.isDirectory(); } diff --git a/tests/playwright-test/aria-snapshot-file.spec.ts b/tests/playwright-test/aria-snapshot-file.spec.ts index a8fe9fc442..38d3422f1f 100644 --- a/tests/playwright-test/aria-snapshot-file.spec.ts +++ b/tests/playwright-test/aria-snapshot-file.spec.ts @@ -130,6 +130,24 @@ test('should generate snapshot name', async ({ runInlineTest }, testInfo) => { expect(snapshot2).toBe('- heading "hello world 2" [level=1]'); }); +test('backwads compat with .yml extension', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.spec.ts-snapshots/test-1.yml': ` + - heading "hello old world" + `, + 'a.spec.ts': ` + import { test, expect } from '@playwright/test'; + test('test', async ({ page }) => { + await page.setContent(\`