-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add ability to copy playwright config into checkly config (#919)
* feat: add ability to copy playwright config when creating the CLI Once creating the CLI it will check if there is a playwright.config file on the directory, then ask the user if he wants to copy it to the checkly config file * feat: add ability to sync playwright config with 'sync-playwright' command New feature that allows the user to sync (update or create) their playwright config with the checkly config * fix: update package-lock.json file * fix: do not fail if file does not exist * refactor: use JSON5 instead of handlebars * test: add test for sync-playwright feature * fix: prompts and logs for better experience
- Loading branch information
1 parent
6bd7405
commit fdc09c7
Showing
21 changed files
with
880 additions
and
52 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
21 changes: 21 additions & 0 deletions
21
packages/cli/e2e/__tests__/fixtures/test-playwright-project/checkly.config.original.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { defineConfig } from 'checkly' | ||
|
||
const config = defineConfig({ | ||
projectName: 'Test Playwright Project', | ||
logicalId: 'test-playwright-project', | ||
repoUrl: 'https://github.com/checkly/checkly-cli', | ||
checks: { | ||
locations: ['us-east-1', 'eu-west-1'], | ||
tags: ['mac'], | ||
runtimeId: '2022.10', | ||
checkMatch: '**/*.check.ts', | ||
browserChecks: { | ||
testMatch: '**/__checks__/*.test.ts', | ||
}, | ||
}, | ||
cli: { | ||
runLocation: 'us-east-1', | ||
}, | ||
}) | ||
|
||
export default config |
21 changes: 21 additions & 0 deletions
21
packages/cli/e2e/__tests__/fixtures/test-playwright-project/checkly.config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { defineConfig } from 'checkly' | ||
|
||
const config = defineConfig({ | ||
projectName: 'Test Playwright Project', | ||
logicalId: 'test-playwright-project', | ||
repoUrl: 'https://github.com/checkly/checkly-cli', | ||
checks: { | ||
locations: ['us-east-1', 'eu-west-1'], | ||
tags: ['mac'], | ||
runtimeId: '2022.10', | ||
checkMatch: '**/*.check.ts', | ||
browserChecks: { | ||
testMatch: '**/__checks__/*.test.ts', | ||
}, | ||
}, | ||
cli: { | ||
runLocation: 'us-east-1', | ||
}, | ||
}) | ||
|
||
export default config |
23 changes: 23 additions & 0 deletions
23
packages/cli/e2e/__tests__/fixtures/test-playwright-project/playwright.config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { defineConfig, devices } from '@playwright/test' | ||
|
||
export default defineConfig({ | ||
testDir: 'tests', | ||
timeout: 1234, | ||
use: { | ||
baseURL: 'http://127.0.0.1:3000', | ||
extraHTTPHeaders: { | ||
foo: 'bar', | ||
}, | ||
}, | ||
expect: { | ||
toMatchSnapshot: { | ||
maxDiffPixelRatio: 1, | ||
}, | ||
}, | ||
projects: [ | ||
{ | ||
name: 'chromium', | ||
use: { ...devices['Desktop Chrome'] }, | ||
}, | ||
], | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { runChecklyCli } from '../run-checkly' | ||
import * as path from 'path' | ||
import { loadChecklyConfig } from '../../src/services/checkly-config-loader' | ||
import * as fs from 'fs' | ||
|
||
describe('sync-playwright', () => { | ||
// Since we are modifying the file let's keep it clean after each test | ||
afterEach(() => { | ||
const configPath = path.join(__dirname, 'fixtures', 'test-playwright-project') | ||
fs.copyFileSync(path.join(configPath, 'checkly.config.original.ts'), path.join(configPath, 'checkly.config.ts')) | ||
}) | ||
|
||
it('should copy playwright config into checkly config', async () => { | ||
const { status, stdout } = await runChecklyCli({ | ||
args: ['sync-playwright'], | ||
directory: path.join(__dirname, 'fixtures', 'test-playwright-project'), | ||
}) | ||
expect(status).toBe(0) | ||
expect(stdout).toContain('Successfully updated Checkly config file') | ||
const checklyConfig = await loadChecklyConfig(path.join(__dirname, 'fixtures', 'test-playwright-project')) | ||
expect(checklyConfig.config?.checks?.browserChecks?.playwrightConfig).toBeDefined() | ||
expect(checklyConfig.config?.checks?.browserChecks?.playwrightConfig?.timeout).toEqual(1234) | ||
expect(checklyConfig.config?.checks?.browserChecks?.playwrightConfig?.use).toBeDefined() | ||
expect(checklyConfig.config?.checks?.browserChecks?.playwrightConfig?.use?.baseURL).toEqual('http://127.0.0.1:3000') | ||
expect(checklyConfig.config?.checks?.browserChecks?.playwrightConfig?.expect).toBeDefined() | ||
}) | ||
|
||
it('should fail if no playwright config file exists', async () => { | ||
const { status, stdout } = await runChecklyCli({ | ||
args: ['sync-playwright'], | ||
directory: path.join(__dirname, 'fixtures', 'test-project'), | ||
}) | ||
expect(status).toBe(1) | ||
expect(stdout).toContain('Could not find any playwright.config file.') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { BaseCommand } from './baseCommand' | ||
import * as recast from 'recast' | ||
import { getChecklyConfigFile } from '../services/checkly-config-loader' | ||
import { loadPlaywrightConfig } from '../playwright/playwright-config-loader' | ||
import fs from 'fs' | ||
import path from 'path' | ||
import { ux } from '@oclif/core' | ||
import PlaywrightConfigTemplate from '../playwright/playwright-config-template' | ||
|
||
export default class SyncPlaywright extends BaseCommand { | ||
static hidden = true | ||
static description = 'Copy Playwright config into the Checkly config file' | ||
|
||
async run (): Promise<void> { | ||
ux.action.start('Syncing Playwright config to the Checkly config file', undefined, { stdout: true }) | ||
|
||
const config = await loadPlaywrightConfig() | ||
if (!config) { | ||
return this.handleError('Could not find any playwright.config file.') | ||
} | ||
|
||
const configFile = getChecklyConfigFile() | ||
if (!configFile) { | ||
return this.handleError('Could not find a checkly config file') | ||
} | ||
const checklyAst = recast.parse(configFile.checklyConfig) | ||
|
||
const checksAst = this.findPropertyByName(checklyAst, 'checks') | ||
if (!checksAst) { | ||
return this.handleError('Unable to automatically sync your config file. This can happen if your Checkly config is ' + | ||
'built using helper functions or other JS/TS features. You can still manually set Playwright config values in ' + | ||
'your Checkly config: https://www.checklyhq.com/docs/cli/constructs-reference/#project') | ||
} | ||
|
||
const browserCheckAst = this.findPropertyByName(checksAst.value, 'browserChecks') | ||
if (!browserCheckAst) { | ||
return this.handleError('Unable to automatically sync your config file. This can happen if your Checkly config is ' + | ||
'built using helper functions or other JS/TS features. You can still manually set Playwright config values in ' + | ||
'your Checkly config: https://www.checklyhq.com/docs/cli/constructs-reference/#project') | ||
} | ||
|
||
const pwtConfig = new PlaywrightConfigTemplate(config).getConfigTemplate() | ||
const pwtConfigAst = this.findPropertyByName(recast.parse(pwtConfig), 'playwrightConfig') | ||
this.addOrReplacePlaywrightConfig(browserCheckAst.value, pwtConfigAst) | ||
|
||
const checklyConfigData = recast.print(checklyAst, { tabWidth: 2 }).code | ||
const dir = path.resolve(path.dirname(configFile.fileName)) | ||
this.reWriteChecklyConfigFile(checklyConfigData, configFile.fileName, dir) | ||
|
||
ux.action.stop('✅ ') | ||
this.log('Successfully updated Checkly config file') | ||
this.exit(0) | ||
} | ||
|
||
private handleError (message: string) { | ||
ux.action.stop('❌') | ||
this.log(message) | ||
this.exit(1) | ||
} | ||
|
||
private findPropertyByName (ast: any, name: string): recast.types.namedTypes.Property | undefined { | ||
let node | ||
recast.visit(ast, { | ||
visitProperty (path: any) { | ||
if (path.node.key.name === name) { | ||
node = path.node | ||
} | ||
return false | ||
}, | ||
}) | ||
return node | ||
} | ||
|
||
private addOrReplacePlaywrightConfig (ast: any, node: any) { | ||
const playWrightConfig = this.findPropertyByName(ast, 'playwrightConfig') | ||
if (playWrightConfig) { | ||
playWrightConfig.value = node.value | ||
} else { | ||
ast.properties.push(node) | ||
} | ||
} | ||
|
||
private reWriteChecklyConfigFile (data: string, fileName: string, dir: string) { | ||
fs.writeFileSync(path.join(dir, fileName), data) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import path from 'path' | ||
import { loadFile } from '../services/checkly-config-loader' | ||
import fs from 'fs' | ||
|
||
export async function loadPlaywrightConfig () { | ||
let config | ||
const filenames = ['playwright.config.ts', 'playwright.config.js'] | ||
for (const configFile of filenames) { | ||
if (!fs.existsSync(path.resolve(path.dirname(configFile)))) { | ||
continue | ||
} | ||
const dir = path.resolve(path.dirname(configFile)) | ||
config = await loadFile(path.join(dir, configFile)) | ||
if (config) { | ||
break | ||
} | ||
} | ||
return config | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { PlaywrightConfig, Use, Expect } from '../constructs/browser-defaults' | ||
import * as JSON5 from 'json5' | ||
|
||
export default class PlaywrightConfigTemplate { | ||
playwrightConfig: PlaywrightConfig | ||
|
||
constructor ({ use, expect, timeout }: any) { | ||
this.playwrightConfig = {} | ||
if (use) { | ||
this.playwrightConfig.use = this.getUseParams(use) | ||
} | ||
if (expect) { | ||
this.playwrightConfig.expect = this.getExpectParams(expect) | ||
} | ||
this.playwrightConfig.timeout = timeout | ||
} | ||
|
||
private getUseParams (use: any): Use { | ||
return { | ||
baseURL: use.baseURL, | ||
colorScheme: use.colorScheme, | ||
geolocation: use.geolocation, | ||
locale: use.locale, | ||
permissions: use.permissions, | ||
timezoneId: use.timezoneId, | ||
viewport: use.viewport, | ||
deviceScaleFactor: use.deviceScaleFactor, | ||
hasTouch: use.hasTouch, | ||
isMobile: use.isMobile, | ||
javaScriptEnabled: use.javaScriptEnabled, | ||
acceptDownloads: use.acceptDownloads, | ||
extraHTTPHeaders: use.extraHTTPHeaders, | ||
httpCredentials: use.httpCredentials, | ||
ignoreHTTPSErrors: use.ignoreHTTPSErrors, | ||
offline: use.offline, | ||
actionTimeout: use.actionTimeout, | ||
navigationTimeout: use.navigationTimeout, | ||
testIdAttribute: use.testIdAttribute, | ||
launchOptions: use.launchOptions, | ||
contextOptions: use.contextOptions, | ||
bypassCSP: use.bypassCSP, | ||
} | ||
} | ||
|
||
private getExpectParams (expect: any): Expect { | ||
return { | ||
timeout: expect.timeout, | ||
toHaveScreenshot: expect.toHaveScreenshot, | ||
toMatchSnapshot: expect.toMatchSnapshot, | ||
} | ||
} | ||
|
||
getConfigTemplate () { | ||
return `const playwrightConfig = ${JSON5.stringify(this, { space: 2 })}` | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.