Skip to content
Open
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
11 changes: 10 additions & 1 deletion packages/cli/src/commands/pw-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import { createReporters, ReporterType } from '../reporters/reporter'
import TestRunner from '../services/test-runner'
import {
DEFAULT_CHECK_RUN_TIMEOUT_SECONDS,

Check warning on line 21 in packages/cli/src/commands/pw-test.ts

View workflow job for this annotation

GitHub Actions / lint

'DEFAULT_CHECK_RUN_TIMEOUT_SECONDS' is defined but never used
DEFAULT_PLAYWRIGHT_CHECK_RUN_TIMEOUT_SECONDS,
Events,
SequenceId,
Expand Down Expand Up @@ -94,6 +94,12 @@
default: true,
allowNo: true,
}),
'include': Flags.string({
char: 'i',
description: 'File patterns to include when bundling the test project (e.g., "utils/**/*").',
multiple: true,
default: [],
}),
}

async run (): Promise<void> {
Expand All @@ -115,6 +121,7 @@
'test-session-name': testSessionName,
'create-check': createCheck,
'stream-logs': streamLogs,
'include': includeFlag,
} = flags
const { configDirectory, configFilenames } = splitConfigFilePath(configFilename)
const pwPathFlag = this.getConfigPath(playwrightFlags)
Expand Down Expand Up @@ -173,8 +180,10 @@
verifyRuntimeDependencies: false,
checklyConfigConstructs,
playwrightConfigPath,
include: checklyConfig.checks?.include,
include: includeFlag.length ? includeFlag : checklyConfig.checks?.include,
includeFlagProvided: includeFlag.length > 0,
playwrightChecks: [playwrightCheck],
currentCommand: 'pw-test',
checkFilter: check => {
// Skip non Playwright checks
if (!(check instanceof PlaywrightCheck)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "playwright-check-webserver-fixture",
"devDependencies": {
"@playwright/test": "^1.55.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from '@playwright/test'

export default defineConfig({
testDir: './tests',
webServer: {
command: 'npm run start',
url: 'http://localhost:3000',
},
})
74 changes: 74 additions & 0 deletions packages/cli/src/constructs/__tests__/playwright-check.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ describe('PlaywrightCheck', () => {
headers: new AxiosHeaders(),
},
})
Session.currentCommand = undefined
Session.includeFlagProvided = undefined
})

it('should synthesize groupName', async () => {
Expand Down Expand Up @@ -271,6 +273,78 @@ describe('PlaywrightCheck', () => {
}),
]))
})

it('should warn if webServer is configured in playwright config when running pw-test', async () => {
Session.basePath = path.resolve(__dirname, './fixtures/playwright-check-webserver')
Session.project = new Project('project-id', {
name: 'Test Project',
repoUrl: 'https://github.com/checkly/checkly-cli',
})
Session.currentCommand = 'pw-test'

const check = new PlaywrightCheck('foo', {
name: 'Test Check',
playwrightConfigPath: path.resolve(__dirname, './fixtures/playwright-check-webserver/playwright.config.ts'),
})

const diags = new Diagnostics()
await check.validate(diags)

expect(diags.isFatal()).toEqual(false)
expect(diags.observations).toEqual(expect.arrayContaining([
expect.objectContaining({
title: expect.stringContaining('webServer configuration detected'),
message: expect.stringContaining('webServer configuration requires additional files'),
}),
]))
})

it('should not warn about webServer when not running pw-test command', async () => {
Session.basePath = path.resolve(__dirname, './fixtures/playwright-check-webserver')
Session.project = new Project('project-id', {
name: 'Test Project',
repoUrl: 'https://github.com/checkly/checkly-cli',
})
Session.currentCommand = 'test'

const check = new PlaywrightCheck('foo', {
name: 'Test Check',
playwrightConfigPath: path.resolve(__dirname, './fixtures/playwright-check-webserver/playwright.config.ts'),
})

const diags = new Diagnostics()
await check.validate(diags)

expect(diags.observations).not.toEqual(expect.arrayContaining([
expect.objectContaining({
title: expect.stringContaining('webServer configuration detected'),
}),
]))
})

