From 334cfe472a2c6bc1a13f4971303fd7a89ec3ed5d Mon Sep 17 00:00:00 2001 From: Paul Slaughter Date: Fri, 10 May 2019 07:17:50 -0500 Subject: [PATCH] Update FE test script - Don't fail when no tests match - Print the cmd prefix for each line in it's data - Update exit code handling - Add colors to summary message --- scripts/frontend/test.js | 81 +++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 22 deletions(-) mode change 100644 => 100755 scripts/frontend/test.js diff --git a/scripts/frontend/test.js b/scripts/frontend/test.js old mode 100644 new mode 100755 index 3dff781844e..dab7176f8c1 --- a/scripts/frontend/test.js +++ b/scripts/frontend/test.js @@ -1,11 +1,16 @@ #!/usr/bin/env node -const program = require('commander'); const { spawn } = require('child_process'); +const { EOL } = require('os'); +const program = require('commander'); +const chalk = require('chalk'); const JEST_ROUTE = 'spec/frontend'; const KARMA_ROUTE = 'spec/javascripts'; const COMMON_ARGS = ['--colors']; +const JEST_ARGS = ['--passWithNoTests']; +const KARMA_ARGS = ['--no-fail-on-empty-test-suite']; +const SUCCESS_CODE = 0; program .version('0.1.0') @@ -13,18 +18,40 @@ program .option('-p, --parallel', 'Run tests suites in parallel') .parse(process.argv); +const isSuccess = code => code === SUCCESS_CODE; + +const combineExitCodes = codes => { + const firstFail = codes.find(x => !isSuccess(x)); + + return firstFail === undefined ? SUCCESS_CODE : firstFail; +}; + +const skipIfFail = fn => code => (isSuccess(code) ? fn() : code); + +const endWithEOL = str => (str[str.length - 1] === '\n' ? str : `${str}${EOL}`); + const runTests = paths => { if (program.parallel) { - return Promise.all([runJest(paths), runKarma(paths)]); + return Promise.all([runJest(paths), runKarma(paths)]).then(combineExitCodes); } else { - return runJest(paths).then(() => runKarma(paths)); + return runJest(paths).then(skipIfFail(() => runKarma(paths))); } }; -const spawnPromise = (cmd, args) => { +const spawnYarnScript = (cmd, args) => { return new Promise((resolve, reject) => { const proc = spawn('yarn', ['run', cmd, ...args]); - const output = data => `${cmd}: ${data}`; + const output = data => { + const text = data + .toString() + .split(/\r?\n/g) + .map((line, idx, { length }) => + idx === length - 1 && !line ? line : `${chalk.gray(cmd)}: ${line}`, + ) + .join(EOL); + + return endWithEOL(text); + }; proc.stdout.on('data', data => { process.stdout.write(output(data)); @@ -35,22 +62,22 @@ const spawnPromise = (cmd, args) => { }); proc.on('close', code => { - process.stdout.write(`${cmd} exited with code ${code}`); - if (code === 0) { - resolve(); - } else { - reject(); - } + process.stdout.write(output(`exited with code ${code}`)); + + // We resolve even on a failure code because a `reject` would cause + // Promise.all to reject immediately (without waiting for other promises) + // to finish. + resolve(code); }); }); }; const runJest = args => { - return spawnPromise('jest', [...COMMON_ARGS, ...toJestArgs(args)]); + return spawnYarnScript('jest', [...JEST_ARGS, ...COMMON_ARGS, ...toJestArgs(args)]); }; const runKarma = args => { - return spawnPromise('karma', [...COMMON_ARGS, ...toKarmaArgs(args)]); + return spawnYarnScript('karma', [...KARMA_ARGS, ...COMMON_ARGS, ...toKarmaArgs(args)]); }; const replacePath = to => path => @@ -59,19 +86,29 @@ const replacePath = to => path => .replace(KARMA_ROUTE, to) .replace('app/assets/javascripts', to); -const toJestArgs = paths => paths.map(replacePath(JEST_ROUTE)); +const replacePathForJest = replacePath(JEST_ROUTE); + +const replacePathForKarma = replacePath(KARMA_ROUTE); + +const toJestArgs = paths => paths.map(replacePathForJest); const toKarmaArgs = paths => - paths.map(replacePath(KARMA_ROUTE)).reduce((acc, current) => acc.concat('-f', current), []); + paths.reduce((acc, path) => acc.concat('-f', replacePathForKarma(path)), []); const main = paths => { - runTests(paths) - .then(() => { - console.log('All tests passed!'); - }) - .catch(() => { - console.log('Some tests failed...'); - }); + runTests(paths).then(code => { + console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); + if (isSuccess(code)) { + console.log(chalk.bgGreen(chalk.black('All tests passed :)'))); + } else { + console.log(chalk.bgRed(chalk.white(`Some tests failed :(`))); + } + console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); + + if (!isSuccess(code)) { + process.exit(code); + } + }); }; main(program.args);