storybook/scripts/test.js
Gaëtan Maisse 3d7a024b3c
test: execute CLI tests like all other Jest tests
As CLI tests based on fixtures have been deleted, and the remaining tests are now using Jest we can run them as part of the classic `yarn test --core` command.

I also removed the dedicated GitHub Actions.
2020-12-08 19:26:02 +01:00

191 lines
5.3 KiB
JavaScript

#!/usr/bin/env node
const prompts = require('prompts');
const program = require('commander');
const childProcess = require('child_process');
const chalk = require('chalk');
const log = require('npmlog');
const path = require('path');
log.heading = 'storybook';
const prefix = 'test';
log.addLevel('aborted', 3001, { fg: 'red', bold: true });
const spawn = (command) => {
const out = childProcess.spawnSync(`${command}`, {
shell: true,
stdio: 'inherit',
});
if (out.status !== 0) {
process.exit(out.status);
}
return out;
};
const main = program.version('3.0.0').option('--all', `Test everything ${chalk.gray('(all)')}`);
const createProject = ({ defaultValue, option, name, projectLocation, isJest, script }) => ({
value: false,
defaultValue: defaultValue || false,
option: option || undefined,
name: name || 'unnamed task',
script,
projectLocation,
isJest,
});
const createOption = ({ defaultValue, option, name, extraParam }) => ({
value: false,
defaultValue: defaultValue || false,
option: option || undefined,
name: name || 'unnamed task',
extraParam,
});
const tasks = {
core: createProject({
name: `Core & Examples 🎨 ${chalk.gray('(core)')}`,
defaultValue: true,
option: '--core',
projectLocation: '<all>',
isJest: true,
}),
puppeteer: createProject({
name: `Puppeteer and A11y tests for Official storybook ${chalk.gray('(puppeteer)')}`,
defaultValue: false,
option: '--puppeteer',
projectLocation: path.join(__dirname, '..', 'examples/official-storybook/storyshots-puppeteer'),
isJest: true,
}),
watchmode: createOption({
name: `Run in watch-mode ${chalk.gray('(watchmode)')}`,
defaultValue: false,
option: '--watch',
extraParam: '--watch',
}),
coverage: createOption({
name: `Output coverage reports ${chalk.gray('(coverage)')}`,
defaultValue: false,
option: '--coverage',
extraParam: '--coverage',
}),
runInBand: createOption({
name: `Run all tests serially in the current process ${chalk.gray('(runInBand)')}`,
defaultValue: false,
option: '--runInBand',
extraParam: '--runInBand',
}),
w2: createOption({
name: `Run all tests in max 2 processes process ${chalk.gray('(w2)')}`,
defaultValue: false,
option: '--w2',
extraParam: '-w 2',
}),
reportLeaks: createOption({
name: `report memory leaks ${chalk.gray('(reportLeaks)')}`,
defaultValue: false,
option: '--reportLeaks',
extraParam: '--detectLeaks',
}),
update: createOption({
name: `Update all snapshots ${chalk.gray('(update)')}`,
defaultValue: false,
option: '--update',
extraParam: '-u --updateSnapshot',
}),
};
const getProjects = (list) => list.filter((key) => key.projectLocation);
const getScripts = (list) => list.filter((key) => key.script);
const getExtraParams = (list) => list.filter((key) => key.extraParam).map((key) => key.extraParam);
Object.keys(tasks)
.reduce((acc, key) => acc.option(tasks[key].option, tasks[key].name), main)
.parse(process.argv);
Object.keys(tasks).forEach((key) => {
tasks[key].value =
program[tasks[key].option.replace('--', '')] || (program.all && tasks[key].projectLocation);
});
let selection;
if (
!Object.keys(tasks)
.map((key) => tasks[key].value)
.filter(Boolean).length
) {
selection = prompts([
{
type: 'multiselect',
message: 'Select which tests to run',
name: 'todo',
optionsPerPage: 18,
choices: Object.values(tasks)
.filter((key) => !key.extraParam)
.map((key) => ({
value: key,
title: key.name,
selected: key.defaultValue,
})),
},
{
type: 'multiselect',
message: 'Select extra parameters to add',
name: 'params',
optionsPerPage: 18,
choices: Object.values(tasks)
.filter((key) => key.extraParam)
.map((key) => ({
value: key,
title: key.name,
selected: key.defaultValue,
})),
},
]).then(({ todo, params }) => todo.concat(params));
} else {
selection = Promise.resolve(
Object.keys(tasks)
.map((key) => tasks[key])
.filter((item) => item.value === true)
);
}
selection
.then((list) => {
if (list.length === 0) {
log.warn(prefix, 'Nothing to test');
} else {
const projects = getProjects(list);
const jestProjects = projects.filter((key) => key.isJest).map((key) => key.projectLocation);
const nonJestProjects = projects.filter((key) => !key.isJest);
const extraParams = getExtraParams(list).join(' ');
const jest = path.join(__dirname, '..', 'node_modules', '.bin', 'jest');
if (jestProjects.length > 0) {
const projectsParam = jestProjects.some((project) => project === '<all>')
? ''
: `--projects ${jestProjects.join(' ')}`;
const cmd = `cross-env NODE_OPTIONS=--max_old_space_size=4096 ${jest} ${projectsParam} ${extraParams}`;
spawn(cmd);
}
nonJestProjects.forEach((key) =>
spawn(`npm --prefix ${key.projectLocation} test -- ${extraParams}`)
);
const scripts = getScripts(list);
scripts.forEach((key) => spawn(`${key.script} -- ${extraParams}`));
process.stdout.write('\x07');
}
})
.catch((e) => {
log.aborted(prefix, chalk.red(e.message));
log.silly(prefix, e);
process.exit(1);
});