playwright-bdd
Version:
BDD Testing with Playwright runner
86 lines (73 loc) • 3.14 kB
text/typescript
import path from 'node:path';
import { Command } from 'commander';
import Table from 'cli-table3';
import { ConfigOption } from '../options';
import { loadConfig as loadPlaywrightConfig } from '../../playwright/loadConfig';
import { Logger } from '../../utils/logger';
import { getEnvConfigs } from '../../config/env';
import { assertConfigsCount } from './test';
import { TestFilesGenerator } from '../../generate';
import { relativeToCwd } from '../../utils/paths';
import { BDDConfig } from '../../config/types';
import { StepDefinition } from '../../steps/stepDefinition';
const logger = new Logger({ verbose: true });
type ExportCommandOptions = ConfigOption & {
unusedSteps?: boolean;
};
export const exportCommand = new Command('export')
.description('Prints step definitions')
.configureHelp({ showGlobalOptions: true })
.option('--unused-steps', 'Output only unused steps')
.action(async () => {
const opts = exportCommand.optsWithGlobals<ExportCommandOptions>();
const { resolvedConfigFile } = await loadPlaywrightConfig(opts.config);
logger.log(`Using config: ${path.relative(process.cwd(), resolvedConfigFile)}`);
const configs = Object.values(getEnvConfigs());
assertConfigsCount(configs);
if (opts.unusedSteps) {
await showUnusedStepsForConfigs(configs);
} else {
await showStepsForConfigs(configs);
}
});
async function showStepsForConfigs(configs: BDDConfig[]) {
// here we don't need workers (as in test command) because if some step files
// are already in node cache, we collected them.
const steps = new Set<string>();
const tasks = configs.map(async (config) => {
const stepDefinitions = await new TestFilesGenerator(config).extractSteps();
stepDefinitions.forEach((s) => steps.add(`* ${formatStepText(s)}`));
});
await Promise.all(tasks);
logger.log(`List of all steps (${steps.size}):`);
steps.forEach((stepText) => logger.log(stepText));
}
async function showUnusedStepsForConfigs(configs: BDDConfig[]) {
const steps = new Set<StepDefinition>();
const tasks = configs.map(async (config) => {
const stepDefinitions = await new TestFilesGenerator(config).extractUnusedSteps();
stepDefinitions.forEach((step) => steps.add(step));
});
await Promise.all(tasks);
logger.log(`Unused steps (${steps.size}):`);
logger.log(formatUnusedStepsTable(steps));
}
function formatUnusedStepsTable(steps: Set<StepDefinition>) {
const table = new Table({
head: ['Pattern / Text', /*'Duration', */ 'Location'],
style: { border: [], head: [] }, // disable colors
});
steps.forEach((step) => {
table.push([formatStepText(step), formatStepLocation(step)]);
});
return table.toString();
}
function formatStepText({ pattern, keyword }: StepDefinition) {
// for Unknown return When as it looks the most suitable
const keywordText = keyword === 'Unknown' ? 'When' : keyword;
const patternText = typeof pattern === 'string' ? pattern : pattern.source;
return `${keywordText} ${patternText}`;
}
function formatStepLocation(step: StepDefinition) {
return `${relativeToCwd(step.uri)}:${step.line}`;
}