From 106c8cef01b5a87b6b3ce91dc6ad7ad9afeb1f1b Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Wed, 26 Feb 2025 14:53:59 +0100 Subject: [PATCH] add special case for ext --- .../src/matchers/toMatchAriaSnapshot.ts | 7 +++-- packages/playwright/src/util.ts | 30 ++----------------- packages/playwright/src/worker/testInfo.ts | 12 ++++---- 3 files changed, 13 insertions(+), 36 deletions(-) diff --git a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts index c187f155fd..0c76a97c68 100644 --- a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts @@ -70,7 +70,8 @@ export async function toMatchAriaSnapshot( timeout = options.timeout ?? this.timeout; } else { if (expectedParam?.name) { - expectedPath = testInfo._resolveSnapshotPath(pathTemplate, defaultTemplate, [sanitizeFilePathBeforeExtension(expectedParam.name)]); + const ext = expectedParam.name!.endsWith('.snapshot.yml') ? '.snapshot.yml' : undefined; + expectedPath = testInfo._resolveSnapshotPath(pathTemplate, defaultTemplate, [sanitizeFilePathBeforeExtension(expectedParam.name, ext)]); } else { let snapshotNames = (testInfo as any)[snapshotNamesSymbol] as SnapshotNames; if (!snapshotNames) { @@ -78,11 +79,11 @@ export async function toMatchAriaSnapshot( (testInfo as any)[snapshotNamesSymbol] = snapshotNames; } const fullTitleWithoutSpec = [...testInfo.titlePath.slice(1), ++snapshotNames.anonymousSnapshotIndex].join(' '); - expectedPath = testInfo._resolveSnapshotPath(pathTemplate, defaultTemplate, [sanitizeForFilePath(trimLongString(fullTitleWithoutSpec)) + '.snapshot.yml']); + 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']); + const legacyPath = testInfo._resolveSnapshotPath(pathTemplate, defaultTemplate, [sanitizeForFilePath(trimLongString(fullTitleWithoutSpec))], '.yml'); if (await fileExistsAsync(legacyPath)) expectedPath = legacyPath; } diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index 223b37f034..a2e0810f59 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -200,39 +200,13 @@ export function trimLongString(s: string, length = 100) { return s.substring(0, start) + middle + s.slice(-end); } -function findNthFromEnd(string: string, searchString: string, n: number) { - let i = string.length; - while (n--) { - const pos = string.lastIndexOf(searchString, i - 1); - if (pos === -1) - break; - i = pos; - } - return i; -} - -function multiExtname(filePath: string, maximum = 2): string { - const basename = path.basename(filePath); - const startOfExtension = findNthFromEnd(basename, '.', maximum); - return basename.substring(startOfExtension); -} - -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; -} - export function addSuffixToFilePath(filePath: string, suffix: string): string { - const ext = multiExtname(filePath); + const ext = path.extname(filePath); const base = filePath.substring(0, filePath.length - ext.length); return base + suffix + ext; } -export function sanitizeFilePathBeforeExtension(filePath: string): string { - const ext = multiExtname(filePath); +export function sanitizeFilePathBeforeExtension(filePath: string, ext = path.extname(filePath)): string { const base = filePath.substring(0, filePath.length - ext.length); return sanitizeForFilePath(base) + ext; } diff --git a/packages/playwright/src/worker/testInfo.ts b/packages/playwright/src/worker/testInfo.ts index 20e5837010..d72ba7699f 100644 --- a/packages/playwright/src/worker/testInfo.ts +++ b/packages/playwright/src/worker/testInfo.ts @@ -20,7 +20,7 @@ import path from 'path'; import { captureRawStack, monotonicTime, sanitizeForFilePath, stringifyStackFrames, currentZone } from 'playwright-core/lib/utils'; import { TimeoutManager, TimeoutManagerError, kMaxDeadline } from './timeoutManager'; -import { debugTest, filteredStackTrace, formatLocation, getContainedPath, normalizeAndSaveAttachment, trimLongString, windowsFilesystemFriendlyLength, parsePathMultiExt } from '../util'; +import { debugTest, filteredStackTrace, formatLocation, getContainedPath, normalizeAndSaveAttachment, trimLongString, windowsFilesystemFriendlyLength } from '../util'; import { TestTracing } from './testTracing'; import { testInfoError } from './util'; import { FloatingPromiseScope } from './floatingPromiseScope'; @@ -463,9 +463,11 @@ export class TestInfoImpl implements TestInfo { return sanitizeForFilePath(trimLongString(fullTitleWithoutSpec)); } - _resolveSnapshotPath(template: string | undefined, defaultTemplate: string, pathSegments: string[]) { + _resolveSnapshotPath(template: string | undefined, defaultTemplate: string, pathSegments: string[], extension?: string) { const subPath = path.join(...pathSegments); - const parsedSubPath = parsePathMultiExt(subPath); + const dir = path.dirname(subPath); + const ext = extension ?? path.extname(subPath); + const name = path.basename(subPath, ext); const relativeTestFilePath = path.relative(this.project.testDir, this._requireFile); const parsedRelativeTestFilePath = path.parse(relativeTestFilePath); const projectNamePathSegment = sanitizeForFilePath(this.project.name); @@ -481,8 +483,8 @@ export class TestInfoImpl implements TestInfo { .replace(/\{(.)?testName\}/g, '$1' + this._fsSanitizedTestName()) .replace(/\{(.)?testFileName\}/g, '$1' + parsedRelativeTestFilePath.base) .replace(/\{(.)?testFilePath\}/g, '$1' + relativeTestFilePath) - .replace(/\{(.)?arg\}/g, '$1' + path.join(parsedSubPath.dir, parsedSubPath.name)) - .replace(/\{(.)?ext\}/g, parsedSubPath.ext ? '$1' + parsedSubPath.ext : ''); + .replace(/\{(.)?arg\}/g, '$1' + path.join(dir, name)) + .replace(/\{(.)?ext\}/g, ext ? '$1' + ext : ''); return path.normalize(path.resolve(this._configInternal.configDir, snapshotPath)); }