From 88b02af305a1d279827235e13f8c58940eca9fb5 Mon Sep 17 00:00:00 2001 From: Paul Gascou-Vaillancourt Date: Wed, 10 Apr 2019 15:55:11 -0400 Subject: Create a unified script to run Jest & Karma tests - Created scripts/frontend/test.js - Updated test task to call Node script --- scripts/frontend/test.js | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 scripts/frontend/test.js (limited to 'scripts') diff --git a/scripts/frontend/test.js b/scripts/frontend/test.js new file mode 100644 index 00000000000..3dff781844e --- /dev/null +++ b/scripts/frontend/test.js @@ -0,0 +1,77 @@ +#!/usr/bin/env node + +const program = require('commander'); +const { spawn } = require('child_process'); + +const JEST_ROUTE = 'spec/frontend'; +const KARMA_ROUTE = 'spec/javascripts'; +const COMMON_ARGS = ['--colors']; + +program + .version('0.1.0') + .usage('[options] ') + .option('-p, --parallel', 'Run tests suites in parallel') + .parse(process.argv); + +const runTests = paths => { + if (program.parallel) { + return Promise.all([runJest(paths), runKarma(paths)]); + } else { + return runJest(paths).then(() => runKarma(paths)); + } +}; + +const spawnPromise = (cmd, args) => { + return new Promise((resolve, reject) => { + const proc = spawn('yarn', ['run', cmd, ...args]); + const output = data => `${cmd}: ${data}`; + + proc.stdout.on('data', data => { + process.stdout.write(output(data)); + }); + + proc.stderr.on('data', data => { + process.stderr.write(output(data)); + }); + + proc.on('close', code => { + process.stdout.write(`${cmd} exited with code ${code}`); + if (code === 0) { + resolve(); + } else { + reject(); + } + }); + }); +}; + +const runJest = args => { + return spawnPromise('jest', [...COMMON_ARGS, ...toJestArgs(args)]); +}; + +const runKarma = args => { + return spawnPromise('karma', [...COMMON_ARGS, ...toKarmaArgs(args)]); +}; + +const replacePath = to => path => + path + .replace(JEST_ROUTE, to) + .replace(KARMA_ROUTE, to) + .replace('app/assets/javascripts', to); + +const toJestArgs = paths => paths.map(replacePath(JEST_ROUTE)); + +const toKarmaArgs = paths => + paths.map(replacePath(KARMA_ROUTE)).reduce((acc, current) => acc.concat('-f', current), []); + +const main = paths => { + runTests(paths) + .then(() => { + console.log('All tests passed!'); + }) + .catch(() => { + console.log('Some tests failed...'); + }); +}; + +main(program.args); -- cgit v1.2.1 From 334cfe472a2c6bc1a13f4971303fd7a89ec3ed5d Mon Sep 17 00:00:00 2001 From: Paul Slaughter Date: Fri, 10 May 2019 07:17:50 -0500 Subject: 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 (limited to 'scripts') 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); -- cgit v1.2.1