From 90bc711e9d8dec25a941f3faade5b42912dd7b40 Mon Sep 17 00:00:00 2001 From: Harald Wartig Date: Fri, 20 Feb 2026 12:02:27 +0100 Subject: [PATCH] fix: error out if node_modules doesn't contain correct @playwright/test version The version of @playwright/test in node_modules might be out of sync with what is required in package.json/package-lock.json. In those rare cases the cli will report an incorrect playwright version to the API which will cause checks to fail as checks rely on the playwright version noted in lock files. --- packages/cli/src/constructs/api-check.ts | 1 - packages/cli/src/services/__tests__/util.spec.ts | 10 +++++----- packages/cli/src/services/util.ts | 16 ++++++++++++++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/constructs/api-check.ts b/packages/cli/src/constructs/api-check.ts index 23e9f95dc..b9490b184 100644 --- a/packages/cli/src/constructs/api-check.ts +++ b/packages/cli/src/constructs/api-check.ts @@ -11,7 +11,6 @@ import { DeprecatedPropertyDiagnostic, InvalidPropertyValueDiagnostic } from './ import { ApiCheckBundle, ApiCheckBundleProps } from './api-check-bundle' import { Assertion } from './api-assertion' import { validateResponseTimes } from './internal/common-diagnostics' -import { Runtime } from '../runtimes' /** * Default configuration that can be applied to API checks. diff --git a/packages/cli/src/services/__tests__/util.spec.ts b/packages/cli/src/services/__tests__/util.spec.ts index b39cecb89..be035c8e8 100644 --- a/packages/cli/src/services/__tests__/util.spec.ts +++ b/packages/cli/src/services/__tests__/util.spec.ts @@ -30,17 +30,17 @@ describe('util', () => { }) describe('getPlaywrightVersionFromPackage()', () => { - it('should throw error when playwright package is not found', () => { + it('should throw error when playwright package is not found', async () => { // Use a directory that doesn't have playwright installed const nonExistentDir = '/tmp/non-existent-dir' - expect(() => getPlaywrightVersionFromPackage(nonExistentDir)) - .toThrow('Could not find @playwright/test package. Make sure it is installed.') + await expect(getPlaywrightVersionFromPackage(nonExistentDir)) + .rejects.toThrow('Could not find @playwright/test package. Make sure it is installed.') }) - it('should get version from installed playwright package', () => { + it('should get version from installed playwright package', async () => { // Use the current working directory which should have playwright installed const currentDir = process.cwd() - const version = getPlaywrightVersionFromPackage(currentDir) + const version = await getPlaywrightVersionFromPackage(currentDir) // Should return a valid semver version expect(version).toMatch(/^\d+\.\d+\.\d+/) diff --git a/packages/cli/src/services/util.ts b/packages/cli/src/services/util.ts index b902ef4b0..9ee78a5bc 100644 --- a/packages/cli/src/services/util.ts +++ b/packages/cli/src/services/util.ts @@ -16,6 +16,7 @@ import { createHash } from 'crypto' import { Session } from '../constructs/project' import semver from 'semver' import { existsSync } from 'fs' +import { detectNearestPackageJson } from './check-parser/package-files/package-manager' export interface GitInformation { commitId: string @@ -184,7 +185,7 @@ export async function bundlePlayWrightProject ( const pwConfigParsed = new PlaywrightConfig(filePath, pwtConfig) - const playwrightVersion = getPlaywrightVersionFromPackage(dir) + const playwrightVersion = await getPlaywrightVersionFromPackage(dir) const [cacheHash] = await Promise.all([ getCacheHash(lockfile), @@ -217,7 +218,7 @@ export async function getCacheHash (lockFile: string): Promise { return hash.digest('hex') } -export function getPlaywrightVersionFromPackage (cwd: string): string { +export async function getPlaywrightVersionFromPackage (cwd: string): Promise { try { const playwrightPath = require.resolve('@playwright/test/package.json', { paths: [cwd] }) // eslint-disable-next-line @typescript-eslint/no-require-imports @@ -228,6 +229,17 @@ export function getPlaywrightVersionFromPackage (cwd: string): string { throw new Error('Invalid version found in @playwright/test package.json') } + const packageJson = await detectNearestPackageJson(cwd) + const range = + packageJson.dependencies?.['@playwright/test'] + ?? packageJson.devDependencies?.['@playwright/test'] + if (range && !semver.satisfies(version, range)) { + throw new Error( + `Installed @playwright/test version ${version} does not satisfy the required range "${range}" in package.json. ` + + 'Please run your package manager\'s install command to sync node_modules.', + ) + } + return version } catch (error) { // @ts-ignore