diff --git a/lib/runner.js b/lib/runner.js index f65452d..bf84cc1 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -12,6 +12,7 @@ const Mocha = require('mocha'); const glob = require('glob'); const mkdirp = require('mkdirp'); const tmp = require('tmp'); +const _ = require('lodash'); const fs = require('fs'); const path = require('path'); @@ -40,6 +41,39 @@ function formatJson(val) { return JSON.stringify(val, null, 2); } +function expandError(err) { + try { + if (!(err instanceof Error)) { + return; + } + const detail = {}; + // particle-api-js stores the original HTTP client error in a `error` property + if (err.error instanceof Error) { + detail['cause'] = err.error.toString(); + } + // The parsed body of a 3xx or 4xx response goes to `body` (but only if it's a valid JSON, + // otherwise the info is not available) + if (err.body !== undefined && !(err.body instanceof Error)) { + detail['body'] = err.body; + } + const lines = []; + for (let [name, val] of Object.entries(detail)) { // eslint-disable-line prefer-const + if (!_.isString(val)) { + val = JSON.stringify(val); + } + lines.push(name + ': ' + val); + } + if (lines.length) { + if (err.message) { + lines.unshift(err.message); + } + err.message = lines.join('\n\t'); + } + } catch (err) { + // Ignore + } +} + class Runner { constructor({ log }) { this._log = log; // Logger instance @@ -387,18 +421,23 @@ class Runner { test.title = s; } }; + const testFail = (test, err) => { + expandError(err); + }; const runEnd = () => { runner.off(MochaRunner.constants.EVENT_SUITE_BEGIN, suiteBegin); runner.off(MochaRunner.constants.EVENT_SUITE_END, suiteEnd); runner.off(MochaRunner.constants.EVENT_TEST_BEGIN, testBegin); runner.off(MochaRunner.constants.EVENT_TEST_END, testEnd); runner.off(MochaRunner.constants.EVENT_TEST_PASS, testPass); + runner.off(MochaRunner.constants.EVENT_TEST_FAIL, testPass); }; runner.on(MochaRunner.constants.EVENT_SUITE_BEGIN, suiteBegin); runner.on(MochaRunner.constants.EVENT_SUITE_END, suiteEnd); runner.on(MochaRunner.constants.EVENT_TEST_BEGIN, testBegin); runner.on(MochaRunner.constants.EVENT_TEST_END, testEnd); runner.prependListener(MochaRunner.constants.EVENT_TEST_PASS, testPass); + runner.prependListener(MochaRunner.constants.EVENT_TEST_FAIL, testFail); runner.once(MochaRunner.constants.EVENT_RUN_END, runEnd); }