Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
/tmp
/yarn.lock
node_modules
!packages/cli/src/services/__tests__/fixtures/playwright-json/**
.vscode
.checkly
.DS_Store
Expand All @@ -17,4 +18,4 @@ local
.tsbuildinfo
**/checkly-github-report.md
**/checkly-summary.md
**/e2e/__tests__/fixtures/empty-project/e2e-test-project-*
**/e2e/__tests__/fixtures/empty-project/e2e-test-project-*
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,4 @@
"optional": true
}
}
}
}
4 changes: 4 additions & 0 deletions packages/cli/src/constructs/playwright-check-bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface PlaywrightCheckBundleProps {
codeBundlePath?: string
browsers?: string[]
cacheHash?: string
playwrightVersion?: string
}

export class PlaywrightCheckBundle implements Bundle {
Expand All @@ -15,13 +16,15 @@ export class PlaywrightCheckBundle implements Bundle {
codeBundlePath?: string
browsers?: string[]
cacheHash?: string
playwrightVersion?: string

constructor (playwrightCheck: PlaywrightCheck, props: PlaywrightCheckBundleProps) {
this.playwrightCheck = playwrightCheck
this.groupId = props.groupId
this.codeBundlePath = props.codeBundlePath
this.browsers = props.browsers
this.cacheHash = props.cacheHash
this.playwrightVersion = props.playwrightVersion
}

synthesize () {
Expand All @@ -31,6 +34,7 @@ export class PlaywrightCheckBundle implements Bundle {
codeBundlePath: this.codeBundlePath,
browsers: this.browsers,
cacheHash: this.cacheHash,
playwrightVersion: this.playwrightVersion
}
}
}
6 changes: 4 additions & 2 deletions packages/cli/src/constructs/playwright-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ export class PlaywrightCheck extends RuntimeCheck {
let dir = ''
try {
const {
outputFile, browsers, relativePlaywrightConfigPath, cacheHash,
outputFile, browsers, relativePlaywrightConfigPath, cacheHash, playwrightVersion
} = await bundlePlayWrightProject(playwrightConfigPath, include)
dir = outputFile
const { data: { key } } = await PlaywrightCheck.uploadPlaywrightProject(dir)
return { key, browsers, relativePlaywrightConfigPath, cacheHash }
return { key, browsers, relativePlaywrightConfigPath, cacheHash, playwrightVersion }
} finally {
await cleanup(dir)
}
Expand Down Expand Up @@ -131,13 +131,15 @@ export class PlaywrightCheck extends RuntimeCheck {
key: codeBundlePath,
browsers,
cacheHash,
playwrightVersion,
} = await PlaywrightCheck.bundleProject(this.playwrightConfigPath, this.include ?? [])

return new PlaywrightCheckBundle(this, {
groupId,
codeBundlePath,
browsers,
cacheHash,
playwrightVersion,
})
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"dependencies": {
"@playwright/test": "1.1.1",
}
}
35 changes: 32 additions & 3 deletions packages/cli/src/services/__tests__/util.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import path from 'node:path'
import { describe, it, expect, vi, beforeEach, afterAll } from 'vitest'
import fs from 'node:fs/promises'
import fsSync from 'node:fs'

import { describe, it, expect } from 'vitest'

import { pathToPosix, isFileSync } from '../util'
import { pathToPosix, isFileSync, getPlaywrightVersion } from '../util'

describe('util', () => {
describe('pathToPosix()', () => {
Expand All @@ -24,4 +25,32 @@ describe('util', () => {
expect(isFileSync('some random string')).toBeFalsy()
})
})

describe('getPlaywrightVersion()', () => {
const fixturesDir = path.join(__dirname, '..', '__tests__', 'fixtures', 'playwright-json');
const emptyDir = path.join(__dirname, 'fixtures', 'empty');

// Create empty directory for testing the "not found" case
beforeEach(async () => {
if (!fsSync.existsSync(emptyDir)) {
await fs.mkdir(emptyDir, { recursive: true });
}
});

afterAll(async () => {
if (fsSync.existsSync(emptyDir)) {
await fs.rm(emptyDir, { recursive: true, force: true });
}
})

it('should find version using node_modules path', async () => {
const version = await getPlaywrightVersion(fixturesDir);
expect(version).toBe('1.1.1');
});

it('should return undefined if playwright is not found', async () => {
const version = await getPlaywrightVersion(emptyDir);
expect(version).toBeUndefined();
});
})
})
45 changes: 37 additions & 8 deletions packages/cli/src/services/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as fs from 'fs/promises'
import * as fsSync from 'fs'
import gitRepoInfo from 'git-repo-info'
import { parse } from 'dotenv'

// @ts-ignore
import { getProxyForUrl } from 'proxy-from-env'
import { httpOverHttp, httpsOverHttp, httpOverHttps, httpsOverHttps } from 'tunnel'
Expand All @@ -18,6 +19,7 @@ import { PlaywrightConfig } from './playwright-config'
import { access , readFile} from 'fs/promises'
import { createHash } from 'crypto';
import { Session } from '../constructs'
import semver from 'semver'

export interface GitInformation {
commitId: string
Expand Down Expand Up @@ -173,8 +175,15 @@ export function assignProxy (baseURL: string, axiosConfig: CreateAxiosDefaults)
return axiosConfig
}

export function normalizeVersion(v?: string | undefined): string | undefined {
const cleaned =
semver.valid(semver.clean(v ?? '') || '') ??
semver.coerce(v ?? '')?.version;
return cleaned && semver.valid(cleaned) ? cleaned : undefined;
}

export async function bundlePlayWrightProject (playwrightConfig: string, include: string[]):
Promise<{outputFile: string, browsers: string[], relativePlaywrightConfigPath: string, cacheHash: string}> {
Promise<{outputFile: string, browsers: string[], relativePlaywrightConfigPath: string, cacheHash: string, playwrightVersion: string | undefined}> {
const dir = path.resolve(path.dirname(playwrightConfig))
const filePath = path.resolve(dir, playwrightConfig)
const pwtConfig = await Session.loadFile(filePath)
Expand All @@ -191,9 +200,14 @@ Promise<{outputFile: string, browsers: string[], relativePlaywrightConfigPath: s
archive.pipe(output)

const pwConfigParsed = new PlaywrightConfig(filePath, pwtConfig)
const lockFile = await findLockFile(dir)
if (!lockFile) {
throw new Error('No lock file found')
}

const [cacheHash] = await Promise.all([
getCacheHash(dir),
const [cacheHash, playwrightVersion] = await Promise.all([
getCacheHash(lockFile),
getPlaywrightVersion(dir),
loadPlaywrightProjectFiles(dir, pwConfigParsed, include, archive)
])

Expand All @@ -203,6 +217,7 @@ Promise<{outputFile: string, browsers: string[], relativePlaywrightConfigPath: s
return resolve({
outputFile,
browsers: pwConfigParsed.getBrowsers(),
playwrightVersion,
relativePlaywrightConfigPath: path.relative(dir, filePath),
cacheHash
})
Expand All @@ -214,16 +229,30 @@ Promise<{outputFile: string, browsers: string[], relativePlaywrightConfigPath: s
})
}

export async function getCacheHash (dir: string): Promise<string> {
const lockFile = await findLockFile(dir)
if (!lockFile) {
throw new Error('No lock file found')
}
export async function getCacheHash (lockFile: string): Promise<string> {
const fileBuffer = await readFile(lockFile);
const hash = createHash('sha256');
hash.update(fileBuffer);
return hash.digest('hex');
}

export async function getPlaywrightVersion(projectDir: string): Promise<string | undefined> {
try {
const modulePath = path.join(projectDir, 'node_modules', '@playwright', 'test', 'package.json');
const packageJson = JSON.parse(await readFile(modulePath, 'utf-8'));
return normalizeVersion(packageJson.version);
} catch {
// If node_modules not found, fall back to checking the project's package.json
const packageJsonPath = path.join(projectDir, 'package.json');
try {
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
const version = packageJson.dependencies?.['@playwright/test'] ||
packageJson.devDependencies?.['@playwright/test'];
return normalizeVersion(version);
} catch {
return;
}
}
}

async function findLockFile(dir: string): Promise<string | null> {
Expand Down
Loading