Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/cli/src/constructs/api-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 5 additions & 5 deletions packages/cli/src/services/__tests__/util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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+/)
Expand Down
16 changes: 14 additions & 2 deletions packages/cli/src/services/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -217,7 +218,7 @@ export async function getCacheHash (lockFile: string): Promise<string> {
return hash.digest('hex')
}

export function getPlaywrightVersionFromPackage (cwd: string): string {
export async function getPlaywrightVersionFromPackage (cwd: string): Promise<string> {
try {
const playwrightPath = require.resolve('@playwright/test/package.json', { paths: [cwd] })
// eslint-disable-next-line @typescript-eslint/no-require-imports
Expand All @@ -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)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I already approved the PR and unfortunately you already merged, but I had a late suggestion. There is a possibility that the range is not valid. For example it could point to a local copy of the package or be something like "catalog:" w/ pnpm. For invalid ranges, satisfies() just returns false so they'll always hit this error. We should probably do this instead:

if (range) {
  const validRange = semver.validRange(range)
  if (validRange && !semver.satisfies(version, validRange)) {
    // throw
    // ...

Copy link
Contributor Author

@hwartig hwartig Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhrg right. good catch, I'll prep the PR

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
Expand Down