it('should not warn about webServer when --include flag is provided', async () => {
Session.basePath = path.resolve(__dirname, './fixtures/playwright-check-webserver')
Session.project = new Project('project-id', {
name: 'Test Project',
repoUrl: 'https://github.com/checkly/checkly-cli',
})
Session.currentCommand = 'pw-test'
Session.includeFlagProvided = true

const check = new PlaywrightCheck('foo', {
name: 'Test Check',
playwrightConfigPath: path.resolve(__dirname, './fixtures/playwright-check-webserver/playwright.config.ts'),
})

const diags = new Diagnostics()
await check.validate(diags)

expect(diags.observations).not.toEqual(expect.arrayContaining([
expect.objectContaining({
title: expect.stringContaining('webServer configuration detected'),
}),
]))
})
})

describe('defaults', () => {
Expand Down
28 changes: 28 additions & 0 deletions packages/cli/src/constructs/playwright-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
InvalidPropertyValueDiagnostic,
UnsupportedPropertyDiagnostic,
} from './construct-diagnostics'
import { WarningDiagnostic } from './diagnostics'
import { Diagnostics } from './diagnostics'
import { PlaywrightCheckBundle } from './playwright-check-bundle'
import { Session } from './project'
Expand Down Expand Up @@ -237,12 +238,39 @@ export class PlaywrightCheck extends RuntimeCheck {
}
}

protected async validateWebServerConfig (diagnostics: Diagnostics): Promise<void> {
// Only show webServer warning for pw-test command when --include is not provided
if (Session.currentCommand !== 'pw-test' || Session.includeFlagProvided) {
return
}

try {
const playwrightConfig = await Session.loadFile(this.playwrightConfigPath)

if (playwrightConfig && typeof playwrightConfig === 'object' && 'webServer' in playwrightConfig) {
diagnostics.add(new WarningDiagnostic({
title: 'webServer configuration detected',
message:
`webServer configuration requires additional files. `
+ `Include all files needed to start the server (e.g., server scripts, config files) `
+ `by passing them via the --include flag.`,
}))
}
} catch (err: any) {
diagnostics.add(new InvalidPropertyValueDiagnostic(
'playwrightConfigPath',
new Error(`Unable to parse Playwright config "${this.playwrightConfigPath}": ${err.message}`, { cause: err }),
))
}
}

async validate (diagnostics: Diagnostics): Promise<void> {
await super.validate(diagnostics)
await this.validateRetryStrategy(diagnostics)

try {
await fs.access(this.playwrightConfigPath, fs.constants.R_OK)
await this.validateWebServerConfig(diagnostics)
} catch (err: any) {
diagnostics.add(new InvalidPropertyValueDiagnostic(
'playwrightConfigPath',
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/src/constructs/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ export class Session {
static parsers = new Map<string, Parser>()
static constructExports: ConstructExport[] = []
static ignoreDirectoriesMatch: string[] = []
static currentCommand?: 'pw-test' | 'test' | 'deploy'
static includeFlagProvided?: boolean

static async loadFile<T = unknown> (filePath: string): Promise<T> {
const loader = this.loader
Expand Down
6 changes: 6 additions & 0 deletions packages/cli/src/services/project-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ type ProjectParseOpts = {
checklyConfigConstructs?: Construct[]
playwrightConfigPath?: string
include?: string | string[]
includeFlagProvided?: boolean
playwrightChecks?: PlaywrightSlimmedProp[]
currentCommand?: 'pw-test' | 'test' | 'deploy'
}

const BASE_CHECK_DEFAULTS = {
Expand All @@ -59,7 +61,9 @@ export async function parseProject (opts: ProjectParseOpts): Promise<Project> {
checklyConfigConstructs,
playwrightConfigPath,
include,
includeFlagProvided,
playwrightChecks,
currentCommand,
} = opts
const project = new Project(projectLogicalId, {
name: projectName,
Expand All @@ -82,6 +86,8 @@ export async function parseProject (opts: ProjectParseOpts): Promise<Project> {
Session.defaultRuntimeId = defaultRuntimeId
Session.verifyRuntimeDependencies = verifyRuntimeDependencies ?? true
Session.ignoreDirectoriesMatch = ignoreDirectoriesMatch
Session.currentCommand = currentCommand
Session.includeFlagProvided = includeFlagProvided

// TODO: Do we really need all of the ** globs, or could we just put node_modules?
const ignoreDirectories = ['**/node_modules/**', '**/.git/**', ...ignoreDirectoriesMatch]
Expand Down