144 lines
3.3 KiB
TypeScript
144 lines
3.3 KiB
TypeScript
import { execSync, fork } from 'child_process';
|
|
import {
|
|
ExecutorContext,
|
|
getPackageManagerCommand,
|
|
names,
|
|
output,
|
|
workspaceRoot,
|
|
} from '@nx/devkit';
|
|
|
|
export interface PlaywrightExecutorSchema {
|
|
/*
|
|
* if 'projects' is configured then that name needs to be provided instead of
|
|
* all, chromium, firefox, webkit
|
|
**/
|
|
browser?: 'all' | 'chromium' | 'firefox' | 'webkit' | string;
|
|
config?: string;
|
|
debug?: boolean;
|
|
forbidOnly?: boolean;
|
|
fullyParallel?: boolean;
|
|
grep?: string;
|
|
globalTimeout?: number;
|
|
grepInvert?: string;
|
|
headed?: boolean;
|
|
ignoreSnapshots?: boolean;
|
|
workers?: string;
|
|
list?: boolean;
|
|
maxFailures?: number | boolean;
|
|
noDeps?: boolean;
|
|
output?: string;
|
|
passWithNoTests?: boolean;
|
|
project?: string[];
|
|
quiet?: boolean;
|
|
repeatEach?: number;
|
|
reporter?:
|
|
| 'list'
|
|
| 'line'
|
|
| 'dot'
|
|
| 'json'
|
|
| 'junit'
|
|
| 'null'
|
|
| 'github'
|
|
| 'html'
|
|
| 'blob';
|
|
retries?: number;
|
|
shard?: string;
|
|
timeout?: number;
|
|
trace?:
|
|
| 'on'
|
|
| 'off'
|
|
| 'on-first-retry'
|
|
| 'on-all-retries'
|
|
| 'retain-on-failure';
|
|
updateSnapshots?: boolean;
|
|
ui?: boolean;
|
|
uiHost?: string;
|
|
uiPort?: string;
|
|
skipInstall?: boolean;
|
|
}
|
|
|
|
export async function playwrightExecutor(
|
|
options: PlaywrightExecutorSchema,
|
|
context: ExecutorContext
|
|
) {
|
|
const projectRoot =
|
|
context.projectGraph?.nodes?.[context?.projectName]?.data?.root;
|
|
|
|
if (!projectRoot) {
|
|
throw new Error(
|
|
`Unable to find the Project Root for ${context.projectName}. Is it set in the project.json?`
|
|
);
|
|
}
|
|
|
|
if (!options.skipInstall) {
|
|
output.log({
|
|
title: 'Ensuring Playwright is installed.',
|
|
bodyLines: ['use --skipInstall to skip installation.'],
|
|
});
|
|
const pmc = getPackageManagerCommand();
|
|
execSync(`${pmc.exec} playwright install`, {
|
|
cwd: workspaceRoot,
|
|
stdio: 'inherit',
|
|
});
|
|
}
|
|
|
|
const args = createArgs(options);
|
|
const p = runPlaywright(args, context.root);
|
|
p.stdout.on('data', (message) => {
|
|
process.stdout.write(message);
|
|
});
|
|
p.stderr.on('data', (message) => {
|
|
process.stderr.write(message);
|
|
});
|
|
|
|
return new Promise<{ success: boolean }>((resolve) => {
|
|
p.on('close', (code) => {
|
|
resolve({ success: code === 0 });
|
|
});
|
|
});
|
|
}
|
|
|
|
function createArgs(
|
|
opts: PlaywrightExecutorSchema,
|
|
exclude: string[] = ['skipInstall']
|
|
): string[] {
|
|
const args: string[] = [];
|
|
|
|
for (const key in opts) {
|
|
if (exclude.includes(key)) continue;
|
|
|
|
const value = opts[key];
|
|
// NOTE: playwright doesn't accept pascalCase args, only kebab-case
|
|
const arg = names(key).fileName;
|
|
|
|
if (Array.isArray(value)) {
|
|
args.push(...value.map((v) => `--${arg}=${v.trim()}`));
|
|
} else if (typeof value === 'boolean') {
|
|
// NOTE: playwright don't accept --arg=false, instead just don't pass the arg.
|
|
if (value) {
|
|
args.push(`--${arg}`);
|
|
}
|
|
} else {
|
|
args.push(`--${arg}=${value}`);
|
|
}
|
|
}
|
|
|
|
return args;
|
|
}
|
|
|
|
function runPlaywright(args: string[], cwd: string) {
|
|
try {
|
|
const cli = require.resolve('@playwright/test/cli');
|
|
|
|
return fork(cli, ['test', ...args], {
|
|
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
|
|
cwd,
|
|
});
|
|
} catch (e) {
|
|
console.error(e);
|
|
throw new Error('Unable to run playwright. Is @playwright/test installed?');
|
|
}
|
|
}
|
|
|
|
export default playwrightExecutor;
|