diff --git a/.npmignore b/.npmignore index dd826f83..8d1d57a1 100755 --- a/.npmignore +++ b/.npmignore @@ -10,15 +10,14 @@ *.DS_Store ### folders -.idea -node_modules +.idea/ +node_modules/ coverage/ -.nyc_output -yarn.lock +.nyc_output/ test/ dist/ -.github -.tscmultiwatch +.github/ +.tscmultiwatch/ ### files exp.js @@ -30,6 +29,8 @@ suman.conf.js .editorconfig .babelrc .dockerignore +package-lock.json +yarn.lock ### negation !lib/**/*.sh diff --git a/cli.js b/cli.js index 2362c6ab..605237e8 100755 --- a/cli.js +++ b/cli.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -"use strict"; +'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); debugger; var process = require('suman-browser-polyfills/modules/process'); @@ -53,6 +53,7 @@ process.on('uncaughtException', function (err) { }, 500); }); process.on('unhandledRejection', function (err, p) { + debugger; if (typeof err !== 'object') { console.error(new Error("err passed to unhandledRejection was not an object => '" + err + "'").stack); err = new Error(typeof err === 'string' ? err : util.inspect(err)); @@ -180,6 +181,7 @@ var tscMultiWatch = sumanOpts.tsc_multi_watch; var sumanD = sumanOpts.suman_d; var watchPer = sumanOpts.watch_per; var singleProcess = sumanOpts.single_process; +var script = sumanOpts.script; if (singleProcess) { process.env.SUMAN_SINGLE_PROCESS = 'yes'; } @@ -304,7 +306,7 @@ var preOptCheck = { convert: convert, groups: groups, s: s, tailTest: tailTest, tailRunner: tailRunner, interactive: interactive, uninstallBabel: uninstallBabel, diagnostics: diagnostics, installGlobals: installGlobals, postinstall: postinstall, - repair: repair, sumanD: sumanD + repair: repair, sumanD: sumanD, script: script }; var optCheck = Object.keys(preOptCheck).filter(function (key, index) { return preOptCheck[key]; @@ -358,6 +360,9 @@ if (!process.stdout.isTTY && !useTAPOutput) { if (diagnostics) { require('./lib/cli-commands/run-diagnostics').run(sumanOpts); } +else if (script) { + require('./lib/cli-commands/run-scripts').run(sumanConfig, sumanOpts); +} else if (tscMultiWatch) { require('./lib/cli-commands/run-tscmultiwatch').run(sumanOpts); } @@ -411,7 +416,7 @@ else if (s) { require('./lib/cli-commands/start-suman-server')(sumanServerInstalled, sumanConfig, serverName); } else if (watch || watchPer) { - require('./lib/cli-commands/watching').run(paths, sumanOpts, sumanConfig); + require('./lib/cli-commands/watching').run(projectRoot, paths, sumanOpts, sumanConfig); } else if (groups) { require('./lib/cli-commands/groups').run(paths); diff --git a/cli.ts b/cli.ts index db30657e..98ce1b70 100755 --- a/cli.ts +++ b/cli.ts @@ -1,19 +1,11 @@ #!/usr/bin/env node +'use strict'; -/////////////////////////////////////////////////////////////////// - -import {IGlobalSumanObj} from "./dts/global"; +//dts +import {IGlobalSumanObj} from "suman-types/dts/global"; debugger; //leave here forever so users can easily debug with "node --inspect" or "node debug" -/////////////////////////////////////////////////////////////////// - -/* - Note for the reader: Suman uses dashdash to parse command line arguments - We found dashdash to be a better alternative to other option parsers - => https://github.com/trentm/node-dashdash - */ - //polyfills const process = require('suman-browser-polyfills/modules/process'); const global = require('suman-browser-polyfills/modules/global'); @@ -61,7 +53,7 @@ function handleExceptionsAndRejections() { process.on('uncaughtException', function (err: Error) { - debugger; + debugger; // leave it here :) if (typeof err !== 'object') { console.error(new Error(`err passed to uncaughtException was not an object => ${err}`).stack); @@ -85,6 +77,8 @@ process.on('uncaughtException', function (err: Error) { process.on('unhandledRejection', function (err: Error, p: Promise) { + debugger; // leave it here :) + if (typeof err !== 'object') { console.error(new Error(`err passed to unhandledRejection was not an object => '${err}'`).stack); err = new Error(typeof err === 'string' ? err : util.inspect(err)) @@ -114,19 +108,17 @@ import tty = require('tty'); //npm import semver = require('semver'); - const dashdash = require('dashdash'); import * as chalk from 'chalk'; import async = require('async'); import su = require('suman-utils'); import _ = require('lodash'); - const uniqBy = require('lodash.uniqby'); const {events} = require('suman-events'); const debug = require('suman-debug')('s:cli'); //project -const _suman : IGlobalSumanObj = global.__suman = (global.__suman || {}); +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); require('./lib/helpers/add-suman-global-properties'); require('./lib/patches/all'); import {loadReporters} from './lib/helpers/load-reporters'; @@ -260,8 +252,9 @@ const tscMultiWatch = sumanOpts.tsc_multi_watch; const sumanD = sumanOpts.suman_d; const watchPer = sumanOpts.watch_per; const singleProcess = sumanOpts.single_process; +const script = sumanOpts.script; -if(singleProcess){ +if (singleProcess) { process.env.SUMAN_SINGLE_PROCESS = 'yes'; } @@ -444,7 +437,7 @@ const preOptCheck = { convert, groups, s, tailTest, tailRunner, interactive, uninstallBabel, diagnostics, installGlobals, postinstall, - repair, sumanD + repair, sumanD, script }; const optCheck = Object.keys(preOptCheck).filter(function (key, index) { @@ -524,6 +517,9 @@ if (!process.stdout.isTTY && !useTAPOutput) { if (diagnostics) { require('./lib/cli-commands/run-diagnostics').run(sumanOpts); } +else if (script) { + require('./lib/cli-commands/run-scripts').run(sumanConfig, sumanOpts); +} else if (tscMultiWatch) { require('./lib/cli-commands/run-tscmultiwatch').run(sumanOpts); } @@ -570,7 +566,6 @@ else if (uninstall) { removeBabel: removeBabel, }); } - else if (convert) { require('./lib/cli-commands/convert-mocha').run(projectRoot, src, dest, force); } @@ -578,7 +573,7 @@ else if (s) { require('./lib/cli-commands/start-suman-server')(sumanServerInstalled, sumanConfig, serverName); } else if (watch || watchPer) { - require('./lib/cli-commands/watching').run(paths, sumanOpts, sumanConfig); + require('./lib/cli-commands/watching').run(projectRoot, paths, sumanOpts, sumanConfig); } else if (groups) { require('./lib/cli-commands/groups').run(paths); diff --git a/config/suman-constants.d.ts b/config/suman-constants.d.ts index 303d3f86..9f40749f 100755 --- a/config/suman-constants.d.ts +++ b/config/suman-constants.d.ts @@ -5,6 +5,7 @@ export declare const constants: Readonly<{ DEFAULT_PARALLEL_TOTAL_LIMIT: number; DEFAULT_PARALLEL_TEST_LIMIT: number; DEFAULT_PARALLEL_BLOCK_LIMIT: number; + DEFAULT_CHILD_PROCESS_TIMEOUT: number; OLDEST_SUPPORTED_NODE_VERSION: string; DEBUGGING_ENV: { name: string; @@ -12,6 +13,8 @@ export declare const constants: Readonly<{ }; SUMAN_SERVER_MESSAGE: string; GIT_IGNORE: string[]; + SUMAN_HOOK_FATAL_WARNING_MESSAGE: string; + SUMAN_HOOK_FATAL_MESSAGE: string; SUMAN_HARD_LIST: string[]; CORE_MODULE_LIST: any; CLI_EXIT_CODES: { diff --git a/config/suman-constants.js b/config/suman-constants.js index 6a0c5351..996c1318 100755 --- a/config/suman-constants.js +++ b/config/suman-constants.js @@ -8,6 +8,7 @@ exports.constants = Object.freeze({ DEFAULT_PARALLEL_TOTAL_LIMIT: 30, DEFAULT_PARALLEL_TEST_LIMIT: 10, DEFAULT_PARALLEL_BLOCK_LIMIT: 10, + DEFAULT_CHILD_PROCESS_TIMEOUT: 6000000, OLDEST_SUPPORTED_NODE_VERSION: 'v4.0.0', DEBUGGING_ENV: { name: 'SUMAN_DEBUG', @@ -17,6 +18,8 @@ exports.constants = Object.freeze({ GIT_IGNORE: [ '**suman/logs/**' ], + SUMAN_HOOK_FATAL_WARNING_MESSAGE: 'Suman non-fatal error => Error in hook and "fatal" option for the hook is set to false =>\n', + SUMAN_HOOK_FATAL_MESSAGE: ' => fatal error in hook => (to continue even in the event of an error in a hook, use option {fatal:false}) =>\n', SUMAN_HARD_LIST: Object.keys({ describe: true, before: true, diff --git a/config/suman-constants.ts b/config/suman-constants.ts index df65a70a..524c30b1 100755 --- a/config/suman-constants.ts +++ b/config/suman-constants.ts @@ -12,6 +12,8 @@ export const constants = Object.freeze({ DEFAULT_PARALLEL_TEST_LIMIT: 10, DEFAULT_PARALLEL_BLOCK_LIMIT: 10, + DEFAULT_CHILD_PROCESS_TIMEOUT: 6000000, + OLDEST_SUPPORTED_NODE_VERSION: 'v4.0.0', DEBUGGING_ENV: { @@ -25,6 +27,12 @@ export const constants = Object.freeze({ '**suman/logs/**' ], + SUMAN_HOOK_FATAL_WARNING_MESSAGE: + 'Suman non-fatal error => Error in hook and "fatal" option for the hook is set to false =>\n', + + SUMAN_HOOK_FATAL_MESSAGE: + ' => fatal error in hook => (to continue even in the event of an error in a hook, use option {fatal:false}) =>\n', + SUMAN_HARD_LIST: Object.keys({ //bdd diff --git a/exp.js b/exp.js index 719ab1da..3388b668 100644 --- a/exp.js +++ b/exp.js @@ -11,6 +11,18 @@ // hi +////// + +console.log('this is the beginning.'); const path = require('path'); console.error(`${path.basename(__dirname)} reporter may be unable to properly indent output.`); + + +var player = require('play-sound')(opts = {}); + +const failTrombonePath = path.resolve(process.env.HOME + '/fail-trombone-02.mp3'); + +player.play(failTrombonePath, { timeout: 6000 }, function(err){ + if (err) throw err +}); diff --git a/lib/cli-commands/run-scripts/index.d.ts b/lib/cli-commands/run-scripts/index.d.ts new file mode 100644 index 00000000..39b8122d --- /dev/null +++ b/lib/cli-commands/run-scripts/index.d.ts @@ -0,0 +1,2 @@ +import { ISumanConfig, ISumanOpts } from "suman-types/dts/global"; +export declare const run: (sumanConfig: ISumanConfig, opts: ISumanOpts) => void; diff --git a/lib/cli-commands/run-scripts/index.js b/lib/cli-commands/run-scripts/index.js new file mode 100644 index 00000000..aea00d1f --- /dev/null +++ b/lib/cli-commands/run-scripts/index.js @@ -0,0 +1,49 @@ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +var process = require('suman-browser-polyfills/modules/process'); +var global = require('suman-browser-polyfills/modules/global'); +var assert = require("assert"); +var cp = require("child_process"); +var util = require("util"); +var su = require("suman-utils"); +var chalk = require("chalk"); +var prepend_transform_1 = require("prepend-transform"); +var _suman = global.__suman = (global.__suman || {}); +exports.run = function (sumanConfig, opts) { + var k = cp.spawn('bash'); + var scriptKey = opts.script; + assert(su.isStringWithPositiveLn(scriptKey), 'script key must be a string.'); + var scriptValue; + try { + scriptValue = sumanConfig['scripts'][scriptKey]; + assert(su.isStringWithPositiveLn(scriptValue), "script value must be a string with positive length, instead we got <" + util.inspect(scriptValue) + ">."); + } + catch (err) { + if (sumanConfig['scripts']) { + _suman.log('Here are the available scripts in your suman.conf.js file:'); + _suman.log(util.inspect(sumanConfig['scripts'])); + } + throw err; + } + k.stdin.setDefaultEncoding('utf8'); + k.stdout.setEncoding('utf8'); + k.stderr.setEncoding('utf8'); + console.log('\n'); + _suman.log("Your script with key '" + scriptKey + "' is now running, and its output follows:\n"); + k.stdout.pipe(prepend_transform_1.pt(chalk.blue(' stdout: '))).pipe(process.stdout); + k.stderr.pipe(prepend_transform_1.pt(chalk.red(' stderr: '))).pipe(process.stderr); + k.stdin.write('\n'); + k.stdin.write(scriptValue); + k.stdin.end('\n'); + k.once('exit', function (code) { + console.log('\n'); + console.error('\n'); + if (code > 0) { + _suman.logError("script with key '" + scriptKey + "' exited with code " + code); + } + else { + _suman.log("script with key '" + scriptKey + "' exited with code " + code); + } + process.exit(code); + }); +}; diff --git a/lib/cli-commands/run-scripts/index.ts b/lib/cli-commands/run-scripts/index.ts new file mode 100644 index 00000000..8739153e --- /dev/null +++ b/lib/cli-commands/run-scripts/index.ts @@ -0,0 +1,79 @@ +'use strict'; + +//dts +import {ISumanConfig, ISumanOpts, IGlobalSumanObj} from "suman-types/dts/global"; + +//polyfills +const process = require('suman-browser-polyfills/modules/process'); +const global = require('suman-browser-polyfills/modules/global'); + +//core +import assert = require('assert'); +import * as cp from 'child_process'; +import util = require('util'); + + +//npm +import su = require('suman-utils'); +import chalk = require('chalk'); +import {pt} from 'prepend-transform'; + +//project +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); + +//////////////////////////////////////////////////////////////////////////////// + +export const run = function (sumanConfig: ISumanConfig, opts: ISumanOpts) { + + const k = cp.spawn('bash'); + + const scriptKey = opts.script; + + assert(su.isStringWithPositiveLn(scriptKey), 'script key must be a string.'); + + let scriptValue; + + try { + scriptValue = sumanConfig['scripts'][scriptKey]; + assert(su.isStringWithPositiveLn(scriptValue), + `script value must be a string with positive length, instead we got <${util.inspect(scriptValue)}>.`); + } + catch (err) { + if(sumanConfig['scripts']){ + _suman.log('Here are the available scripts in your suman.conf.js file:'); + _suman.log(util.inspect(sumanConfig['scripts'])); + } + throw err; + } + + k.stdin.setDefaultEncoding('utf8'); + k.stdout.setEncoding('utf8'); + k.stderr.setEncoding('utf8'); + + console.log('\n'); + _suman.log(`Your script with key '${scriptKey}' is now running, and its output follows:\n`); + + k.stdout.pipe(pt(chalk.blue(' stdout: '))).pipe(process.stdout); + k.stderr.pipe(pt(chalk.red(' stderr: '))).pipe(process.stderr); + + k.stdin.write('\n'); + k.stdin.write(scriptValue); + k.stdin.end('\n'); + + k.once('exit', function (code) { + + console.log('\n'); + console.error('\n'); + + if (code > 0) { + _suman.logError(`script with key '${scriptKey}' exited with code ${code}`); + } + else { + _suman.log(`script with key '${scriptKey}' exited with code ${code}`); + } + + process.exit(code); + + }); + +}; diff --git a/lib/cli-commands/watching/index.d.ts b/lib/cli-commands/watching/index.d.ts index c0e5c7ff..ea174f8e 100755 --- a/lib/cli-commands/watching/index.d.ts +++ b/lib/cli-commands/watching/index.d.ts @@ -1,2 +1,2 @@ import { ISumanConfig, ISumanOpts } from "suman-types/dts/global"; -export declare const run: (paths: string[], sumanOpts: ISumanOpts, sumanConfig: ISumanConfig) => void; +export declare const run: (projectRoot: string, paths: string[], sumanOpts: ISumanOpts, sumanConfig: ISumanConfig) => void; diff --git a/lib/cli-commands/watching/index.js b/lib/cli-commands/watching/index.js index 453d1c6e..d6af6aa6 100755 --- a/lib/cli-commands/watching/index.js +++ b/lib/cli-commands/watching/index.js @@ -2,33 +2,20 @@ Object.defineProperty(exports, "__esModule", { value: true }); var process = require('suman-browser-polyfills/modules/process'); var global = require('suman-browser-polyfills/modules/global'); -var assert = require("assert"); -var suman_utils_1 = require("suman-utils"); var chalk = require("chalk"); var suman_watch_1 = require("suman-watch"); var _suman = global.__suman = (global.__suman || {}); -exports.run = function (paths, sumanOpts, sumanConfig) { - console.log(' => Suman message => --watch option selected => Suman will watch files in your project, and run your tests on changes.'); - if (_suman.sumanOpts.verbosity > 2) { - console.log(' => Suman message => --watch option selected => Using the "watch" property object in your suman.conf.js file,' + +exports.run = function (projectRoot, paths, sumanOpts, sumanConfig) { + _suman.log('"--watch" option selected => Suman will watch files in your project, and run your tests on changes.'); + if (sumanOpts.verbosity > 2) { + _suman.log('"--watch" option selected => Using the "watch" property object in your suman.conf.js file,' + 'you can also configure Suman to do whatever you want based off a file change.'); } - var watchPer = null; - if (sumanOpts.watch_per) { - assert(suman_utils_1.default.isObject(sumanConfig.watch), chalk.red(' => Suman usage error => suman.conf.js needs a "watch" property that is an object.')); - assert(suman_utils_1.default.isObject(sumanConfig.watch.per), chalk.red(' => Suman usage error => suman.conf.js "watch" object, needs property called "per" that is an object.')); - watchPer = sumanConfig.watch.per[sumanOpts.watch_per]; - assert(suman_utils_1.default.isObject(watchPer), chalk.red(" => Suman usage error => key \"" + sumanOpts.watch_per + "\", \n does not exist on the {suman.conf.js}.watch.per object.")); - } - suman_watch_1.run(Object.freeze({ - paths: paths, - watchPer: watchPer, - noTranspile: sumanOpts.no_transpile, - noRun: sumanOpts.no_run - }), function (err) { + suman_watch_1.runWatch(projectRoot, paths, sumanConfig, sumanOpts, function (err) { if (err) { console.log('\n'); console.error(err.stack || err); + console.log('\n'); process.exit(1); } else { diff --git a/lib/cli-commands/watching/index.ts b/lib/cli-commands/watching/index.ts index 7df9b697..57dac62c 100755 --- a/lib/cli-commands/watching/index.ts +++ b/lib/cli-commands/watching/index.ts @@ -1,5 +1,8 @@ 'use strict'; +//dts +import {IGlobalSumanObj, ISumanConfig, ISumanOpts} from "suman-types/dts/global"; + //polyfills const process = require('suman-browser-polyfills/modules/process'); const global = require('suman-browser-polyfills/modules/global'); @@ -12,60 +15,52 @@ import EE = require('events'); import fs = require('fs'); import * as stream from 'stream'; - //npm import su from 'suman-utils'; import * as chalk from 'chalk'; -import {run as runWatch} from 'suman-watch'; -import {IGlobalSumanObj, ISumanConfig, ISumanOpts} from "suman-types/dts/global"; +import {runWatch} from 'suman-watch'; //project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); ///////////////////////////////////////////////////////////////////////// -export const run = function (paths: Array, sumanOpts: ISumanOpts, sumanConfig: ISumanConfig) { +export const run = function (projectRoot: string, paths: Array, sumanOpts: ISumanOpts, sumanConfig: ISumanConfig) { - console.log(' => Suman message => --watch option selected => Suman will watch files in your project, and run your tests on changes.'); - if (_suman.sumanOpts.verbosity > 2) { - console.log(' => Suman message => --watch option selected => Using the "watch" property object in your suman.conf.js file,' + + _suman.log('"--watch" option selected => Suman will watch files in your project, and run your tests on changes.'); + if (sumanOpts.verbosity > 2) { + _suman.log('"--watch" option selected => Using the "watch" property object in your suman.conf.js file,' + 'you can also configure Suman to do whatever you want based off a file change.'); } - let watchPer = null; - - if (sumanOpts.watch_per) { - assert(su.isObject(sumanConfig.watch), - chalk.red(' => Suman usage error => suman.conf.js needs a "watch" property that is an object.')); - - assert(su.isObject(sumanConfig.watch.per), - chalk.red(' => Suman usage error => suman.conf.js "watch" object, needs property called "per" that is an object.')); - - watchPer = sumanConfig.watch.per[sumanOpts.watch_per]; - - assert(su.isObject(watchPer), - chalk.red(` => Suman usage error => key "${sumanOpts.watch_per}", - does not exist on the {suman.conf.js}.watch.per object.`)); - } - - runWatch(Object.freeze({ - paths, - watchPer, - noTranspile: sumanOpts.no_transpile, - noRun: sumanOpts.no_run - }), - function (err: Error) { - if (err) { - console.log('\n'); - console.error(err.stack || err); - process.exit(1); - } - else { - console.log('\n'); - _suman.logInfo(chalk.underline('Suman watch successfully initialized.')); - } - }) + // const watchOpts = Object.freeze({ + // paths, + // watchPer, + // noTranspile: sumanOpts.no_transpile, + // noRun: sumanOpts.no_run + // }); + + + // const watchOpts = { + // paths, + // watchPer: sumanOpts.watch_per, + // noRun: sumanOpts.no_run, + // noTranspile: sumanOpts.no_transpile + // }; + + runWatch(projectRoot, paths, sumanConfig, sumanOpts, function (err: Error) { + if (err) { + console.log('\n'); + console.error(err.stack || err); + console.log('\n'); + process.exit(1); + } + else { + console.log('\n'); + _suman.logInfo(chalk.underline('Suman watch successfully initialized.')); + } + }) }; diff --git a/lib/default-conf-files/suman.default.conf.js b/lib/default-conf-files/suman.default.conf.js index 9660bad7..ac5343a4 100755 --- a/lib/default-conf-files/suman.default.conf.js +++ b/lib/default-conf-files/suman.default.conf.js @@ -7,13 +7,14 @@ const numOfCPUs = os.cpus().length || 1; module.exports = { - // Array + // Array matchAny: [], //recommended regex for 'matchAny' => [/\.test\.js$/], matchNone: [/fixture/, /.*target/], //recommended regex for 'matchNone' => [/fixture/], matchAll: [/\.test\.js$/], //recommended regex for 'matchAll' => [], //string testDir: 'test', + testSrcDir: 'test', sumanHelpersDir: 'suman', uniqueAppName: '', browser: 'Firefox', // browser to open test results with @@ -87,9 +88,14 @@ module.exports = { }, watch: { + options:{ + // incomplete + }, per: { 'zoom': { exec: 'suman test', + include: [], + exclude: [], includes: [__dirname], excludes: ['/test/', '/node_modules/', '/.git/'], confOverride: {} @@ -104,7 +110,7 @@ module.exports = { reporters: { // usage: $ suman --reporters tap - 'tap': 'suman-reporters/modules/tap' + 'tap': 'suman-reporters/modules/tap-reporter' // the value is simply passed to require() }, servers: { // list of servers to output test result data to, with the os.hostname() as the key diff --git a/lib/default-conf-files/suman.default.conf.x.d.ts b/lib/default-conf-files/suman.default.conf.x.d.ts index d23f640e..68085c81 100755 --- a/lib/default-conf-files/suman.default.conf.x.d.ts +++ b/lib/default-conf-files/suman.default.conf.x.d.ts @@ -1,103 +1,3 @@ -export interface ISumanConf { - matchAny: any[]; - matchNone: RegExp[]; - matchAll: RegExp[]; - testDir: string; - testSrcDir: string; - testTargetDir: string; - sumanHelpersDir: string; - uniqueAppName: string; - browser: string; - autoLoggingPre: boolean; - autoLoggingPost: boolean; - autoLoggingIoc: boolean; - autoLoggingHooks: boolean; - installSumanExtraDeps: boolean; - autoLoggingTestCases: boolean; - isLogChildStdout: boolean; - isLogChildStderr: boolean; - includeSumanGlobalsInPath: boolean; - useSumanUtilityPatches: boolean; - useTAPOutput: boolean; - errorsOnly: boolean; - replayErrorsAtRunnerEnd: boolean; - logStdoutToTestLogs: boolean; - allowArrowFunctionsForTestBlocks: boolean; - alwaysUseRunner: boolean; - enforceGlobalInstallationOnly: boolean; - enforceLocalInstallationOnly: boolean; - sourceTopLevelDepsInPackageDotJSON: boolean; - enforceTestCaseNames: boolean; - enforceBlockNames: boolean; - enforceHookNames: boolean; - bail: boolean; - bailRunner: boolean; - useBabelRegister: boolean; - transpile: boolean; - executeRunnerCWDAtTestFile: boolean; - sendStderrToSumanErrLogOnly: boolean; - useSuiteNameInTestCaseOutput: boolean; - ultraSafe: boolean; - verbose: boolean; - checkMemoryUsage: boolean; - fullStackTraces: boolean; - disableAutoOpen: boolean; - suppressRunnerOutput: boolean; - allowCollectUsageStats: boolean; - highestPerformance: boolean; - saveLogsForThisManyPastRuns: number; - verbosity: number; - maxParallelProcesses: number; - resultsCapCount: number; - resultsCapSize: number; - defaultHookTimeout: number; - defaultTestCaseTimeout: number; - timeoutToSearchForAvailServer: number; - defaultDelayFunctionTimeout: number; - defaultChildProcessTimeout: number; - defaultTestSuiteTimeout: number; - expireResultsAfter: number; - coverage: { - coverageDir: string; - nyc: { - use: boolean; - }; - istanbul: {}; - }; - watch: { - '//tests': { - 'default': { - script: (p: any) => string; - include: any[]; - exclude: string[]; - }; - }; - '//project': { - 'default': { - script: string; - include: any[]; - exclude: string[]; - }; - }; - }; - reporters: { - 'tap': string; - }; - servers: { - '*default': { - host: string; - port: number; - }; - '###': { - host: string; - port: number; - }; - }; - babelRegisterOpts: { - ignore: RegExp; - extensions: string[]; - }; -} declare const _default: { matchAny: any[]; matchNone: RegExp[]; diff --git a/lib/default-conf-files/suman.default.conf.x.ts b/lib/default-conf-files/suman.default.conf.x.ts index 58677c54..128ada69 100755 --- a/lib/default-conf-files/suman.default.conf.x.ts +++ b/lib/default-conf-files/suman.default.conf.x.ts @@ -8,106 +8,7 @@ const numOfCPUs = os.cpus().length || 1; //////////////////////////////////////////////// -export interface ISumanConf { - matchAny: any[]; - matchNone: RegExp[]; - matchAll: RegExp[]; - testDir: string; - testSrcDir: string; - testTargetDir: string; - sumanHelpersDir: string; - uniqueAppName: string; - browser: string; - autoLoggingPre: boolean; - autoLoggingPost: boolean; - autoLoggingIoc: boolean; - autoLoggingHooks: boolean; - installSumanExtraDeps: boolean; - autoLoggingTestCases: boolean; - isLogChildStdout: boolean; - isLogChildStderr: boolean; - includeSumanGlobalsInPath: boolean; - useSumanUtilityPatches: boolean; - useTAPOutput: boolean; - errorsOnly: boolean; - replayErrorsAtRunnerEnd: boolean; - logStdoutToTestLogs: boolean; - allowArrowFunctionsForTestBlocks: boolean; - alwaysUseRunner: boolean; - enforceGlobalInstallationOnly: boolean; - enforceLocalInstallationOnly: boolean; - sourceTopLevelDepsInPackageDotJSON: boolean; - enforceTestCaseNames: boolean; - enforceBlockNames: boolean; - enforceHookNames: boolean; - bail: boolean; - bailRunner: boolean; - useBabelRegister: boolean; - transpile: boolean; - executeRunnerCWDAtTestFile: boolean; - sendStderrToSumanErrLogOnly: boolean; - useSuiteNameInTestCaseOutput: boolean; - ultraSafe: boolean; - verbose: boolean; - checkMemoryUsage: boolean; - fullStackTraces: boolean; - disableAutoOpen: boolean; - suppressRunnerOutput: boolean; - allowCollectUsageStats: boolean; - highestPerformance: boolean; - saveLogsForThisManyPastRuns: number; - verbosity: number; - maxParallelProcesses: number; - resultsCapCount: number; - resultsCapSize: number; - defaultHookTimeout: number; - defaultTestCaseTimeout: number; - timeoutToSearchForAvailServer: number; - defaultDelayFunctionTimeout: number; - defaultChildProcessTimeout: number; - defaultTestSuiteTimeout: number; - expireResultsAfter: number; - coverage: { - coverageDir: string; - nyc: { - use: boolean; - }; - istanbul: {}; - }; - watch: { - '//tests': { - 'default': { - script: (p: any) => string; - include: any[]; - exclude: string[]; - }; - }; - '//project': { - 'default': { - script: string; - include: any[]; - exclude: string[]; - }; - }; - }; - reporters: { - 'tap': string; - }; - servers: { - '*default': { - host: string; - port: number; - }; - '###': { - host: string; - port: number; - }; - }; - babelRegisterOpts: { - ignore: RegExp; - extensions: string[]; - }; -} + export default { diff --git a/lib/exec-suite.js b/lib/exec-suite.js index 1e7eee64..5e23178a 100755 --- a/lib/exec-suite.js +++ b/lib/exec-suite.js @@ -58,8 +58,10 @@ exports.execSuite = function (suman) { msg: msg_1 } }, function () { - console.log(msg_1 + '\n\n'); - console.error(new Error(' => Suman usage error => invalid arrow/generator function usage.').stack); + console.error(msg_1 + '\n\n'); + var err = new Error('Suman usage error => invalid arrow/generator function usage.').stack; + _suman.logError(err); + _suman.writeTestError(err); process.exit(suman_constants_1.constants.EXIT_CODES.INVALID_ARROW_FUNCTION_USAGE); }); } @@ -202,8 +204,9 @@ exports.execSuite = function (suman) { var start = function () { _suman.suiteResultEmitter.emit('suman-test-registered', function () { var sumanOpts = _suman.sumanOpts; - _suman.currentPaddingCount = _suman.currentPaddingCount || {}; - _suman.currentPaddingCount.val = 1; + var currentPaddingCount = _suman.currentPaddingCount + = (_suman.currentPaddingCount || {}); + currentPaddingCount.val = 1; function runSuite(suite, cb) { if (_suman.sumanUncaughtExceptionTriggered) { _suman.logError("\"UncaughtException:Triggered\" => halting program.\n[" + __filename + "]"); @@ -228,12 +231,12 @@ exports.execSuite = function (suman) { if (children.length < 1) { return process.nextTick(cb); } - sumanOpts.series && (_suman.currentPaddingCount.val += 3); + sumanOpts.series && (currentPaddingCount.val += 3); async.eachLimit(children, limit, function (child, cb) { runSuite(child, cb); }, function (err) { - sumanOpts.series && (_suman.currentPaddingCount.val -= 3); - err && _suman.logError('Suman implementation error => ', err.stack || err); + sumanOpts.series && (currentPaddingCount.val -= 3); + err && _suman.logError('Suman implementation error:', err.stack || err); process.nextTick(cb); }); }); @@ -244,10 +247,8 @@ exports.execSuite = function (suman) { _suman.logError("\"UncaughtException\" event => halting program.\n[" + __filename + "]"); return; } - debugger; if (sumanOpts.parallel_max) { suman.getQueue().drain = function () { - debugger; onSumanCompleted(0, null); }; } diff --git a/lib/exec-suite.ts b/lib/exec-suite.ts index 2dd7bf38..05f2e80e 100755 --- a/lib/exec-suite.ts +++ b/lib/exec-suite.ts @@ -31,7 +31,6 @@ const pragmatik = require('pragmatik'); const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); import rules = require('./helpers/handle-varargs'); import {constants} from '../config/suman-constants'; -import {getQueue} from './helpers/job-queue'; import su from 'suman-utils'; import {makeGracefulExit} from './make-graceful-exit'; import {acquireIocDeps} from './acquire-dependencies/acquire-ioc-deps'; @@ -93,8 +92,9 @@ export const execSuite = function (suman: ISuman): Function { msg: msg } }, function () { - console.log(msg + '\n\n'); - console.error(new Error(' => Suman usage error => invalid arrow/generator function usage.').stack); + console.error(msg + '\n\n'); + let err = new Error('Suman usage error => invalid arrow/generator function usage.').stack; + _suman.logError(err); _suman.writeTestError(err); process.exit(constants.EXIT_CODES.INVALID_ARROW_FUNCTION_USAGE); }); @@ -353,8 +353,6 @@ export const execSuite = function (suman: ISuman): Function { return; } - debugger; - if (sumanOpts.parallel_max) { suman.getQueue().drain = function () { onSumanCompleted(0, null); diff --git a/lib/handle-exit.js b/lib/handle-exit.js index 8671384e..8a7b7801 100755 --- a/lib/handle-exit.js +++ b/lib/handle-exit.js @@ -12,7 +12,12 @@ _suman.isActualExitHandlerRegistered = true; if (!process.prependListener) { process.prependListener = process.on.bind(process); } -process.prependListener('exit', function (code) { +if (!process.prependOnceListener) { + process.prependOnceListener = process.on.bind(process); +} +process.prependOnceListener('exit', function (code) { + var testDebugLogPath = _suman.testDebugLogPath; + debugger; if (errors.length > 0) { code = code || constants.EXIT_CODES.UNEXPECTED_NON_FATAL_ERROR; errors.forEach(function (e) { @@ -24,28 +29,19 @@ process.prependListener('exit', function (code) { else if (testErrors.length > 0) { code = code || constants.EXIT_CODES.TEST_CASE_FAIL; } - if (_suman.writeTestError) { - _suman.writeTestError('\n\n ### Suman end run ### \n\n\n\n', { suppress: true }); - } - if (_suman._writeLog) { - if (process.env.SUMAN_SINGLE_PROCESS === 'yes') { - _suman._writeLog('\n\n\ [ end of Suman run in SUMAN_SINGLE_PROCESS mode ]'); - } - else { - _suman._writeLog('\n\n\ [ end of Suman individual test run for file => "' + _suman._currentModule + '" ]'); - } + if (testDebugLogPath) { } + _suman.writeTestError('\n\n ### Suman end run ### \n\n\n\n', { suppress: true }); if (code > 0 && testErrors.length < 1) { if (!_suman.usingRunner) { - process.stdout.write('\n\n =>' + chalk.underline.bold.yellow(' Suman test process experienced a fatal error during the run, ' + + console.log(chalk.underline.bold.yellow(' Suman test process experienced a fatal error during the run, ' + 'most likely the majority of tests, if not all tests, were not run.') + '\n'); } } if (_suman.checkTestErrorLog) { - process.stdout.write('\n\n =>' + chalk.yellow(' You have some additional errors/warnings - ' + - 'check the test debug log for more information.' + '\n')); - process.stdout.write(' => ' + chalk.underline.bold.yellow(_suman.sumanHelperDirRoot + '/logs/test-debug.log')); - process.stdout.write('\n\n'); + console.log(chalk.yellow(' You have some additional errors/warnings - check the test debug log for more information.')); + console.log(' => ' + chalk.underline.bold.yellow(_suman.sumanHelperDirRoot + '/logs/test-debug.log')); + console.log('\n'); } if (Number.isInteger(_suman.expectedExitCode)) { if (code !== _suman.expectedExitCode) { @@ -64,9 +60,8 @@ process.prependListener('exit', function (code) { } if (!_suman.usingRunner) { var extra = ''; - if (code > 0) { + if (code > 0) extra = ' => see http://sumanjs.org/exit-codes.html'; - } console.log('\n'); var start = void 0; if (start = process.env['SUMAN_START_TIME']) { @@ -76,8 +71,8 @@ process.prependListener('exit', function (code) { console.log('\n'); } if (typeof _suman.absoluteLastHook === 'function') { - _suman.log('killing daemon process, using absolute last hook.'); + _suman.logError('killing daemon process, using absolute last hook.'); _suman.absoluteLastHook(code); } - process.exit(code); + process.exitCode = code; }); diff --git a/lib/handle-exit.ts b/lib/handle-exit.ts index 81516c33..1061a3f5 100755 --- a/lib/handle-exit.ts +++ b/lib/handle-exit.ts @@ -16,9 +16,8 @@ import assert = require('assert'); import * as chalk from 'chalk'; import su from 'suman-utils'; - //project -const _suman : IGlobalSumanObj = global.__suman = (global.__suman || {}); +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); const {constants} = require('../config/suman-constants'); const testErrors = _suman.testErrors = _suman.testErrors || []; const errors = _suman.sumanRuntimeErrors = _suman.sumanRuntimeErrors || []; @@ -31,45 +30,47 @@ if (!process.prependListener) { process.prependListener = process.on.bind(process); } -process.prependListener('exit', function (code: number) { +if (!process.prependOnceListener) { + process.prependOnceListener = process.on.bind(process); +} + +process.prependOnceListener('exit', function (code: number) { + + const testDebugLogPath = _suman.testDebugLogPath; + debugger; if (errors.length > 0) { code = code || constants.EXIT_CODES.UNEXPECTED_NON_FATAL_ERROR; errors.forEach(function (e: Error) { let eStr = su.getCleanErrorString(e); - _suman.usingRunner && process.stderr.write(eStr); - _suman.writeTestError && _suman.writeTestError(eStr); + _suman.usingRunner && process.stderr.write(eStr); + _suman.writeTestError && _suman.writeTestError(eStr); }); } else if (testErrors.length > 0) { code = code || constants.EXIT_CODES.TEST_CASE_FAIL; } - if (_suman.writeTestError) { - _suman.writeTestError('\n\n ### Suman end run ### \n\n\n\n', {suppress: true}); + if (testDebugLogPath) { + // fs.appendFileSync(testDebugLogPath, 'nonsesnse nonsesnse nosneses\n'); + // fs.appendFileSync(testDebugLogPath, 'nonsesnse nonsesnse nosneses\n'); + // fs.appendFileSync(testDebugLogPath, 'nonsesnse nonsesnse nosneses\n'); + // fs.appendFileSync(testDebugLogPath, 'nonsesnse nonsesnse nosneses\n'); } - if (_suman._writeLog) { - if (process.env.SUMAN_SINGLE_PROCESS === 'yes') { - _suman._writeLog('\n\n\ [ end of Suman run in SUMAN_SINGLE_PROCESS mode ]'); - } - else { - _suman._writeLog('\n\n\ [ end of Suman individual test run for file => "' + _suman._currentModule + '" ]'); - } - } + _suman.writeTestError('\n\n ### Suman end run ### \n\n\n\n', {suppress: true}); - if (code > 0 && testErrors.length < 1) { //TODO: fix this with logic saying if code > 0 and code < 60 or something + if (code > 0 && testErrors.length < 1) { if (!_suman.usingRunner) { //TODO: need to fix this - process.stdout.write('\n\n =>' + chalk.underline.bold.yellow(' Suman test process experienced a fatal error during the run, ' + + console.log(chalk.underline.bold.yellow(' Suman test process experienced a fatal error during the run, ' + 'most likely the majority of tests, if not all tests, were not run.') + '\n'); } } if (_suman.checkTestErrorLog) { - process.stdout.write('\n\n =>' + chalk.yellow(' You have some additional errors/warnings - ' + - 'check the test debug log for more information.' + '\n')); - process.stdout.write(' => ' + chalk.underline.bold.yellow(_suman.sumanHelperDirRoot + '/logs/test-debug.log')); - process.stdout.write('\n\n'); + console.log(chalk.yellow(' You have some additional errors/warnings - check the test debug log for more information.')); + console.log(' => ' + chalk.underline.bold.yellow(_suman.sumanHelperDirRoot + '/logs/test-debug.log')); + console.log('\n'); } if (Number.isInteger(_suman.expectedExitCode)) { @@ -91,9 +92,7 @@ process.prependListener('exit', function (code: number) { if (!_suman.usingRunner) { let extra = ''; - if (code > 0) { - extra = ' => see http://sumanjs.org/exit-codes.html'; - } + if (code > 0) extra = ' => see http://sumanjs.org/exit-codes.html'; console.log('\n'); @@ -106,12 +105,13 @@ process.prependListener('exit', function (code: number) { } if (typeof _suman.absoluteLastHook === 'function') { - _suman.log('killing daemon process, using absolute last hook.'); + _suman.logError('killing daemon process, using absolute last hook.'); _suman.absoluteLastHook(code); } - // => we probably don't need this... - process.exit(code); + // this is important, because we *can* change the exit code by using this call + process.exitCode = code; + // process.exit(code); }); diff --git a/lib/helpers/add-suman-global-properties.js b/lib/helpers/add-suman-global-properties.js index e13aed29..1dde17ab 100755 --- a/lib/helpers/add-suman-global-properties.js +++ b/lib/helpers/add-suman-global-properties.js @@ -5,7 +5,6 @@ var global = require('suman-browser-polyfills/modules/global'); var chalk = require("chalk"); var log_prepend_1 = require("log-prepend"); var _suman = global.__suman = (global.__suman || {}); -debugger; if (!('SUMAN_INCEPTION_LEVEL' in process.env) || process.argv.indexOf('--force-inception-level-zero')) { _suman.inceptionLevel = 0; process.env.SUMAN_INCEPTION_LEVEL = 0; diff --git a/lib/helpers/add-suman-global-properties.ts b/lib/helpers/add-suman-global-properties.ts index dc7f71de..6155eb28 100755 --- a/lib/helpers/add-suman-global-properties.ts +++ b/lib/helpers/add-suman-global-properties.ts @@ -9,12 +9,11 @@ const global = require('suman-browser-polyfills/modules/global'); //npm import * as chalk from 'chalk'; import {lp} from 'log-prepend'; +import {pt} from 'prepend-transform'; //project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); -debugger; - if (!('SUMAN_INCEPTION_LEVEL' in process.env) || process.argv.indexOf('--force-inception-level-zero')) { _suman.inceptionLevel = 0; process.env.SUMAN_INCEPTION_LEVEL = 0; diff --git a/lib/helpers/handle-suman-counts.js b/lib/helpers/handle-suman-counts.js index 1140a868..c7566091 100755 --- a/lib/helpers/handle-suman-counts.js +++ b/lib/helpers/handle-suman-counts.js @@ -2,18 +2,19 @@ Object.defineProperty(exports, "__esModule", { value: true }); var process = require('suman-browser-polyfills/modules/process'); var global = require('suman-browser-polyfills/modules/global'); +var util = require("util"); var EE = require("events"); var fs = require("fs"); var suman_events_1 = require("suman-events"); +var su = require("suman-utils"); var _suman = global.__suman = (global.__suman || {}); var handle_runner_request_response_1 = require("../index-helpers/handle-runner-request-response"); var counts = require('./suman-counts'); var handle_suman_once_post_1 = require("./handle-suman-once-post"); -var suiteResultEmitter = _suman.suiteResultEmitter = (_suman.suiteResultEmitter || new EE()); -var resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); -var results = _suman.tableResults = (_suman.tableResults || []); +var suiteResultEmitter = _suman.suiteResultEmitter = _suman.suiteResultEmitter || new EE(); +var resultBroadcaster = _suman.resultBroadcaster = _suman.resultBroadcaster || new EE(); +var results = _suman.tableResults = _suman.tableResults || []; suiteResultEmitter.once('suman-test-file-complete', function () { - debugger; var fn, resultz; if (_suman.usingRunner) { resultz = results.map(function (i) { return i.tableData; }); @@ -28,7 +29,9 @@ suiteResultEmitter.once('suman-test-file-complete', function () { fn = handle_suman_once_post_1.oncePostFn; } var codes = results.map(function (i) { return i.exitCode; }); - _suman.log(' => All "exit" codes from test suites => ', codes); + if (su.vgt(6)) { + _suman.log(' => All "exit" codes from test suites => ', util.inspect(codes)); + } var highestExitCode = Math.max.apply(null, codes); fn(function (err) { err && _suman.logError(err.stack || err); @@ -40,11 +43,12 @@ suiteResultEmitter.once('suman-test-file-complete', function () { return process.nextTick(cb); } var timedout = false; - var to = setTimeout(function () { + var timeout = _suman.usingRunner ? 20 : 10; + var onTimeout = function () { timedout = true; - _suman.logWarning('Drain callback timed out, exitting +.'); cb(null); - }, _suman.usingRunner ? 20 : 10); + }; + var to = setTimeout(onTimeout, timeout); _suman.drainCallback = function (logpath) { clearTimeout(to); _suman.logWarning('Drain callback was actually called.'); diff --git a/lib/helpers/handle-suman-counts.ts b/lib/helpers/handle-suman-counts.ts index 0e624090..1b25cef3 100755 --- a/lib/helpers/handle-suman-counts.ts +++ b/lib/helpers/handle-suman-counts.ts @@ -2,7 +2,7 @@ //dts import {IGlobalSumanObj, IPseudoError} from "suman-types/dts/global"; -import {ITableDataCallbackObj} from "../suman"; +import {ITableDataCallbackObj} from "suman-types/dts/suman"; //polyfills const process = require('suman-browser-polyfills/modules/process'); @@ -16,25 +16,20 @@ import fs = require('fs'); //npm import {events} from 'suman-events'; import su = require('suman-utils'); -import chalk = require('chalk'); //project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); import {handleRequestResponseWithRunner} from '../index-helpers/handle-runner-request-response'; - const counts = require('./suman-counts'); import {oncePostFn} from './handle-suman-once-post'; - -const suiteResultEmitter = _suman.suiteResultEmitter = (_suman.suiteResultEmitter || new EE()); -const resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); -const results: Array = _suman.tableResults = (_suman.tableResults || []); +const suiteResultEmitter = _suman.suiteResultEmitter = _suman.suiteResultEmitter || new EE(); +const resultBroadcaster = _suman.resultBroadcaster = _suman.resultBroadcaster || new EE(); +const results: Array = _suman.tableResults = _suman.tableResults || []; /////////////////////////////////////////////////////////////////// suiteResultEmitter.once('suman-test-file-complete', function () { - debugger; - let fn, resultz; if (_suman.usingRunner) { @@ -46,7 +41,6 @@ suiteResultEmitter.once('suman-test-file-complete', function () { // i may not be defined if testsuite (rootsuite) was skipped resultz = results.map(i => i ? i : null).filter(i => i); - resultz.forEach(function (r) { resultBroadcaster.emit(String(events.STANDARD_TABLE), r.tableData, r.exitCode); }); @@ -55,7 +49,9 @@ suiteResultEmitter.once('suman-test-file-complete', function () { } const codes = results.map(i => i.exitCode); - _suman.log(' => All "exit" codes from test suites => ', codes); + if (su.vgt(6)) { + _suman.log(' => All "exit" codes from test suites => ', util.inspect(codes)); + } const highestExitCode = Math.max.apply(null, codes); @@ -64,7 +60,6 @@ suiteResultEmitter.once('suman-test-file-complete', function () { err && _suman.logError(err.stack || err); // this is for testing expected test result counts resultBroadcaster.emit(String(events.META_TEST_ENDED)); - _suman.endLogStream && _suman.endLogStream(); let waitForStdioToDrain = function (cb: Function) { @@ -75,11 +70,14 @@ suiteResultEmitter.once('suman-test-file-complete', function () { } let timedout = false; - let to = setTimeout(function () { + let timeout = _suman.usingRunner ? 20 : 10; + + let onTimeout = function () { timedout = true; - _suman.logWarning('Drain callback timed out, exitting +.'); cb(null); - }, _suman.usingRunner ? 20 : 10); + }; + + let to = setTimeout(onTimeout, timeout); _suman.drainCallback = function (logpath: string) { clearTimeout(to); diff --git a/lib/helpers/job-queue.d.ts b/lib/helpers/job-queue.d.ts deleted file mode 100755 index 5263b30b..00000000 --- a/lib/helpers/job-queue.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const getQueue: () => any; diff --git a/lib/helpers/job-queue.js b/lib/helpers/job-queue.js deleted file mode 100755 index 3a1db612..00000000 --- a/lib/helpers/job-queue.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; -Object.defineProperty(exports, "__esModule", { value: true }); -var process = require('suman-browser-polyfills/modules/process'); -var global = require('suman-browser-polyfills/modules/global'); -var assert = require("assert"); -var async = require("async"); -var _suman = global.__suman = (global.__suman || {}); -var constants = require('../../config/suman-constants').constants; -var queue, envTotal, envConfig; -if (process.env.DEFAULT_PARALLEL_TOTAL_LIMIT && (envTotal = Number(process.env.DEFAULT_PARALLEL_TOTAL_LIMIT))) { - assert(Number.isInteger(envTotal), 'process.env.DEFAULT_PARALLEL_TOTAL_LIMIT cannot be cast to an integer.'); -} -exports.getQueue = function () { - if (!queue) { - var sumanConfig = _suman.sumanConfig, sumanOpts = _suman.sumanOpts; - if (sumanConfig.DEFAULT_PARALLEL_TOTAL_LIMIT && - (envConfig = Number(_suman.sumanConfig.DEFAULT_PARALLEL_TOTAL_LIMIT))) { - assert(Number.isInteger(envConfig), 'process.env.DEFAULT_PARALLEL_TOTAL_LIMIT cannot be cast to an integer.'); - } - var c = 1; - if (!sumanOpts.series) { - c = envTotal || envConfig || constants.DEFAULT_PARALLEL_TOTAL_LIMIT; - } - assert(Number.isInteger(c) && c > 0 && c < 301, 'DEFAULT_PARALLEL_TOTAL_LIMIT must be an integer between 1 and 300 inclusive.'); - queue = async.queue(function (task, cb) { - task(cb); - }, c); - } - return queue; -}; diff --git a/lib/helpers/job-queue.ts b/lib/helpers/job-queue.ts deleted file mode 100755 index 93a189db..00000000 --- a/lib/helpers/job-queue.ts +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; - -import {IGlobalSumanObj} from "suman-types/dts/global"; - -//polyfills -const process = require('suman-browser-polyfills/modules/process'); -const global = require('suman-browser-polyfills/modules/global'); - -//core -import assert = require('assert'); - -// npm -import async = require('async'); - -//project -const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); -const {constants} = require('../../config/suman-constants'); - -let queue: any, envTotal: number, envConfig: number; - -if (process.env.DEFAULT_PARALLEL_TOTAL_LIMIT && (envTotal = Number(process.env.DEFAULT_PARALLEL_TOTAL_LIMIT))) { - assert(Number.isInteger(envTotal), 'process.env.DEFAULT_PARALLEL_TOTAL_LIMIT cannot be cast to an integer.'); -} - -export const getQueue = function () { - - if (!queue) { - - const {sumanConfig, sumanOpts} = _suman; - // note: we have to create the queue after loading this file, so that _suman.sumanConfig is defined. - - if (sumanConfig.DEFAULT_PARALLEL_TOTAL_LIMIT && - (envConfig = Number(_suman.sumanConfig.DEFAULT_PARALLEL_TOTAL_LIMIT))) { - assert(Number.isInteger(envConfig), 'process.env.DEFAULT_PARALLEL_TOTAL_LIMIT cannot be cast to an integer.'); - } - - let c = 1; // concurrency - - if (!sumanOpts.series) { - c = envTotal || envConfig || constants.DEFAULT_PARALLEL_TOTAL_LIMIT; - } - - assert(Number.isInteger(c) && c > 0 && c < 301, - 'DEFAULT_PARALLEL_TOTAL_LIMIT must be an integer between 1 and 300 inclusive.'); - - queue = async.queue(function (task: Function, cb: Function) { - task(cb); - }, c); - - } - - return queue; - -}; diff --git a/lib/helpers/load-reporters.js b/lib/helpers/load-reporters.js index 6fa6c114..a81b1d23 100755 --- a/lib/helpers/load-reporters.js +++ b/lib/helpers/load-reporters.js @@ -26,7 +26,8 @@ exports.loadReporters = function (sumanOpts, projectRoot, sumanConfig) { _suman.logWarning('a reporter path was undefined.'); } return v; - }).map(function (item) { + }) + .map(function (item) { if (!path.isAbsolute(item)) { item = path.resolve(projectRoot + '/' + item); } diff --git a/lib/helpers/log-stdio-of-child.js b/lib/helpers/log-stdio-of-child.js index f766b00d..e1a360df 100755 --- a/lib/helpers/log-stdio-of-child.js +++ b/lib/helpers/log-stdio-of-child.js @@ -15,7 +15,9 @@ exports.run = function (filePath) { } callable = false; if (process.env.MAKE_SUMAN_LOG !== 'no') { - _suman.log('we are logging child stdout/stderr to files.', '\n'); + if (su.vgt(6)) { + _suman.log('we are logging child stdout/stderr to files.', '\n'); + } var timestamp = process.env.SUMAN_RUNNER_TIMESTAMP; var runId = process.env.SUMAN_RUN_ID; var logsDir = _suman.sumanConfig.logsDir || _suman.sumanHelperDirRoot + '/logs'; @@ -38,8 +40,9 @@ exports.run = function (filePath) { }); _suman.endLogStream = function () { writeToFileStream_1 = false; + strm_1.end('this is the end\n'); }; - strm_1.once('end', function () { + strm_1.on('drain', function () { _suman.isStrmDrained = true; _suman.drainCallback && _suman.drainCallback(logfile_1); }); @@ -49,12 +52,7 @@ exports.run = function (filePath) { _suman.isStrmDrained = false; isDeleteFile_1 = false; if (writeToFileStream_1) { - try { - strm_1.write.apply(strm_1, arguments); - } - catch (e) { - _suman.logError(e.stack || e); - } + strm_1.write.apply(strm_1, arguments); } stderrWrite_1.apply(process.stderr, arguments); }; @@ -81,9 +79,7 @@ exports.run = function (filePath) { } } else { - fs.appendFileSync(logfile_1, '\n => This is the end of the test.'); } }); } - console.log('\n'); }; diff --git a/lib/helpers/log-stdio-of-child.ts b/lib/helpers/log-stdio-of-child.ts index 5026690c..0cfce70b 100755 --- a/lib/helpers/log-stdio-of-child.ts +++ b/lib/helpers/log-stdio-of-child.ts @@ -16,10 +16,8 @@ const replaceStrm = require('replacestream'); import * as chalk from 'chalk'; //project -const _suman : IGlobalSumanObj = global.__suman = (global.__suman || {}); +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); import su = require('suman-utils'); - - const SUMAN_SINGLE_PROCESS = process.env.SUMAN_SINGLE_PROCESS === 'yes'; //////////////////////////////////////////////////////////////////////////////// @@ -36,7 +34,10 @@ export const run = function (filePath: string) { if (process.env.MAKE_SUMAN_LOG !== 'no') { - _suman.log('we are logging child stdout/stderr to files.','\n'); + if (su.vgt(6)) { + _suman.log('we are logging child stdout/stderr to files.', '\n'); + } + const timestamp = process.env.SUMAN_RUNNER_TIMESTAMP; const runId = process.env.SUMAN_RUN_ID; const logsDir = _suman.sumanConfig.logsDir || _suman.sumanHelperDirRoot + '/logs'; @@ -67,10 +68,11 @@ export const run = function (filePath: string) { // _suman.logError('endLogStream finished.'); // rstrm.unpipe(); writeToFileStream = false; - // strm.end(); + strm.end('this is the end\n'); + }; - strm.once('end', function () { + strm.on('drain', function () { _suman.isStrmDrained = true; _suman.drainCallback && _suman.drainCallback(logfile); }); @@ -80,14 +82,19 @@ export const run = function (filePath: string) { process.stderr.write = function () { _suman.isStrmDrained = false; isDeleteFile = false; - if(writeToFileStream){ - try { - strm.write.apply(strm, arguments); - } - catch (e) { - _suman.logError(e.stack || e); - } + // if (writeToFileStream) { + // try { + // strm.write.apply(strm, arguments); + // } + // catch (e) { + // _suman.logError(e.stack || e); + // } + // } + + if (writeToFileStream) { + strm.write.apply(strm, arguments); } + stderrWrite.apply(process.stderr, arguments); }; } @@ -99,7 +106,7 @@ export const run = function (filePath: string) { process.stdout.write = function () { _suman.isStrmDrained = false; isDeleteFile = false; - if(writeToFileStream){ + if (writeToFileStream) { strm.write.apply(strm, arguments); } stdoutWrite.apply(process.stdout, arguments); @@ -118,10 +125,9 @@ export const run = function (filePath: string) { } } else { - fs.appendFileSync(logfile, '\n => This is the end of the test.'); + // fs.appendFileSync(logfile, '\n => This is the end of the test.'); } }); } - console.log('\n'); }; diff --git a/lib/helpers/resolve-shared-dirs.js b/lib/helpers/resolve-shared-dirs.js index 853e12e1..0506e181 100755 --- a/lib/helpers/resolve-shared-dirs.js +++ b/lib/helpers/resolve-shared-dirs.js @@ -40,15 +40,13 @@ exports.resolveSharedDirs = function (sumanConfig, projectRoot, sumanOpts) { var testSrcDirDefined = !!sumanConfig.testSrcDir; var testDir = process.env.TEST_DIR = _suman.testDir = path.resolve(projectRoot + '/' + (sumanConfig.testDir || 'test')); var testSrcDir = process.env.TEST_SRC_DIR = _suman.testSrcDir = path.resolve(projectRoot + '/' + (sumanConfig.testSrcDir || 'test')); - var errStrmPath = path.resolve(sumanHelpersDir + '/logs/test-debug.log'); - var strmStdoutPath = path.resolve(sumanHelpersDir + '/logs/test-output.log'); + var debugStreamPath = path.resolve(sumanHelpersDir + '/logs/test-debug.log'); return loaded = Object.freeze({ sumanHelpersDir: _suman.sumanHelperDirRoot = process.env.SUMAN_HELPERS_DIR_ROOT = sumanHelpersDir, sumanLogDir: _suman.sumanLogDir = logDir, integPrePath: _suman.integPrePath = integPrePath, integPostPath: _suman.integPostPath = integPostPath, sumanHelpersDirLocated: sumanHelpersDirLocated, - testDebugLogPath: errStrmPath, - testLogPath: strmStdoutPath + testDebugLogPath: _suman.testDebugLogPath = debugStreamPath }); }; diff --git a/lib/helpers/resolve-shared-dirs.ts b/lib/helpers/resolve-shared-dirs.ts index 7064cec0..808f45eb 100755 --- a/lib/helpers/resolve-shared-dirs.ts +++ b/lib/helpers/resolve-shared-dirs.ts @@ -53,7 +53,7 @@ export const resolveSharedDirs = function (sumanConfig: ISumanConfig, projectRoo } catch (err) { console.error('\n\n', chalk.magenta('=> Suman could *not* locate your ; ' + - 'perhaps you need to update your suman.conf.js file, please see: ***'), '\n', + 'perhaps you need to update your suman.conf.js file, please see: ***'), '\n', chalk.cyan(' => http://sumanjs.org/conf.html'), '\n', ' => We expected to find your here =>', '\n', chalk.bgBlack.cyan(sumanHelpersDir), '\n'); @@ -71,8 +71,7 @@ export const resolveSharedDirs = function (sumanConfig: ISumanConfig, projectRoo const testSrcDirDefined = !!sumanConfig.testSrcDir; //TODO: check for valid string const testDir = process.env.TEST_DIR = _suman.testDir = path.resolve(projectRoot + '/' + (sumanConfig.testDir || 'test')); const testSrcDir = process.env.TEST_SRC_DIR = _suman.testSrcDir = path.resolve(projectRoot + '/' + (sumanConfig.testSrcDir || 'test')); - const errStrmPath = path.resolve(sumanHelpersDir + '/logs/test-debug.log'); - const strmStdoutPath = path.resolve(sumanHelpersDir + '/logs/test-output.log'); + const debugStreamPath = path.resolve(sumanHelpersDir + '/logs/test-debug.log'); return loaded = Object.freeze({ sumanHelpersDir: _suman.sumanHelperDirRoot = process.env.SUMAN_HELPERS_DIR_ROOT = sumanHelpersDir, @@ -80,8 +79,7 @@ export const resolveSharedDirs = function (sumanConfig: ISumanConfig, projectRoo integPrePath: _suman.integPrePath = integPrePath, integPostPath: _suman.integPostPath = integPostPath, sumanHelpersDirLocated: sumanHelpersDirLocated, - testDebugLogPath: errStrmPath, - testLogPath: strmStdoutPath + testDebugLogPath: _suman.testDebugLogPath = debugStreamPath }); }; diff --git a/lib/index-helpers/exit-handling.js b/lib/index-helpers/exit-handling.js index e0553fe6..2edb3f69 100755 --- a/lib/index-helpers/exit-handling.js +++ b/lib/index-helpers/exit-handling.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var process = require('suman-browser-polyfills/modules/process'); var global = require('suman-browser-polyfills/modules/global'); @@ -29,7 +29,7 @@ var shutdownSuman = function (msg) { handle_suman_once_post_1.oncePostFn(cb); } else { - _suman.logError('Suman internal warning, oncePostFn not yet defined.'); + _suman.logError('Suman internal warning, "oncePostFn" not yet defined.'); process.nextTick(cb); } }, @@ -87,7 +87,7 @@ process.on('SIGTERM', function () { process.exit(1); } else if (sigtermCount === 1) { - shutdownSuman('SIGINT received'); + shutdownSuman('SIGTERM received'); } }); process.on('warning', function (w) { @@ -98,6 +98,7 @@ process.on('warning', function (w) { console.error(w.stack || w); } }); +process.removeAllListeners('uncaughtException'); process.on('uncaughtException', function (err) { if (!err) { err = new Error('falsy value passed to uncaught exception handler.'); @@ -118,6 +119,12 @@ process.on('uncaughtException', function (err) { if (_suman.afterAlwaysEngaged) { return; } + if (_suman.sumanOpts && _suman.sumanOpts.series) { + if (_suman.activeDomain) { + _suman.activeDomain.emit('error', err); + return; + } + } if (!_suman.sumanOpts || _suman.sumanOpts.ignoreUncaughtExceptions !== false) { _suman.sumanUncaughtExceptionTriggered = err; setTimeout(function () { @@ -138,21 +145,27 @@ process.on('uncaughtException', function (err) { }); process.removeAllListeners('unhandledRejection'); process.on('unhandledRejection', function ($reason, p) { + var reason = $reason ? ($reason.stack || $reason) : new Error('no reason passed to unhandledRejection handler.'); if (p && p.domain) { if (p.domain.sumanTestCase || p.domain.sumanEachHook || p.domain.sumanAllHook) { - $reason && typeof $reason === 'object' && ($reason._alreadyHandledBySuman = true); - p.domain.emit('error', $reason); + typeof reason === 'object' && (reason._alreadyHandledBySuman = true); + p.domain.emit('error', reason); return; } } if (process.domain) { if (process.domain.sumanTestCase || process.domain.sumanEachHook || process.domain.sumanAllHook) { - $reason && typeof $reason === 'object' && ($reason._alreadyHandledBySuman = true); - process.domain.emit('error', $reason); + typeof reason === 'object' && ($reason._alreadyHandledBySuman = true); + process.domain.emit('error', reason); + return; + } + } + if (_suman.sumanOpts && _suman.sumanOpts.series) { + if (_suman.activeDomain) { + _suman.activeDomain.emit('error', reason); return; } } - var reason = ($reason.stack || $reason); console.error('\n'); _suman.logError(chalk.magenta.bold('Unhandled Rejection at Promise:'), chalk.magenta(util.inspect(p))); console.error('\n'); diff --git a/lib/index-helpers/exit-handling.ts b/lib/index-helpers/exit-handling.ts index 49ab2f46..60263dc0 100755 --- a/lib/index-helpers/exit-handling.ts +++ b/lib/index-helpers/exit-handling.ts @@ -1,4 +1,6 @@ -//typescript imports +'use strict'; + +//dts import {IGlobalSumanObj, IPromiseWithDomain, ISumanDomain, SumanErrorRace} from "suman-types/dts/global"; //polyfills @@ -18,18 +20,21 @@ const {fatalRequestReply} = require('../helpers/fatal-request-reply'); import {constants} from '../../config/suman-constants'; import {oncePostFn} from '../helpers/handle-suman-once-post'; import {runAfterAlways} from '../helpers/run-after-always'; - const sumanRuntimeErrors = _suman.sumanRuntimeErrors = _suman.sumanRuntimeErrors || []; const weAreDebugging = require('../helpers/we-are-debugging'); /////////////////////////////////////////////////////////////////////////////////////// +type AsyncFuncType = AsyncResultArrayCallback, Error>; + +////////////////////////////////////////////////////////////////////////////////////// + const shutdownSuman = function (msg: string) { async.parallel([ - function (cb: AsyncResultArrayCallback, Error>) { + function (cb: AsyncFuncType) { async.series([ - function (cb: AsyncResultArrayCallback, Error>) { + function (cb: AsyncFuncType) { if (runAfterAlways && _suman.whichSuman) { runAfterAlways(_suman.whichSuman, cb); } @@ -38,12 +43,12 @@ const shutdownSuman = function (msg: string) { } }, - function (cb: AsyncResultArrayCallback, Error>) { + function (cb: AsyncFuncType) { if (oncePostFn) { oncePostFn(cb); } else { - _suman.logError('Suman internal warning, oncePostFn not yet defined.'); + _suman.logError('Suman internal warning, "oncePostFn" not yet defined.'); process.nextTick(cb); } }, @@ -119,7 +124,7 @@ process.on('SIGTERM', function () { process.exit(1); } else if (sigtermCount === 1) { - shutdownSuman('SIGINT received'); + shutdownSuman('SIGTERM received'); } }); @@ -136,6 +141,8 @@ process.on('warning', function (w: Error) { } }); +// remove all pre-existing listeners +process.removeAllListeners('uncaughtException'); process.on('uncaughtException', function (err: SumanErrorRace) { if (!err) { @@ -150,11 +157,6 @@ process.on('uncaughtException', function (err: SumanErrorRace) { } } - /* - - @benjamingr yeah I am working on sumanjs/suman - it's a test runner - TapJS and Lab among others also see the same need for domains. Once Node.js test runners started parallelizing tests, putting the current executing test in the global scope was no longer possible, since tests/hooks would interleave. So all these test runners are using domains to solve the problem atm. AVA parallelizes tests, but they are relying on promises and async/await to trap errors. IMO for edge cases it's not quite good enough yet, so like TapJS and Lab, I decided to use domains. - */ - if (err._alreadyHandledBySuman) { console.error(' => Error already handled => \n', (err.stack || err)); return; @@ -168,6 +170,13 @@ process.on('uncaughtException', function (err: SumanErrorRace) { return; } + if (_suman.sumanOpts && _suman.sumanOpts.series) { + if (_suman.activeDomain) { + _suman.activeDomain.emit('error', err); + return; + } + } + if (!_suman.sumanOpts || _suman.sumanOpts.ignoreUncaughtExceptions !== false) { _suman.sumanUncaughtExceptionTriggered = err; @@ -201,23 +210,31 @@ process.removeAllListeners('unhandledRejection'); process.on('unhandledRejection', ($reason: any, p: IPromiseWithDomain) => { + const reason = $reason ? ($reason.stack || $reason) : new Error('no reason passed to unhandledRejection handler.'); + if (p && p.domain) { if (p.domain.sumanTestCase || p.domain.sumanEachHook || p.domain.sumanAllHook) { - $reason && typeof $reason === 'object' && ($reason._alreadyHandledBySuman = true); - p.domain.emit('error', $reason); + typeof reason === 'object' && (reason._alreadyHandledBySuman = true); + p.domain.emit('error', reason); return; } } if (process.domain) { if (process.domain.sumanTestCase || process.domain.sumanEachHook || process.domain.sumanAllHook) { - $reason && typeof $reason === 'object' && ($reason._alreadyHandledBySuman = true); - process.domain.emit('error', $reason); + typeof reason === 'object' && ($reason._alreadyHandledBySuman = true); + process.domain.emit('error', reason); + return; + } + } + + if (_suman.sumanOpts && _suman.sumanOpts.series) { + if (_suman.activeDomain) { + _suman.activeDomain.emit('error', reason); return; } } - const reason = ($reason.stack || $reason); console.error('\n'); _suman.logError(chalk.magenta.bold('Unhandled Rejection at Promise:'), chalk.magenta(util.inspect(p))); console.error('\n'); diff --git a/lib/index-helpers/handle-integrants.js b/lib/index-helpers/handle-integrants.js index e7c352f9..90b14722 100755 --- a/lib/index-helpers/handle-integrants.js +++ b/lib/index-helpers/handle-integrants.js @@ -32,13 +32,17 @@ exports.handleIntegrants = function (integrants, $oncePost, integrantPreFn, $mod if (waitForResponseFromRunnerRegardingPostList) { postOnlyReady = false; } + var client, usingRunner = _suman.usingRunner; if (integrants.length < 1) { + if (usingRunner) { + socketio_child_client_1.getClient(); + } integrantsFn = function () { return Promise.resolve({}); }; } - else if (_suman.usingRunner) { - var client_1 = socketio_child_client_1.getClient(); + else if (usingRunner) { + client = socketio_child_client_1.getClient(); integrantsFn = function () { return new Promise(function (resolve, reject) { var oncePreVals; @@ -61,8 +65,8 @@ exports.handleIntegrants = function (integrants, $oncePost, integrantPreFn, $mod } }; var INTEGRANT_INFO = suman_constants_1.constants.runner_message_type.INTEGRANT_INFO; - client_1.on(INTEGRANT_INFO, integrantMessage); - client_1.emit(INTEGRANT_INFO, { + client.on(INTEGRANT_INFO, integrantMessage); + client.emit(INTEGRANT_INFO, { type: INTEGRANT_INFO, msg: integrants, oncePost: $oncePost, diff --git a/lib/index-helpers/handle-integrants.ts b/lib/index-helpers/handle-integrants.ts index 471bed36..1a87ab55 100755 --- a/lib/index-helpers/handle-integrants.ts +++ b/lib/index-helpers/handle-integrants.ts @@ -1,24 +1,24 @@ 'use strict'; -//typescript imports +// dts import {IGlobalSumanObj} from "suman-types/dts/global"; import {IIntegrantsMessage, ISumanModuleExtended} from "suman-types/dts/index-init"; -//polyfills +// polyfills const process = require('suman-browser-polyfills/modules/process'); const global = require('suman-browser-polyfills/modules/global'); -//core +// core import domain = require('domain'); import util = require('util'); import EE = require('events'); -//npm +// npm import * as chalk from 'chalk'; import * as fnArgs from 'function-arguments'; import su from 'suman-utils'; -//project +// project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); if (!('integrantHashKeyVals' in _suman)) { @@ -31,10 +31,8 @@ if (!('integrantHashKeyVals' in _suman)) { const {acquirePreDeps} = require('../acquire-dependencies/acquire-pre-deps'); import {constants} from '../../config/suman-constants'; import integrantInjector from '../injection/integrant-injector'; - const IS_SUMAN_SINGLE_PROCESS = process.env.SUMAN_SINGLE_PROCESS === 'yes'; import {getClient} from './socketio-child-client'; - let integPreConfiguration: any = null; ///////////////////////////////////////////////////////////////////////////////////////////// @@ -57,14 +55,22 @@ export const handleIntegrants = function (integrants: Array, $oncePost: postOnlyReady = false; } + let client: SocketIOClient.Socket, usingRunner = _suman.usingRunner; + if (integrants.length < 1) { + + if (usingRunner) { + // we should start establishing a connection now, to get ahead of things + getClient(); + } + integrantsFn = function () { return Promise.resolve({}); } } - else if (_suman.usingRunner) { + else if (usingRunner) { - const client = getClient(); + client = getClient(); integrantsFn = function () { @@ -143,7 +149,7 @@ export const handleIntegrants = function (integrants: Array, $oncePost: d.run(function () { - if(!integPreConfiguration){ + if (!integPreConfiguration) { throw new Error('suman implementation error, missing definition.'); } // with suman single process, or not, we acquire integrants the same way diff --git a/lib/index-helpers/handle-runner-request-response.js b/lib/index-helpers/handle-runner-request-response.js index 5fe85a96..74f1f3d9 100755 --- a/lib/index-helpers/handle-runner-request-response.js +++ b/lib/index-helpers/handle-runner-request-response.js @@ -35,7 +35,7 @@ exports.handleRequestResponseWithRunner = function (data) { timedout = true; _suman.logError('Action to receive table data response from runner timed out.'); cb(null); - }, 100); + }, 1000); client.on(TABLE_DATA, function onTableDataReceived(data) { if (data.info = 'table-data-received' && timedout === false) { clearTimeout(to); diff --git a/lib/index-helpers/handle-runner-request-response.ts b/lib/index-helpers/handle-runner-request-response.ts index 8e3928aa..073746fb 100755 --- a/lib/index-helpers/handle-runner-request-response.ts +++ b/lib/index-helpers/handle-runner-request-response.ts @@ -61,7 +61,7 @@ export const handleRequestResponseWithRunner = function (data: Array) { timedout = true; _suman.logError('Action to receive table data response from runner timed out.'); cb(null); - }, 100); + }, 1000); client.on(TABLE_DATA, function onTableDataReceived(data: Object) { if (data.info = 'table-data-received' && timedout === false) { diff --git a/lib/index-helpers/setup-extra-loggers.d.ts b/lib/index-helpers/setup-extra-loggers.d.ts deleted file mode 100755 index ce2787f3..00000000 --- a/lib/index-helpers/setup-extra-loggers.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { ISumanModuleExtended } from "suman-types/dts/index-init"; -export default function (usingRunner: boolean, testDebugLogPath: string, testLogPath: string, $module: ISumanModuleExtended): void; diff --git a/lib/index-helpers/setup-extra-loggers.js b/lib/index-helpers/setup-extra-loggers.js deleted file mode 100755 index e553911b..00000000 --- a/lib/index-helpers/setup-extra-loggers.js +++ /dev/null @@ -1,67 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var process = require('suman-browser-polyfills/modules/process'); -var global = require('suman-browser-polyfills/modules/global'); -var assert = require("assert"); -var util = require("util"); -var fs = require("fs"); -var inBrowser = false; -var _suman = global.__suman = (global.__suman || {}); -var IS_SUMAN_DEBUG = process.env.SUMAN_DEBUG === 'yes'; -var SUMAN_SINGLE_PROCESS = process.env.SUMAN_SINGLE_PROCESS === 'yes'; -var callable = true; -function default_1(usingRunner, testDebugLogPath, testLogPath, $module) { - if (usingRunner && callable) { - callable = false; - _suman.writeTestError = function (data, options) { - if (!data) { - data = new Error('falsy data passed to writeTestError').stack; - } - if (typeof data !== 'string') { - data = util.inspect(data); - } - options = options || {}; - assert(typeof options === 'object', ' => Options should be an object.'); - if (true || IS_SUMAN_DEBUG) { - fs.appendFileSync(testDebugLogPath, data); - } - }; - _suman._writeLog = function (data) { - if (IS_SUMAN_DEBUG) { - fs.appendFileSync(testDebugLogPath, data); - } - }; - } - else { - if (SUMAN_SINGLE_PROCESS) { - fs.writeFileSync(testLogPath, '\n => [SUMAN_SINGLE_PROCESS mode] Next Suman run @' + new Date() + - '\n Test file => "' + $module.filename + '"', { flag: 'a' }); - } - else { - fs.writeFileSync(testLogPath, '\n\n => Test file => "' + $module.filename + '"\n\n', { flag: 'a' }); - } - _suman._writeLog = function (data) { - fs.appendFileSync(testLogPath, data); - }; - _suman.writeTestError = function (data, ignore) { - if (!ignore) { - _suman.checkTestErrorLog = true; - } - if (data) { - if (typeof data !== 'string') { - data = util.inspect(data); - } - fs.appendFileSync(testDebugLogPath, '\n' + data + '\n'); - } - else { - _suman.logError('Suman implementation error => no data passed to writeTestError. Please report.'); - } - }; - fs.writeFileSync(testDebugLogPath, '\n\n', { flag: 'a', encoding: 'utf8' }); - _suman.writeTestError('\n\n', true); - _suman.writeTestError(' ### Suman start run @' + new Date(), true); - _suman.writeTestError(' ### Filename => ' + $module.filename, true); - _suman.writeTestError(' ### Command => ' + JSON.stringify(process.argv), true); - } -} -exports.default = default_1; diff --git a/lib/index-helpers/setup-extra-loggers.ts b/lib/index-helpers/setup-extra-loggers.ts deleted file mode 100755 index 7d143a5c..00000000 --- a/lib/index-helpers/setup-extra-loggers.ts +++ /dev/null @@ -1,105 +0,0 @@ -//typescript imports -import {IGlobalSumanObj} from "suman-types/dts/global"; -import {ISumanModuleExtended} from "suman-types/dts/index-init"; - -//polyfills -const process = require('suman-browser-polyfills/modules/process'); -const global = require('suman-browser-polyfills/modules/global'); - -//core -import assert = require('assert'); -import util = require('util'); -import fs = require('fs'); - -//project -let inBrowser = false; -const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); - -//env -const IS_SUMAN_DEBUG = process.env.SUMAN_DEBUG === 'yes'; -const SUMAN_SINGLE_PROCESS = process.env.SUMAN_SINGLE_PROCESS === 'yes'; - -///////////////////////////////////////////////////////////////////////////////////// - -let callable = true; - -export default function (usingRunner: boolean, testDebugLogPath: string, testLogPath: string, - $module: ISumanModuleExtended) { - - // SUMAN_SINGLE_PROCESS can call this routine multiple times - // whereas we return early if not in SSP mode - // this is ugly, but works for now - - if (usingRunner && callable) { - - callable = false; - - _suman.writeTestError = function (data: string, options: any) { - - // assert(typeof data === 'string', 'Implementation error => data passed to ' + - // 'writeTestError should already be in string format => \n' + util.inspect(data)); - - if(!data){ - data = new Error('falsy data passed to writeTestError').stack; - } - - if(typeof data !== 'string'){ - data = util.inspect(data); - } - - options = options || {}; - assert(typeof options === 'object', ' => Options should be an object.'); - - if (true || IS_SUMAN_DEBUG) { - fs.appendFileSync(testDebugLogPath, data); - } - }; - - _suman._writeLog = function (data: string) { - // use process.send to send data to runner? or no-op - if (IS_SUMAN_DEBUG) { - fs.appendFileSync(testDebugLogPath, data); - } - } - } - else { - - if (SUMAN_SINGLE_PROCESS) { - fs.writeFileSync(testLogPath, - '\n => [SUMAN_SINGLE_PROCESS mode] Next Suman run @' + new Date() + - '\n Test file => "' + $module.filename + '"', {flag: 'a'}); - } - else { - fs.writeFileSync(testLogPath, '\n\n => Test file => "' + $module.filename + '"\n\n', {flag: 'a'}); - } - - _suman._writeLog = function (data: string) { - fs.appendFileSync(testLogPath, data); - }; - - _suman.writeTestError = function (data: string, ignore: boolean) { - if (!ignore) { - _suman.checkTestErrorLog = true; - } - // strm.write.apply(strm, arguments); - if (data) { - if (typeof data !== 'string') { - data = util.inspect(data); - } - fs.appendFileSync(testDebugLogPath, '\n' + data + '\n'); - } - else { - _suman.logError('Suman implementation error => no data passed to writeTestError. Please report.'); - } - - }; - - fs.writeFileSync(testDebugLogPath, '\n\n', {flag: 'a', encoding: 'utf8'}); - _suman.writeTestError('\n\n', true); - _suman.writeTestError(' ### Suman start run @' + new Date(), true); - _suman.writeTestError(' ### Filename => ' + $module.filename, true); - _suman.writeTestError(' ### Command => ' + JSON.stringify(process.argv), true); - } -} - - diff --git a/lib/index-helpers/socketio-child-client.js b/lib/index-helpers/socketio-child-client.js index 45f57f88..d67f1996 100755 --- a/lib/index-helpers/socketio-child-client.js +++ b/lib/index-helpers/socketio-child-client.js @@ -4,17 +4,22 @@ var process = require('suman-browser-polyfills/modules/process'); var global = require('suman-browser-polyfills/modules/global'); var Client = require("socket.io-client"); var client = null; +var _suman = global.__suman = (global.__suman || {}); exports.getClient = function () { if (!client) { - client = Client("http://localhost:" + process.env.SUMAN_SOCKETIO_SERVER_PORT); + var port = process.env.SUMAN_SOCKETIO_SERVER_PORT; + if (!port) { + throw new Error('Suman implementation error, no port specified by "SUMAN_SOCKETIO_SERVER_PORT" env var.'); + } + client = Client("http://localhost:" + port); client.on('connect', function () { - console.log('client connected.'); + _suman.logWarning('client connected.'); }); client.on('event', function (data) { - console.log('event data => ', data); + _suman.log('event data => ', data); }); client.on('disconnect', function () { - console.log('client disconnected.'); + _suman.logError('client disconnected.'); }); } return client; diff --git a/lib/index-helpers/socketio-child-client.ts b/lib/index-helpers/socketio-child-client.ts index a56b00ac..1beeae17 100755 --- a/lib/index-helpers/socketio-child-client.ts +++ b/lib/index-helpers/socketio-child-client.ts @@ -1,15 +1,19 @@ 'use strict'; +//dts +import {IGlobalSumanObj} from 'suman-types/dts/global'; + //polyfills const process = require('suman-browser-polyfills/modules/process'); const global = require('suman-browser-polyfills/modules/global'); //npm import * as Client from 'socket.io-client'; - +import su = require('suman-utils'); //project -let client : SocketIOClient.Socket = null; +let client: SocketIOClient.Socket = null; +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); //////////////////////////////////////////////////////////////// @@ -17,15 +21,24 @@ export const getClient = function () { if (!client) { - client = Client(`http://localhost:${process.env.SUMAN_SOCKETIO_SERVER_PORT}`); + const port = process.env.SUMAN_SOCKETIO_SERVER_PORT; + + if (!port) { + throw new Error('Suman implementation error, no port specified by "SUMAN_SOCKETIO_SERVER_PORT" env var.'); + } + + client = Client(`http://localhost:${port}`); + client.on('connect', function () { - console.log('client connected.'); + _suman.logWarning('client connected.'); }); + client.on('event', function (data: string) { - console.log('event data => ', data); + _suman.log('event data => ', data); }); + client.on('disconnect', function () { - console.log('client disconnected.'); + _suman.logError('client disconnected.'); }); } diff --git a/lib/index.js b/lib/index.js index a60e15f5..02e0d661 100755 --- a/lib/index.js +++ b/lib/index.js @@ -49,7 +49,6 @@ var sumanRuntimeErrors = _suman.sumanRuntimeErrors = _suman.sumanRuntimeErrors | var fatalRequestReply = require('./helpers/fatal-request-reply').fatalRequestReply; var constants = require('../config/suman-constants').constants; var handle_integrants_1 = require("./index-helpers/handle-integrants"); -var setup_extra_loggers_1 = require("./index-helpers/setup-extra-loggers"); var rules = require('./helpers/handle-varargs'); var suman_1 = require("./suman"); var execSuite = require('./exec-suite').execSuite; @@ -59,14 +58,14 @@ var load_shared_objects_1 = require("./helpers/load-shared-objects"); var acquire_ioc_static_deps_1 = require("./acquire-dependencies/acquire-ioc-static-deps"); var allOncePreKeys = _suman.oncePreKeys = []; var allOncePostKeys = _suman.oncePostKeys = []; -var suiteResultEmitter = _suman.suiteResultEmitter = (_suman.suiteResultEmitter || new EE()); +var suiteResultEmitter = _suman.suiteResultEmitter = _suman.suiteResultEmitter || new EE(); if (!SUMAN_SINGLE_PROCESS) { require('./helpers/handle-suman-counts'); } require('./index-helpers/verify-local-global-version'); var projectRoot = _suman.projectRoot = _suman.projectRoot || su.findProjectRoot(process.cwd()) || '/'; var main = require.main.filename; -var usingRunner = _suman.usingRunner = (_suman.usingRunner || process.env.SUMAN_RUNNER === 'yes'); +var usingRunner = _suman.usingRunner = _suman.usingRunner || process.env.SUMAN_RUNNER === 'yes'; var sumanConfig = load_suman_config_1.loadSumanConfig(null, null); if (!_suman.usingRunner && !_suman.viaSuman) { require('./helpers/print-version-info'); @@ -75,16 +74,13 @@ var sumanPaths = resolve_shared_dirs_1.resolveSharedDirs(sumanConfig, projectRoo var sumanObj = load_shared_objects_1.loadSharedObjects(sumanPaths, projectRoot, sumanOpts); var integrantPreFn = sumanObj.integrantPreFn; var testDebugLogPath = sumanPaths.testDebugLogPath; -var testLogPath = sumanPaths.testLogPath; -fs.writeFileSync(testDebugLogPath, '\n', { flag: 'w' }); -fs.writeFileSync(testLogPath, '\n => New Suman run @' + new Date(), { flag: 'w' }); +fs.writeFileSync(testDebugLogPath, '\n'); var loaded = false; var testSuiteQueueCallbacks = []; var testRuns = []; var testSuiteRegistrationQueueCallbacks = []; var c = (sumanOpts && sumanOpts.series) ? 1 : 3; var testSuiteQueue = async.queue(function (task, cb) { - debugger; testSuiteQueueCallbacks.unshift(cb); process.nextTick(task); }, c); @@ -93,7 +89,10 @@ var testSuiteRegistrationQueue = async.queue(function (task, cb) { process.nextTick(task); }, c); testSuiteRegistrationQueue.drain = function () { - _suman.log("Pushing " + testRuns.length + " test suites onto queue with concurrency " + c + ".\n"); + if (su.vgt(5)) { + var suites = testRuns.length === 1 ? 'suite' : 'suites'; + _suman.log("Pushing " + testRuns.length + " test " + suites + " onto queue with concurrency " + c + ".\n\n"); + } while (testRuns.length > 0) { testSuiteQueue.push(testRuns.shift()); } @@ -114,6 +113,20 @@ suiteResultEmitter.on('suman-completed', function () { fn && fn.call(null); }); }); +_suman.writeTestError = function (data, ignore) { + if (IS_SUMAN_DEBUG && !_suman.usingRunner) { + if (!ignore) + _suman.checkTestErrorLog = true; + if (!data) + data = new Error('falsy data passed to writeTestError').stack; + if (typeof data !== 'string') + data = util.inspect(data); + fs.appendFileSync(testDebugLogPath, data); + } +}; +fs.appendFileSync(testDebugLogPath, '\n\n', { encoding: 'utf8' }); +_suman.writeTestError('\n ### Suman start run @' + new Date() + ' ###\n', true); +_suman.writeTestError('\nCommand => ' + util.inspect(process.argv), true); exports.init = function ($module, $opts, confOverride) { debugger; if (exports.init.$ingletonian) { @@ -190,7 +203,6 @@ exports.init = function ($module, $opts, confOverride) { process.exit(constants.EXIT_CODES.IOC_PASSED_TO_SUMAN_INIT_BAD_FORM); } } - setup_extra_loggers_1.default(usingRunner, testDebugLogPath, testLogPath, $module); var integrantsFn = handle_integrants_1.handleIntegrants(integrants, $oncePost, integrantPreFn, $module); exports.init.tooLate = false; var start = function () { @@ -212,7 +224,7 @@ exports.init = function ($module, $opts, confOverride) { clearTimeout(to); _suman['$pre'] = JSON.parse(su.customStringify(vals)); _suman.userData = JSON.parse(su.customStringify(iocData)); - var suman = suman_1.makeSuman($module, _interface, true, sumanConfig); + var suman = suman_1.makeSuman($module, _interface, opts); suman.iocData = JSON.parse(su.customStringify(iocData)); var run = execSuite(suman); try { @@ -273,6 +285,7 @@ exports.init = function ($module, $opts, confOverride) { var create = exports.init.$ingletonian.create = start; _interface === 'TDD' ? exports.init.$ingletonian.suite = create : exports.init.$ingletonian.describe = create; loaded = true; + exports.init.$ingletonian.Test = exports.init.$ingletonian; return exports.init.$ingletonian; }; exports.autoPass = function (t) { diff --git a/lib/index.ts b/lib/index.ts index c232fe91..a70053ed 100755 --- a/lib/index.ts +++ b/lib/index.ts @@ -94,7 +94,6 @@ const sumanRuntimeErrors = _suman.sumanRuntimeErrors = _suman.sumanRuntimeErrors const {fatalRequestReply} = require('./helpers/fatal-request-reply'); const {constants} = require('../config/suman-constants'); import {handleIntegrants} from './index-helpers/handle-integrants'; -import setupExtraLoggers from './index-helpers/setup-extra-loggers'; const rules = require('./helpers/handle-varargs'); import {makeSuman} from './suman'; const {execSuite} = require('./exec-suite'); @@ -108,7 +107,7 @@ import {acquireIocStaticDeps} from './acquire-dependencies/acquire-ioc-static-de //integrants const allOncePreKeys: Array> = _suman.oncePreKeys = []; const allOncePostKeys: Array> = _suman.oncePostKeys = []; -const suiteResultEmitter = _suman.suiteResultEmitter = (_suman.suiteResultEmitter || new EE()); +const suiteResultEmitter = _suman.suiteResultEmitter = _suman.suiteResultEmitter || new EE(); //////////////////////////////////////////////////////////////////////////////////////////// @@ -119,7 +118,7 @@ if (!SUMAN_SINGLE_PROCESS) { require('./index-helpers/verify-local-global-version'); const projectRoot = _suman.projectRoot = _suman.projectRoot || su.findProjectRoot(process.cwd()) || '/'; const main = require.main.filename; -const usingRunner = _suman.usingRunner = (_suman.usingRunner || process.env.SUMAN_RUNNER === 'yes'); +const usingRunner = _suman.usingRunner = _suman.usingRunner || process.env.SUMAN_RUNNER === 'yes'; //could potentially pass dynamic path to suman config here, but for now is static const sumanConfig = loadSumanConfig(null, null); if (!_suman.usingRunner && !_suman.viaSuman) { @@ -129,9 +128,7 @@ const sumanPaths = resolveSharedDirs(sumanConfig, projectRoot, sumanOpts); const sumanObj = loadSharedObjects(sumanPaths, projectRoot, sumanOpts); const {integrantPreFn} = sumanObj; const testDebugLogPath = sumanPaths.testDebugLogPath; -const testLogPath = sumanPaths.testLogPath; -fs.writeFileSync(testDebugLogPath, '\n', {flag: 'w'}); -fs.writeFileSync(testLogPath, '\n => New Suman run @' + new Date(), {flag: 'w'}); +fs.writeFileSync(testDebugLogPath, '\n'); //////////////////////////////////////////////////////////////////////////////// @@ -139,11 +136,9 @@ let loaded = false; const testSuiteQueueCallbacks: Array = []; const testRuns: Array = []; const testSuiteRegistrationQueueCallbacks: Array = []; - const c = (sumanOpts && sumanOpts.series) ? 1 : 3; const testSuiteQueue = async.queue(function (task: Function, cb: Function) { - debugger; testSuiteQueueCallbacks.unshift(cb); process.nextTick(task); }, c); @@ -155,7 +150,11 @@ const testSuiteRegistrationQueue = async.queue(function (task: Function, cb: Fun }, c); testSuiteRegistrationQueue.drain = function () { - _suman.log(`Pushing ${testRuns.length} test suites onto queue with concurrency ${c}.\n`); + if (su.vgt(5)) { + const suites = testRuns.length === 1 ? 'suite' : 'suites'; + _suman.log(`Pushing ${testRuns.length} test ${suites} onto queue with concurrency ${c}.\n\n`); + } + while (testRuns.length > 0) { //explicit for your pleasure testSuiteQueue.push(testRuns.shift()); } @@ -181,6 +180,19 @@ suiteResultEmitter.on('suman-completed', function () { }); }); +_suman.writeTestError = function (data: string, ignore: boolean) { + if (IS_SUMAN_DEBUG && !_suman.usingRunner) { + if (!ignore) _suman.checkTestErrorLog = true; + if (!data) data = new Error('falsy data passed to writeTestError').stack; + if (typeof data !== 'string') data = util.inspect(data); + fs.appendFileSync(testDebugLogPath, data); + } +}; + +fs.appendFileSync(testDebugLogPath, '\n\n', {encoding: 'utf8'}); +_suman.writeTestError('\n ### Suman start run @' + new Date() + ' ###\n', true); +_suman.writeTestError('\nCommand => ' + util.inspect(process.argv), true); + export const init: IInit = function ($module, $opts, confOverride): IStartCreate { ////////////////////////////////////////////////////// @@ -298,7 +310,6 @@ export const init: IInit = function ($module, $opts, confOverride): IStartCreate ////////////////////////////////////////////////////////////////// - setupExtraLoggers(usingRunner, testDebugLogPath, testLogPath, $module); const integrantsFn = handleIntegrants(integrants, $oncePost, integrantPreFn, $module); init.tooLate = false; @@ -329,7 +340,7 @@ export const init: IInit = function ($module, $opts, confOverride): IStartCreate _suman.userData = JSON.parse(su.customStringify(iocData)); // suman instance is the main object that flows through entire program - let suman = makeSuman($module, _interface, true, sumanConfig); + let suman = makeSuman($module, _interface, opts); suman.iocData = JSON.parse(su.customStringify(iocData)); const run = execSuite(suman); @@ -402,6 +413,8 @@ export const init: IInit = function ($module, $opts, confOverride): IStartCreate _interface === 'TDD' ? init.$ingletonian.suite = create : init.$ingletonian.describe = create; loaded = true; + + init.$ingletonian.Test = init.$ingletonian; return init.$ingletonian; }; diff --git a/lib/injection/injection-container.js b/lib/injection/injection-container.js index d2fa853f..c083a1e7 100755 --- a/lib/injection/injection-container.js +++ b/lib/injection/injection-container.js @@ -31,21 +31,18 @@ exports.makeInjectionContainer = function (suman) { var getProxy = function (val, props) { return new Proxy(val, { get: function (target, prop) { - debugger; if (typeof prop === 'symbol') { return Reflect.get.apply(Reflect, arguments); } var meth = String(prop).toLowerCase(); if (!possibleProps[meth]) { try { - debugger; return Reflect.get.apply(Reflect, arguments); } catch (err) { throw new Error("Test suite may not have a '" + prop + "' property or method.\n" + err.stack); } } - debugger; var hasSkip = false; var newProps = props.concat(String(prop)) .map(function (v) { return String(v).toLowerCase(); }) diff --git a/lib/injection/injection-container.ts b/lib/injection/injection-container.ts index e594536a..e4b26add 100755 --- a/lib/injection/injection-container.ts +++ b/lib/injection/injection-container.ts @@ -62,8 +62,6 @@ export const makeInjectionContainer = function (suman: ISuman) { return new Proxy(val, { get: function (target, prop) { - debugger; - if (typeof prop === 'symbol') { return Reflect.get(...arguments); } @@ -72,7 +70,6 @@ export const makeInjectionContainer = function (suman: ISuman) { if (!possibleProps[meth] /*&& !(prop in target)*/) { try { - debugger; return Reflect.get(...arguments); } catch (err) { @@ -80,8 +77,6 @@ export const makeInjectionContainer = function (suman: ISuman) { } } - debugger; - let hasSkip = false; let newProps = props.concat(String(prop)) .map(v => String(v).toLowerCase()) // we map to lowercase first, so we can use indexOf afterwards @@ -139,7 +134,6 @@ export const makeInjectionContainer = function (suman: ISuman) { } return meth().apply(suman.ctx, args); - }; return suman.testBlockMethodCache[cacheId] = getProxy(fn, newProps); diff --git a/lib/parse-cmd-line-opts/suman-options.js b/lib/parse-cmd-line-opts/suman-options.js index b9b28e6e..585ff7e3 100755 --- a/lib/parse-cmd-line-opts/suman-options.js +++ b/lib/parse-cmd-line-opts/suman-options.js @@ -450,6 +450,11 @@ module.exports = [ type: 'bool', help: 'Run multiple test scripts in the same node.js process.' }, + { + names: ['script'], + type: 'string', + help: 'Run scripts by key given by the "scripts" object in `suman.conf.js`.' + }, { names: ['dest'], type: 'string', diff --git a/lib/parse-cmd-line-opts/suman-options.ts b/lib/parse-cmd-line-opts/suman-options.ts index 48d54463..1c6e2b30 100755 --- a/lib/parse-cmd-line-opts/suman-options.ts +++ b/lib/parse-cmd-line-opts/suman-options.ts @@ -451,6 +451,11 @@ module.exports = [ type: 'bool', help: 'Run multiple test scripts in the same node.js process.' }, + { + names: ['script'], + type: 'string', + help: 'Run scripts by key given by the "scripts" object in `suman.conf.js`.' + }, { names: ['dest'], type: 'string', diff --git a/lib/run-child-not-runner.js b/lib/run-child-not-runner.js index ce64ff33..115d12f1 100755 --- a/lib/run-child-not-runner.js +++ b/lib/run-child-not-runner.js @@ -4,9 +4,8 @@ var process = require('suman-browser-polyfills/modules/process'); var global = require('suman-browser-polyfills/modules/global'); var path = require('path'); var util = require("util"); +var su = require("suman-utils"); var chalk = require("chalk"); -var sumanUtils = require('suman-utils'); -var debug = require('suman-debug')('s'); var _suman = global.__suman = (global.__suman || {}); var constants = require('../config/suman-constants').constants; var SUMAN_SINGLE_PROCESS = process.env.SUMAN_SINGLE_PROCESS === 'yes'; @@ -51,18 +50,25 @@ exports.run = function (files) { if (!process.prependListener) { process.prependListener = process.on.bind(process); } - process.prependListener('exit', function (code) { + if (!process.prependOnceListener) { + process.prependOnceListener = process.on.bind(process); + } + process.prependOnceListener('exit', function (code) { if (!_suman.isActualExitHandlerRegistered) { _suman.logError(chalk.magenta('Warning, you may have failed to point Suman to an actual Suman test file.')); _suman.logError(chalk.magenta('Or there was an immediate error, which prevented any other exit handlers from being registered.')); } }); if (SUMAN_SINGLE_PROCESS) { - _suman.log('we are in SUMAN_SINGLE_PROCESS mode.'); + if (su.vgt(5)) { + _suman.log('We are in "SUMAN_SINGLE_PROCESS" mode: all JavaScript-based tests will be run in a single process.'); + } require('./handle-single-proc').run(files); } else { - _suman.log("running this single test file => \"" + files[0] + "\""); + if (su.vgt(5)) { + _suman.log("running this single test file => \"" + chalk.bold(files[0]) + "\""); + } require('./helpers/log-stdio-of-child').run(files[0]); require(files[0]); } diff --git a/lib/run-child-not-runner.ts b/lib/run-child-not-runner.ts index dd2e4711..68123417 100755 --- a/lib/run-child-not-runner.ts +++ b/lib/run-child-not-runner.ts @@ -10,11 +10,9 @@ const path = require('path'); import util = require('util'); //npm +import su = require('suman-utils'); import chalk = require('chalk'); -const sumanUtils = require('suman-utils'); -const debug = require('suman-debug')('s'); - //project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); const {constants} = require('../config/suman-constants'); @@ -81,7 +79,11 @@ export const run = function (files: Array) { process.prependListener = process.on.bind(process); } - process.prependListener('exit', function (code: number) { + if (!process.prependOnceListener) { + process.prependOnceListener = process.on.bind(process); + } + + process.prependOnceListener('exit', function (code: number) { if (!_suman.isActualExitHandlerRegistered) { _suman.logError(chalk.magenta('Warning, you may have failed to point Suman to an actual Suman test file.'); _suman.logError(chalk.magenta('Or there was an immediate error, which prevented any other exit handlers from being registered.')); @@ -89,11 +91,17 @@ export const run = function (files: Array) { }); if (SUMAN_SINGLE_PROCESS) { - _suman.log('we are in SUMAN_SINGLE_PROCESS mode.'); + if (su.vgt(5)) { + _suman.log('We are in "SUMAN_SINGLE_PROCESS" mode: all JavaScript-based tests will be run in a single process.'); + } + require('./handle-single-proc').run(files); } else { - _suman.log(`running this single test file => "${files[0]}"`); + if (su.vgt(5)) { + _suman.log(`running this single test file => "${chalk.bold(files[0])}"`); + } + require('./helpers/log-stdio-of-child').run(files[0]); require(files[0]); } diff --git a/lib/run.js b/lib/run.js index d6cbf58b..f14852f5 100755 --- a/lib/run.js +++ b/lib/run.js @@ -9,7 +9,7 @@ var EE = require("events"); var async = require("async"); var shuffle = require('lodash.shuffle'); var chalk = require("chalk"); -var suman_utils_1 = require("suman-utils"); +var su = require("suman-utils"); var rimraf = require('rimraf'); var events = require('suman-events').events; var debug = require('suman-debug')('s:cli'); @@ -22,7 +22,7 @@ var ascii = require('./helpers/ascii'); var constants = require('../config/suman-constants').constants; var findFilesToRun = require('./runner-helpers/get-file-paths').findFilesToRun; var resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); -var dbPth = path.resolve(process.env.HOME + '/.suman/database/exec_db'); +var dbPth = path.resolve(sumanHome + '/database/exec_db'); exports.run = function (sumanOpts, paths) { var logsDir = _suman.sumanConfig.logsDir || _suman.sumanHelperDirRoot + '/logs'; var sumanCPLogs = path.resolve(logsDir + '/runs'); @@ -126,7 +126,7 @@ exports.run = function (sumanOpts, paths) { findFilesToRun(paths, cb); }, findSumanMarkers: function (getFilesToRun, cb) { - suman_utils_1.default.findSumanMarkers(['@run.sh', '@transform.sh', '@config.json'], testDir, getFilesToRun.files, function (err, map) { + su.findSumanMarkers(['@run.sh', '@transform.sh', '@config.json'], testDir, getFilesToRun.files, function (err, map) { if (err) { cb(err); } @@ -145,7 +145,7 @@ exports.run = function (sumanOpts, paths) { } }, getRunId: function (cb) { - var first = suman_utils_1.default.once(this, cb); + var first = su.once(this, cb); function createDir(runId) { var p = path.resolve(sumanCPLogs + '/' + timestamp + '-' + runId); mkdirp(p, 511, first); @@ -190,7 +190,7 @@ exports.run = function (sumanOpts, paths) { _suman.logError('fatal problem => ' + (err.stack || err), '\n'); return process.exit(1); } - if (suman_utils_1.default.vgt(9)) { + if (su.vgt(9)) { _suman.log('"$ npm list -g" results: ', results.npmList); } function changeCWDToRootOrTestDir(p) { @@ -214,7 +214,7 @@ exports.run = function (sumanOpts, paths) { process.exit(constants.RUNNER_EXIT_CODES.UNEXPECTED_FATAL_ERROR); }); resultBroadcaster.emit(String(events.RUNNER_TEST_PATHS_CONFIRMATION), files); - if (suman_utils_1.default.vgt(6) || sumanOpts.dry_run) { + if (su.vgt(6) || sumanOpts.dry_run) { console.log(' ', chalk.bgCyan.magenta(' => Suman verbose message => ' + 'Suman will execute test files from the following locations:'), '\n', files, '\n'); } @@ -230,11 +230,11 @@ exports.run = function (sumanOpts, paths) { files = shuffle(files); } _suman.sumanSingleProcessStartTime = Date.now(); - require('./run-child-not-runner').run(suman_utils_1.default.removeSharedRootPath(files)); + require('./run-child-not-runner').run(su.removeSharedRootPath(files)); }); } else if (!sumanOpts.runner && !sumanOpts.containerize - && !sumanOpts.coverage && files.length === 1 && suman_utils_1.default.checkStatsIsFile(files[0]) && !nonJSFile) { + && !sumanOpts.coverage && files.length === 1 && su.checkStatsIsFile(files[0]) && !nonJSFile) { console.log(ascii.suman_slant, '\n'); d.run(function () { changeCWDToRootOrTestDir(files[0]); diff --git a/lib/run.ts b/lib/run.ts index dbd3662c..965b7384 100755 --- a/lib/run.ts +++ b/lib/run.ts @@ -1,6 +1,6 @@ 'use strict'; -//ts +//dts import {IGlobalSumanObj, ISumanOpts} from "suman-types/dts/global"; //polyfills @@ -21,7 +21,7 @@ import cp = require('child_process'); import * as async from 'async'; const shuffle = require('lodash.shuffle'); import * as chalk from 'chalk'; -import su, {IMapValue} from 'suman-utils'; +import * as su from 'suman-utils'; import {IGetFilePathObj} from "./runner-helpers/get-file-paths"; const rimraf = require('rimraf'); const {events} = require('suman-events'); @@ -36,10 +36,9 @@ const noFilesFoundError = require('./helpers/no-files-found-error'); const ascii = require('./helpers/ascii'); const {constants} = require('../config/suman-constants'); import {findSumanServer} from './helpers/find-suman-server'; - const {findFilesToRun} = require('./runner-helpers/get-file-paths'); const resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); -const dbPth = path.resolve(process.env.HOME + '/.suman/database/exec_db'); +const dbPth = path.resolve(sumanHome + '/database/exec_db'); ////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/lib/runner-helpers/create-suman-runner.js b/lib/runner-helpers/create-suman-runner.js index 7c30a82c..f371c6b6 100755 --- a/lib/runner-helpers/create-suman-runner.js +++ b/lib/runner-helpers/create-suman-runner.js @@ -4,20 +4,22 @@ var process = require('suman-browser-polyfills/modules/process'); var global = require('suman-browser-polyfills/modules/global'); var fs = require("fs"); var path = require("path"); +var util = require("util"); var assert = require("assert"); var chalk = require("chalk"); var su = require("suman-utils"); var _suman = global.__suman = (global.__suman || {}); var cwd = process.cwd(); var socketio_server_1 = require("./socketio-server"); +var runnerDebugLogPath = _suman.sumanRunnerStderrStreamPath = + path.resolve(_suman.sumanHelperDirRoot + '/logs/runner-debug.log'); exports.createRunner = function (obj) { var runObj = obj.runObj; - var strmPath = _suman.sumanRunnerStderrStreamPath = path.resolve(_suman.sumanHelperDirRoot + '/logs/runner-debug.log'); - var strm = _suman.sumanStderrStream = fs.createWriteStream(strmPath); + var strm = _suman.sumanStderrStream = fs.createWriteStream(runnerDebugLogPath); strm.write('\n\n### Suman runner start ###\n\n'); strm.write('Beginning of run at ' + Date.now() + ' = [' + new Date() + ']' + '\n'); - strm.write('Command issued from the following directory "' + cwd + '"\n'); - strm.write('Command = ' + JSON.stringify(process.argv) + '\n'); + strm.write('Suman command issued from the following directory "' + cwd + '"\n'); + strm.write('Suman "process.argv" => \n' + util.inspect(process.argv) + '\n'); var oncePath = path.resolve(_suman.sumanHelperDirRoot + '/suman.once.pre.js'); var runOnce; try { diff --git a/lib/runner-helpers/create-suman-runner.ts b/lib/runner-helpers/create-suman-runner.ts index 47f19055..9770edb4 100755 --- a/lib/runner-helpers/create-suman-runner.ts +++ b/lib/runner-helpers/create-suman-runner.ts @@ -23,19 +23,20 @@ import su = require('suman-utils'); const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); const cwd = process.cwd(); import {initializeSocketServer} from './socketio-server'; +const runnerDebugLogPath = _suman.sumanRunnerStderrStreamPath = + path.resolve(_suman.sumanHelperDirRoot + '/logs/runner-debug.log'); //////////////////////////////////////////////////////////////////////////// export const createRunner = function (obj: Object) { const runObj = obj.runObj; - const strmPath = _suman.sumanRunnerStderrStreamPath = path.resolve(_suman.sumanHelperDirRoot + '/logs/runner-debug.log'); - const strm = _suman.sumanStderrStream = fs.createWriteStream(strmPath); + const strm = _suman.sumanStderrStream = fs.createWriteStream(runnerDebugLogPath); strm.write('\n\n### Suman runner start ###\n\n'); strm.write('Beginning of run at ' + Date.now() + ' = [' + new Date() + ']' + '\n'); - strm.write('Command issued from the following directory "' + cwd + '"\n'); - strm.write('Command = ' + JSON.stringify(process.argv) + '\n'); + strm.write('Suman command issued from the following directory "' + cwd + '"\n'); + strm.write('Suman "process.argv" => \n' + util.inspect(process.argv) + '\n'); /////////////// validate suman.once.js ////////////////////////////////////////////////////////// diff --git a/lib/runner-helpers/handle-fatal-message.js b/lib/runner-helpers/handle-fatal-message.js index 97c1dc90..5cac2e36 100755 --- a/lib/runner-helpers/handle-fatal-message.js +++ b/lib/runner-helpers/handle-fatal-message.js @@ -11,17 +11,21 @@ var _suman = global.__suman = (global.__suman || {}); var resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); exports.handleFatalMessage = function ($msg, n, socket) { var msg = String(typeof $msg.error === 'string' ? $msg.error : util.inspect($msg)).replace(/\n/g, '\n').replace('\t', ''); - msg = msg.split('\n').map(function (item, index) { + msg = msg.split('\n') + .concat(su.repeatCharXTimes('_', 115)) + .map(function (item, index) { if (index === 0) { return item; } else { - return su.padWithXSpaces(8) + item; + return su.padWithXSpaces(3) + item; } - }).join('\n'); + }) + .join('\n'); + var padding = su.padWithXSpaces(2); var message = [ '\n', - chalk.bgWhite.magenta.bold(' => Suman runner => there was a fatal test suite error - an error was encountered in ' + + chalk.bgWhite.magenta.bold(' There was a fatal test suite error - an error was encountered in ' + 'your test code that prevents Suman '), chalk.bgWhite.magenta.bold(' from continuing with a particular test suite within the following path: '), ' ', @@ -34,9 +38,8 @@ exports.handleFatalMessage = function ($msg, n, socket) { } return null; })(), - ' ', chalk.magenta.bold(msg), '\n\n' - ].filter(function (item) { return item; }).join('\n\t'); + ].filter(function (item) { return item; }).join('\n' + padding); resultBroadcaster.emit(String(events.FATAL_TEST_ERROR), message); }; diff --git a/lib/runner-helpers/handle-fatal-message.ts b/lib/runner-helpers/handle-fatal-message.ts index daf72123..5d2eeafb 100755 --- a/lib/runner-helpers/handle-fatal-message.ts +++ b/lib/runner-helpers/handle-fatal-message.ts @@ -29,19 +29,23 @@ export const handleFatalMessage = function ($msg: Object, n: ISumanChildProcess let msg = String(typeof $msg.error === 'string' ? $msg.error : util.inspect($msg)).replace(/\n/g, '\n').replace('\t', ''); - msg = msg.split('\n').map(function (item, index) { + msg = msg.split('\n') + .concat(su.repeatCharXTimes('_',115)) + .map(function (item, index) { if (index === 0) { return item; } else { - return su.padWithXSpaces(8) + item; + return su.padWithXSpaces(3) + item; } + }) + .join('\n'); - }).join('\n'); + const padding = su.padWithXSpaces(2); const message = [ '\n', - chalk.bgWhite.magenta.bold(' => Suman runner => there was a fatal test suite error - an error was encountered in ' + + chalk.bgWhite.magenta.bold(' There was a fatal test suite error - an error was encountered in ' + 'your test code that prevents Suman '), chalk.bgWhite.magenta.bold(' from continuing with a particular test suite within the following path: '), ' ', @@ -54,11 +58,10 @@ export const handleFatalMessage = function ($msg: Object, n: ISumanChildProcess } return null; })(), - ' ', //chalk.bgBlack.white(' '), chalk.magenta.bold(msg), // chalk.magenta.bold(String(msg.error ? msg.error : JSON.stringify(msg)).replace(/\n/g, '\n\t')), '\n\n' - ].filter(item => item).join('\n\t'); //filter out null/undefined + ].filter(item => item).join('\n' + padding); //filter out null/undefined resultBroadcaster.emit(String(events.FATAL_TEST_ERROR), message); diff --git a/lib/runner-helpers/handle-multiple-processes.js b/lib/runner-helpers/handle-multiple-processes.js index 444d5754..6afe5831 100755 --- a/lib/runner-helpers/handle-multiple-processes.js +++ b/lib/runner-helpers/handle-multiple-processes.js @@ -11,18 +11,18 @@ var semver = require("semver"); var merge = require('lodash.merge'); var shuffle = require('lodash.shuffle'); var suman_events_1 = require("suman-events"); -var suman_utils_1 = require("suman-utils"); +var su = require("suman-utils"); var async = require("async"); var noFilesFoundError = require('../helpers/no-files-found-error'); var chalk = require("chalk"); var _suman = global.__suman = (global.__suman || {}); +var resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); var runnerUtils = require('./runner-utils'); var socket_cp_hash_1 = require("./socket-cp-hash"); var getTapParser = require('./handle-tap').getTapParser; var getTapJSONParser = require('./handle-tap-json').getTapJSONParser; var constants = require('../../config/suman-constants').constants; var debug = require('suman-debug')('s:runner'); -var resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); var multiple_process_each_on_exit_1 = require("./multiple-process-each-on-exit"); var prepend_transform_1 = require("prepend-transform"); var runChildPath = require.resolve(__dirname + '/run-child.js'); @@ -83,7 +83,7 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, files = shuffle(files); } runnerObj.startTime = Date.now(); - var fileObjArray = suman_utils_1.default.removeSharedRootPath(files); + var fileObjArray = su.removeSharedRootPath(files); var sumanEnv = Object.assign({}, process.env, { SUMAN_RUN_CHILD_STATIC_PATH: runChildPath, SUMAN_CONFIG: JSON.stringify(sumanConfig), @@ -101,6 +101,7 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, var istanbulExecPath = _suman.istanbulExecPath || 'istanbul'; var isStdoutSilent = sumanOpts.stdout_silent || sumanOpts.silent; var isStderrSilent = sumanOpts.stderr_silent || sumanOpts.silent; + var inheritTransformStdio = sumanOpts.inherit_all_stdio || sumanOpts.inherit_transform_stdio || process.env.SUMAN_INHERIT_STDIO; fileObjArray.forEach(function (fileShortAndFull) { var uuid = String(uuidV4()); var file = fileShortAndFull[0]; @@ -134,7 +135,7 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, if (tr) { _suman.log(chalk.bgWhite.underline('Suman has found a @transform.sh file => '), chalk.bold(tr)); transpileQueue.push(function (cb) { - suman_utils_1.default.makePathExecutable(tr, function (err) { + su.makePathExecutable(tr, function (err) { if (err) { return cb(err); } @@ -152,18 +153,18 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, var ln = String(_suman.projectRoot).length; if (false) { var onError = function (e) { - _suman.logError('\n', suman_utils_1.default.getCleanErrorString(e), '\n'); + _suman.logError('\n', su.getCleanErrorString(e), '\n'); }; - var temp = suman_utils_1.default.removePath(file, _suman.projectRoot); + var temp = su.removePath(file, _suman.projectRoot); var onlyFile = String(temp).replace(/\//g, '.'); var logfile = path.resolve(f + '/' + onlyFile + '.log'); var fileStrm = fs.createWriteStream(logfile); k.stderr.pipe(fileStrm).once('error', onError); k.stdout.pipe(fileStrm).once('error', onError); } - if (sumanOpts.inherit_all_stdio || sumanOpts.inherit_transform_stdio || process.env.SUMAN_INHERIT_STDIO) { + if (inheritTransformStdio) { var onError = function (e) { - _suman.logError('\n', suman_utils_1.default.getCleanErrorString(e), '\n'); + _suman.logError('\n', su.getCleanErrorString(e), '\n'); }; var stderrPrepend = " [" + chalk.red('transform process stderr:') + " " + chalk.red.bold(String(file.slice(ln))) + "] "; k.stderr.pipe(prepend_transform_1.default(stderrPrepend, { omitWhitespace: true })).once('error', onError).pipe(process.stderr); @@ -201,6 +202,9 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, } }); var childId = 1; + var debugChildren = sumanOpts.debug_child || sumanOpts.inspect_child; + var inheritRunStdio = debugChildren || sumanOpts.inherit_stdio || + sumanOpts.inherit_all_stdio || process.env.SUMAN_INHERIT_STDIO === 'yes'; var outer = function (file, shortFile, stdout, gd) { var run = function () { if (runnerObj.bailed) { @@ -213,15 +217,15 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, var argz = JSON.parse(JSON.stringify(args)); var execArgz = ['--expose-gc']; if (sumanOpts.debug_child) { - execArgz.push('--debug-brk'); execArgz.push('--debug=' + (5303 + runnerObj.processId++)); + execArgz.push('--debug-brk'); } if (sumanOpts.inspect_child) { if (semver.gt(process.version, '7.8.0')) { - execArgz.push('--inspect-brk'); + execArgz.push('--inspect-brk=' + (5303 + runnerObj.processId++)); } else { - execArgz.push('--inspect'); + execArgz.push('--inspect=' + (5303 + runnerObj.processId++)); execArgz.push('--debug-brk'); } } @@ -259,7 +263,6 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, 'ignore', inherit || (isStdoutSilent ? 'ignore' : 'pipe'), inherit || (isStderrSilent ? 'ignore' : 'pipe'), - 'ipc' ], env: Object.assign({}, sumanEnv, { SUMAN_CHILD_TEST_PATH: file, @@ -305,12 +308,12 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, socket_cp_hash_1.cpHash[$childId] = n; if (!_suman.weAreDebugging) { n.to = setTimeout(function () { - console.error(' => Suman killed child process because it timed out => \n', (n.fileName || n.filename)); + _suman.logError("Suman killed a child process because it timed out: '" + (n.fileName || n.filename) + "'."); n.kill('SIGINT'); setTimeout(function () { n.kill('SIGKILL'); - }, 18000); - }, 6000000); + }, 8000); + }, constants.DEFAULT_CHILD_PROCESS_TIMEOUT); } n.testPath = file; n.shortTestPath = shortFile; @@ -335,14 +338,15 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, } n.stdout.setEncoding('utf8'); n.stderr.setEncoding('utf8'); - if (sumanOpts.log_stdio_to_files || sumanOpts.log_stdout_to_files || sumanOpts.log_stderr_to_files) { + if (false && (sumanOpts.log_stdio_to_files || sumanOpts.log_stdout_to_files || sumanOpts.log_stderr_to_files)) { var onError = function (e) { - _suman.logError('\n', suman_utils_1.default.getCleanErrorString(e), '\n'); + _suman.logError('\n', su.getCleanErrorString(e), '\n'); }; - var temp = suman_utils_1.default.removePath(file, _suman.projectRoot); + var temp = su.removePath(file, _suman.projectRoot); var onlyFile = String(temp).replace(/\//g, '.'); var logfile = path.resolve(f + '/' + onlyFile + '.log'); var fileStrm = fs.createWriteStream(logfile); + console.log('logFile => ', logfile); if (sumanOpts.log_stdio_to_files || sumanOpts.log_stderr_to_files) { n.stderr.pipe(fileStrm).once('error', onError); } @@ -350,9 +354,9 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, n.stdout.pipe(fileStrm).once('error', onError); } } - if (sumanOpts.inherit_stdio || sumanOpts.inherit_all_stdio || process.env.SUMAN_INHERIT_STDIO === 'yes') { + if (inheritRunStdio) { var onError = function (e) { - _suman.logError('\n', suman_utils_1.default.getCleanErrorString(e), '\n'); + _suman.logError('\n', su.getCleanErrorString(e), '\n'); }; n.stdout.pipe(prepend_transform_1.default(chalk.cyan(' [suman child stdout] '))) .once('error', onError).pipe(process.stdout); @@ -363,11 +367,7 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, n.tapOutputIsComplete = false; n.stdout.pipe(getTapParser()) .on('error', function (e) { - _suman.logError('error parsing TAP output => ', suman_utils_1.default.getCleanErrorString(e)); - }); - n.stdout.pipe(getTapJSONParser()) - .on('error', function (e) { - _suman.logError('error parsing TAP JSON output => ', suman_utils_1.default.getCleanErrorString(e)); + _suman.logError('error parsing TAP output =>', su.getCleanErrorString(e)); }) .once('finish', function () { n.tapOutputIsComplete = true; @@ -375,23 +375,28 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, n.emit('tap-output-is-complete', true); }); }); + n.stdout.pipe(getTapJSONParser()) + .on('error', function (e) { + _suman.logError('error parsing TAP JSON output =>', su.getCleanErrorString(e)); + }); } n.stdio[2].setEncoding('utf-8'); n.stdio[2].on('data', function (data) { var d = String(data).split('\n').filter(function (line) { return String(line).length; - }).map(function (line) { + }) + .map(function (line) { return '[' + n.shortTestPath + '] ' + line; - }).join('\n'); - _suman.sumanStderrStream.write('\n\n'); - _suman.sumanStderrStream.write(d); + }) + .join('\n'); + _suman.sumanStderrStream.write('\n' + d); if (_suman.weAreDebugging) { console.log('pid => ', n.pid, 'stderr => ', d); } }); } else { - if (suman_utils_1.default.vgt(2)) { + if (su.vgt(2)) { _suman.logWarning('Stdio object not available for child process.'); } } @@ -401,20 +406,20 @@ exports.makeHandleMultipleProcesses = function (runnerObj, tableRows, messages, run.testPath = file; run.shortTestPath = shortFile; if (handleBlocking.runNext(run)) { - if (suman_utils_1.default.vgt(3) || suman_utils_1.default.isSumanDebug()) { + if (su.vgt(3) || su.isSumanDebug()) { _suman.log('File has just started running =>', chalk.blue(file), '\n'); } } else { runnerObj.queuedCPs.push(run); _suman.log('File is blocked by Suman runner =>', file); - if (suman_utils_1.default.isSumanDebug()) { + if (su.isSumanDebug()) { _suman.log('File is blocked by Suman runner =>', file); } } if (waitForAllTranformsToFinish) { if (forkedCPs.length < 1 && runnerObj.queuedCPs.length > 0) { - throw new Error(' => Suman internal error => fatal start order algorithm error, ' + + throw new Error('Suman internal error => fatal start order algorithm error, ' + 'please file an issue on Github, thanks.'); } if (forkedCPs.length < 1) { diff --git a/lib/runner-helpers/handle-multiple-processes.ts b/lib/runner-helpers/handle-multiple-processes.ts index 6c020752..b6b167ae 100755 --- a/lib/runner-helpers/handle-multiple-processes.ts +++ b/lib/runner-helpers/handle-multiple-processes.ts @@ -1,4 +1,6 @@ 'use strict'; + +//dts import {IRunnerObj, IRunnerRunFn, IRunObj, ISumanChildProcess, ITableRows} from "suman-types/dts/runner"; import {IGlobalSumanObj, IPseudoError} from "suman-types/dts/global"; @@ -16,29 +18,25 @@ import EE = require('events'); //npm import semver = require('semver'); - const merge = require('lodash.merge'); const shuffle = require('lodash.shuffle'); import {events} from 'suman-events'; -import su from 'suman-utils'; +import * as su from 'suman-utils'; import * as async from 'async'; - const noFilesFoundError = require('../helpers/no-files-found-error'); import * as chalk from 'chalk'; //project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); +const resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); const runnerUtils = require('./runner-utils'); import {cpHash, socketHash, ganttHash, IGanttHash, IGanttData} from './socket-cp-hash'; - const {getTapParser} = require('./handle-tap'); const {getTapJSONParser} = require('./handle-tap-json'); const {constants} = require('../../config/suman-constants'); const debug = require('suman-debug')('s:runner'); -const resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); import onExitFn from './multiple-process-each-on-exit'; import pt from 'prepend-transform'; - const runChildPath = require.resolve(__dirname + '/run-child.js'); import uuidV4 = require('uuid/v4'); @@ -157,6 +155,8 @@ export const makeHandleMultipleProcesses = const istanbulExecPath = _suman.istanbulExecPath || 'istanbul'; const isStdoutSilent = sumanOpts.stdout_silent || sumanOpts.silent; const isStderrSilent = sumanOpts.stderr_silent || sumanOpts.silent; + const inheritTransformStdio = + sumanOpts.inherit_all_stdio || sumanOpts.inherit_transform_stdio || process.env.SUMAN_INHERIT_STDIO fileObjArray.forEach(function (fileShortAndFull: Array>) { @@ -244,7 +244,7 @@ export const makeHandleMultipleProcesses = k.stdout.pipe(fileStrm).once('error', onError); } - if (sumanOpts.inherit_all_stdio || sumanOpts.inherit_transform_stdio || process.env.SUMAN_INHERIT_STDIO) { + if (inheritTransformStdio) { let onError = function (e: Error) { _suman.logError('\n', su.getCleanErrorString(e), '\n'); @@ -311,6 +311,10 @@ export const makeHandleMultipleProcesses = let childId = 1; + const debugChildren = sumanOpts.debug_child || sumanOpts.inspect_child; + const inheritRunStdio = debugChildren || sumanOpts.inherit_stdio || + sumanOpts.inherit_all_stdio || process.env.SUMAN_INHERIT_STDIO === 'yes'; + const outer = function (file: string, shortFile: string, stdout: string, gd: IGanttData) { const run = function () { @@ -329,16 +333,16 @@ export const makeHandleMultipleProcesses = const execArgz = ['--expose-gc']; if (sumanOpts.debug_child) { - execArgz.push('--debug-brk'); execArgz.push('--debug=' + (5303 + runnerObj.processId++)); + execArgz.push('--debug-brk'); } if (sumanOpts.inspect_child) { if (semver.gt(process.version, '7.8.0')) { - execArgz.push('--inspect-brk'); + execArgz.push('--inspect-brk=' + (5303 + runnerObj.processId++)); } else { - execArgz.push('--inspect'); + execArgz.push('--inspect=' + (5303 + runnerObj.processId++)); execArgz.push('--debug-brk'); } } @@ -374,7 +378,6 @@ export const makeHandleMultipleProcesses = let $childId = childId++; let childUuid = uuidV4(); - const inherit = _suman.$forceInheritStdio ? 'inherit' : ''; if (inherit) { @@ -389,7 +392,7 @@ export const makeHandleMultipleProcesses = 'ignore', inherit || (isStdoutSilent ? 'ignore' : 'pipe'), inherit || (isStderrSilent ? 'ignore' : 'pipe'), - 'ipc' //TODO: assume 'ipc' is ignored if not a .js file.. + // 'ipc' => we don't need IPC anymore, but also can we assume 'ipc' is ignored if not a .js file? ], env: Object.assign({}, sumanEnv, { SUMAN_CHILD_TEST_PATH: file, @@ -453,13 +456,13 @@ export const makeHandleMultipleProcesses = if (!_suman.weAreDebugging) { n.to = setTimeout(function () { - console.error(' => Suman killed child process because it timed out => \n', - (n.fileName || n.filename)); + _suman.logError(`Suman killed a child process because it timed out: '${n.fileName || n.filename}'.`); n.kill('SIGINT'); setTimeout(function () { + // note that we wait 8 seconds for the child process to clean up before sending it a SIGKILL signal n.kill('SIGKILL'); - }, 18000); - }, 6000000); + }, 8000); + }, constants.DEFAULT_CHILD_PROCESS_TIMEOUT); } n.testPath = file; @@ -492,7 +495,7 @@ export const makeHandleMultipleProcesses = n.stdout.setEncoding('utf8'); n.stderr.setEncoding('utf8'); - if (sumanOpts.log_stdio_to_files || sumanOpts.log_stdout_to_files || sumanOpts.log_stderr_to_files) { + if (false && (sumanOpts.log_stdio_to_files || sumanOpts.log_stdout_to_files || sumanOpts.log_stderr_to_files)) { let onError = function (e: Error) { _suman.logError('\n', su.getCleanErrorString(e), '\n'); @@ -503,6 +506,8 @@ export const makeHandleMultipleProcesses = let logfile = path.resolve(f + '/' + onlyFile + '.log'); let fileStrm = fs.createWriteStream(logfile); + console.log('logFile => ', logfile); + if (sumanOpts.log_stdio_to_files || sumanOpts.log_stderr_to_files) { n.stderr.pipe(fileStrm).once('error', onError); } @@ -512,7 +517,7 @@ export const makeHandleMultipleProcesses = } } - if (sumanOpts.inherit_stdio || sumanOpts.inherit_all_stdio || process.env.SUMAN_INHERIT_STDIO === 'yes') { + if (inheritRunStdio) { let onError = function (e: Error) { _suman.logError('\n', su.getCleanErrorString(e), '\n'); @@ -525,16 +530,12 @@ export const makeHandleMultipleProcesses = } if (true || sumanOpts.$useTAPOutput) { + n.tapOutputIsComplete = false; n.stdout.pipe(getTapParser()) .on('error', function (e: Error) { - _suman.logError('error parsing TAP output => ', su.getCleanErrorString(e)); - }); - - n.stdout.pipe(getTapJSONParser()) - .on('error', function (e: Error) { - _suman.logError('error parsing TAP JSON output => ', su.getCleanErrorString(e)); + _suman.logError('error parsing TAP output =>', su.getCleanErrorString(e)); }) .once('finish', function () { n.tapOutputIsComplete = true; @@ -542,6 +543,12 @@ export const makeHandleMultipleProcesses = n.emit('tap-output-is-complete', true); }); }); + + n.stdout.pipe(getTapJSONParser()) + .on('error', function (e: Error) { + _suman.logError('error parsing TAP JSON output =>', su.getCleanErrorString(e)); + }) + } n.stdio[2].setEncoding('utf-8'); @@ -549,12 +556,13 @@ export const makeHandleMultipleProcesses = const d = String(data).split('\n').filter(function (line) { return String(line).length; - }).map(function (line) { + }) + .map(function (line) { return '[' + n.shortTestPath + '] ' + line; - }).join('\n'); + }) + .join('\n'); - _suman.sumanStderrStream.write('\n\n'); - _suman.sumanStderrStream.write(d); + _suman.sumanStderrStream.write('\n' + d); if (_suman.weAreDebugging) { //TODO: add check for NODE_ENV=dev_local_debug //TODO: go through code and make sure that no console.log statements should in fact be console.error @@ -570,8 +578,7 @@ export const makeHandleMultipleProcesses = } n.dateStartedMillis = gd.startDate = Date.now(); - n.once('exit', - onExitFn(n, runnerObj, tableRows, messages, forkedCPs, beforeExitRunOncePost, makeExit, gd)); + n.once('exit', onExitFn(n, runnerObj, tableRows, messages, forkedCPs, beforeExitRunOncePost, makeExit, gd)); }; @@ -594,7 +601,7 @@ export const makeHandleMultipleProcesses = if (waitForAllTranformsToFinish) { if (forkedCPs.length < 1 && runnerObj.queuedCPs.length > 0) { - throw new Error(' => Suman internal error => fatal start order algorithm error, ' + + throw new Error('Suman internal error => fatal start order algorithm error, ' + 'please file an issue on Github, thanks.'); } diff --git a/lib/runner-helpers/handle-tap.js b/lib/runner-helpers/handle-tap.js index 3f8f489f..9144de52 100755 --- a/lib/runner-helpers/handle-tap.js +++ b/lib/runner-helpers/handle-tap.js @@ -18,7 +18,6 @@ exports.getTapParser = function () { resultBroadcaster.emit(String(suman_events_1.events.TAP_COMPLETE), data); }); p.on('assert', function (testpoint) { - debugger; if (first) { first = false; console.log('\n'); diff --git a/lib/runner-helpers/handle-tap.ts b/lib/runner-helpers/handle-tap.ts index fa165b43..c059da5b 100755 --- a/lib/runner-helpers/handle-tap.ts +++ b/lib/runner-helpers/handle-tap.ts @@ -25,7 +25,7 @@ let first = true; export const getTapParser = function () { - if(first){ + if (first) { _suman.log('we are handling TAP.'); } @@ -37,8 +37,6 @@ export const getTapParser = function () { p.on('assert', function (testpoint: Object) { - debugger; - if (first) { first = false; console.log('\n'); @@ -46,7 +44,6 @@ export const getTapParser = function () { console.log('\n'); } - resultBroadcaster.emit(String(events.TEST_CASE_END), testpoint); if (testpoint.skip) { diff --git a/lib/runner-helpers/make-exit.js b/lib/runner-helpers/make-exit.js index 180cee92..f74710e5 100755 --- a/lib/runner-helpers/make-exit.js +++ b/lib/runner-helpers/make-exit.js @@ -2,10 +2,13 @@ Object.defineProperty(exports, "__esModule", { value: true }); var process = require('suman-browser-polyfills/modules/process'); var global = require('suman-browser-polyfills/modules/global'); +var path = require("path"); +var util = require("util"); var EE = require("events"); var events = require('suman-events').events; var sumanUtils = require('suman-utils'); var async = require("async"); +var player = require('play-sound')(); var sortBy = require('lodash.sortby'); var AsciiTable = require('ascii-table'); var chalk = require("chalk"); @@ -131,17 +134,45 @@ exports.makeExit = function (runnerObj, tableRows) { process.exit(1); }, timeOutMillis); async.autoInject({ - handleAsyncReporters: function (cb) { - async.each(reporterRets, function (item, cb) { - if (!item || item.count < 1) { - process.nextTick(cb); + makeErrorOrSuccessSound: function (cb) { + if (process.env.SUMAN_WATCH_TEST_RUN === 'yes') { + var soundFilePath = void 0; + if (exitCode === 0) { + soundFilePath = null; } else { + soundFilePath = path.resolve(process.env.HOME + '/fail-trombone-02.mp3'); + } + if (!soundFilePath) { + return process.nextTick(cb); + } + player.play(soundFilePath, { timeout: 5000 }, function (err) { + err && _suman.logError(err); + cb(null); + }); + } + else { + process.nextTick(cb); + } + }, + handleAsyncReporters: function (cb) { + async.eachLimit(reporterRets, 5, function (item, cb) { + if (item && item.count > 0) { + var timedout_1 = false; + var timeoutFn = function () { + timedout_1 = true; + console.error("async reporter " + util.inspect(item.reporterName || item) + ", appears to have timed out."); + cb(null); + }; + setTimeout(timeoutFn, 5000); item.cb = function (err) { err && _suman.logError(err.stack || err); process.nextTick(cb); }; } + else { + process.nextTick(cb); + } }, cb); }, makeGanttChart: function (cb) { diff --git a/lib/runner-helpers/make-exit.ts b/lib/runner-helpers/make-exit.ts index 9d9a7c8b..c2bc5996 100755 --- a/lib/runner-helpers/make-exit.ts +++ b/lib/runner-helpers/make-exit.ts @@ -17,7 +17,7 @@ import cp = require('child_process'); const {events} = require('suman-events'); const sumanUtils = require('suman-utils'); import async = require('async'); - +const player = require('play-sound')(); const sortBy = require('lodash.sortby'); const AsciiTable = require('ascii-table'); import chalk = require('chalk'); @@ -192,20 +192,59 @@ export const makeExit = function (runnerObj, tableRows) { async.autoInject({ - handleAsyncReporters: function (cb: Function) { - async.each(reporterRets, function (item: Object, cb: Function) { + makeErrorOrSuccessSound: function (cb: any) { - if (!item || item.count < 1) { - // if nothing is returned from the reporter module, we can't do anything - // and we assume it was all sync - // likewise if count is less than 1 then we are ready to go - process.nextTick(cb); + if (process.env.SUMAN_WATCH_TEST_RUN === 'yes') { + + let soundFilePath; + + if (exitCode === 0) { + soundFilePath = null; } else { + soundFilePath = path.resolve(process.env.HOME + '/fail-trombone-02.mp3'); + } + + if(!soundFilePath){ + return process.nextTick(cb); + } + + player.play(soundFilePath, {timeout: 5000}, function (err: Error) { + err && _suman.logError(err); + cb(null); + }); + + } + else { + process.nextTick(cb); + } + + }, + + handleAsyncReporters: function (cb: Function) { + async.eachLimit(reporterRets, 5, function (item: Object, cb: Function) { + + if (item && item.count > 0) { + + let timedout = false; + let timeoutFn = function () { + timedout = true; + console.error(`async reporter ${util.inspect(item.reporterName || item)}, appears to have timed out.`); + cb(null); + }; + + setTimeout(timeoutFn, 5000); + item.cb = function (err: Error) { err && _suman.logError(err.stack || err); process.nextTick(cb); - } + }; + } + else { + // if nothing is returned from the reporter module, we can't do anything + // and we assume it was all sync + // likewise if count is less than 1 then we are ready to go + process.nextTick(cb); } }, cb); }, diff --git a/lib/runner-helpers/multiple-process-each-on-exit.js b/lib/runner-helpers/multiple-process-each-on-exit.js index 48da67be..f9946409 100755 --- a/lib/runner-helpers/multiple-process-each-on-exit.js +++ b/lib/runner-helpers/multiple-process-each-on-exit.js @@ -69,11 +69,12 @@ function default_1(n, runnerObj, tableRows, messages, forkedCPs, beforeExitRunOn } runnerObj.endTime = Date.now(); runnerObj.listening = false; - var waitForTAP = function () { - async.parallel([ + var onTAPOutputComplete = function () { + var tasks = [ beforeExitRunOncePost, coverage_reporting_1.handleTestCoverageReporting - ], function (err) { + ]; + async.parallel(tasks, function (err) { err && _suman.logError(err.stack || err); makeExit(messages, { total: runnerObj.endTime - _suman.startTime, @@ -83,14 +84,14 @@ function default_1(n, runnerObj, tableRows, messages, forkedCPs, beforeExitRunOn }; if ('tapOutputIsComplete' in n) { if (n.tapOutputIsComplete === true) { - process.nextTick(waitForTAP); + process.nextTick(onTAPOutputComplete); } else { - n.once('tap-output-is-complete', waitForTAP); + n.once('tap-output-is-complete', onTAPOutputComplete); } } else { - process.nextTick(waitForTAP); + process.nextTick(onTAPOutputComplete); } } else { diff --git a/lib/runner-helpers/multiple-process-each-on-exit.ts b/lib/runner-helpers/multiple-process-each-on-exit.ts index f0f98dc9..32bb6db2 100755 --- a/lib/runner-helpers/multiple-process-each-on-exit.ts +++ b/lib/runner-helpers/multiple-process-each-on-exit.ts @@ -112,31 +112,33 @@ export default function (n: ISumanChildProcess, runnerObj: IRunnerObj, tableRows runnerObj.endTime = Date.now(); runnerObj.listening = false; - const waitForTAP = function () { - async.parallel([ - beforeExitRunOncePost, - handleTestCoverageReporting - ] as any, - - function (err: IPseudoError) { - err && _suman.logError(err.stack || err); - makeExit(messages, { - total: runnerObj.endTime - _suman.startTime, - runner: runnerObj.endTime - runnerObj.startTime - }); + const onTAPOutputComplete = function () { + + const tasks = [ + beforeExitRunOncePost, + handleTestCoverageReporting + ] as any; + + async.parallel(tasks, function (err: IPseudoError) { + err && _suman.logError(err.stack || err); + makeExit(messages, { + total: runnerObj.endTime - _suman.startTime, + runner: runnerObj.endTime - runnerObj.startTime }); + }); + }; if ('tapOutputIsComplete' in n) { if (n.tapOutputIsComplete === true) { - process.nextTick(waitForTAP); + process.nextTick(onTAPOutputComplete); } else { - n.once('tap-output-is-complete', waitForTAP); + n.once('tap-output-is-complete', onTAPOutputComplete); } } else { - process.nextTick(waitForTAP); + process.nextTick(onTAPOutputComplete); } } diff --git a/lib/runner-helpers/on-exit.js b/lib/runner-helpers/on-exit.js index 58c37540..946f6d4a 100755 --- a/lib/runner-helpers/on-exit.js +++ b/lib/runner-helpers/on-exit.js @@ -7,9 +7,8 @@ var path = require("path"); var EE = require("events"); var chalk = require("chalk"); var events = require('suman-events').events; -var sumanUtils = require('suman-utils'); -var _suman = global.__suman = (global.__suman || {}); -var resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); +var _suman = global.__suman = global.__suman || {}; +var resultBroadcaster = _suman.resultBroadcaster = _suman.resultBroadcaster || new EE(); exports.onExit = function (code) { if (code > 0) { resultBroadcaster.emit(String(events.RUNNER_EXIT_CODE_GREATER_THAN_ZERO), code); @@ -24,5 +23,5 @@ exports.onExit = function (code) { console.log('\n', ' => At least one test experienced an error => View the test logs => ', '\n', chalk.yellow.bold(logsPath), '\n'); } resultBroadcaster.emit(String(events.RUNNER_EXIT_CODE), code); - fs.appendFileSync(_suman.sumanRunnerStderrStreamPath, '\n\n\n### Suman runner end ###\n\n\n\n\n'); + fs.appendFileSync(_suman.sumanRunnerStderrStreamPath, '\n\n### Suman runner end ###\n\n'); }; diff --git a/lib/runner-helpers/on-exit.ts b/lib/runner-helpers/on-exit.ts index e95b30c8..d0d20e31 100755 --- a/lib/runner-helpers/on-exit.ts +++ b/lib/runner-helpers/on-exit.ts @@ -1,5 +1,8 @@ 'use strict'; +//dts +import {IGlobalSumanObj} from "../../../suman-types/dts/global"; + //polyfills const process = require('suman-browser-polyfills/modules/process'); const global = require('suman-browser-polyfills/modules/global'); @@ -11,13 +14,12 @@ import EE = require('events'); //npm import * as chalk from 'chalk'; - const {events} = require('suman-events'); -const sumanUtils = require('suman-utils'); +import su = require('suman-utils'); //project -const _suman = global.__suman = (global.__suman || {}); -const resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); +const _suman: IGlobalSumanObj = global.__suman = global.__suman || {}; +const resultBroadcaster = _suman.resultBroadcaster = _suman.resultBroadcaster || new EE(); //////////////////////////////////////////////////////////////////////////////////////// @@ -44,6 +46,6 @@ export const onExit = function (code: number) { resultBroadcaster.emit(String(events.RUNNER_EXIT_CODE), code); //write synchronously to ensure it gets written - fs.appendFileSync(_suman.sumanRunnerStderrStreamPath, '\n\n\n### Suman runner end ###\n\n\n\n\n'); + fs.appendFileSync(_suman.sumanRunnerStderrStreamPath, '\n\n### Suman runner end ###\n\n'); }; diff --git a/lib/runner-helpers/run-child.ts b/lib/runner-helpers/run-child.ts index 2897ef58..44066603 100755 --- a/lib/runner-helpers/run-child.ts +++ b/lib/runner-helpers/run-child.ts @@ -47,7 +47,7 @@ process.send = process.send || function (data) { process.on('uncaughtException', function (err: Error) { - debugger; + debugger; // leave it here :) if (_suman.afterAlwaysEngaged) { // after.always hooks are running, let them complete as much as possible diff --git a/lib/runner.js b/lib/runner.js index cdc06468..26a6c6ea 100755 --- a/lib/runner.js +++ b/lib/runner.js @@ -69,8 +69,10 @@ var runnerObj = { var handleIntegrantInfo = makeHandleIntegrantInfo(runnerObj, allOncePostKeys); var exit = make_exit_1.makeExit(runnerObj, tableRows); var beforeExitRunOncePost = make_before_exit_once_post_1.makeBeforeExit(runnerObj, oncePosts, allOncePostKeys); -global.__suman.isActualExitHandlerRegistered = true; -process.once('exit', onExit); +{ + _suman.isActualExitHandlerRegistered = true; + process.once('exit', onExit); +} process.on('error', function (e) { _suman.logError(chalk.magenta('Whoops! "error" event in runner process:') + " \n " + chalk.bold(suman_utils_1.default.getCleanErrorString(e))); }); diff --git a/lib/runner.ts b/lib/runner.ts index 082903fb..054b6841 100755 --- a/lib/runner.ts +++ b/lib/runner.ts @@ -1,4 +1,6 @@ 'use strict'; + +//dts import {IRunnerObj, ISumanChildProcess, ITableRows} from "suman-types/dts/runner"; import {IGlobalSumanObj, IPseudoError} from "suman-types/dts/global"; @@ -48,35 +50,27 @@ import cp = require('child_process'); const fnArgs = require('function-arguments'); const mapValues = require('lodash.mapvalues'); import * as chalk from 'chalk'; - const a8b = require('ansi-256-colors'), fg = a8b.fg, bg = a8b.bg; import {events} from 'suman-events'; import su from 'suman-utils'; - const debug = require('suman-debug')('s:runner'); //project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); import integrantInjector from './injection/integrant-injector'; import {constants} from '../config/suman-constants'; - const ascii = require('./helpers/ascii'); import makeHandleBlocking from './runner-helpers/make-handle-blocking'; - const resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); import {handleFatalMessage} from './runner-helpers/handle-fatal-message'; import {logTestResult} from './runner-helpers/log-test-result'; - const {onExit} = require('./runner-helpers/on-exit'); import {makeExit} from './runner-helpers/make-exit'; - const {makeHandleIntegrantInfo} = require('./runner-helpers/handle-integrant-info'); import {makeBeforeExit} from './runner-helpers/make-before-exit-once-post'; - const makeSingleProcess = require('./runner-helpers/handle-single-process'); const {makeContainerize} = require('./runner-helpers/handle-containerize'); import {makeHandleMultipleProcesses} from './runner-helpers/handle-multiple-processes'; - const IS_SUMAN_SINGLE_PROCESS = process.env.SUMAN_SINGLE_PROCESS === 'yes'; import {getSocketServer, initializeSocketServer} from './runner-helpers/socketio-server'; import {cpHash, socketHash} from './runner-helpers/socket-cp-hash'; @@ -121,8 +115,12 @@ const runnerObj: IRunnerObj = { const handleIntegrantInfo = makeHandleIntegrantInfo(runnerObj, allOncePostKeys); const exit = makeExit(runnerObj, tableRows); const beforeExitRunOncePost = makeBeforeExit(runnerObj, oncePosts, allOncePostKeys); -global.__suman.isActualExitHandlerRegistered = true; -process.once('exit', onExit); + +{ + //register exit here ! + _suman.isActualExitHandlerRegistered = true; + process.once('exit', onExit); +} process.on('error', function (e: IPseudoError) { _suman.logError(`${chalk.magenta('Whoops! "error" event in runner process:')} \n ${chalk.bold(su.getCleanErrorString(e))}`); diff --git a/lib/suman.d.ts b/lib/suman.d.ts index 4886fe7b..49e7f341 100755 --- a/lib/suman.d.ts +++ b/lib/suman.d.ts @@ -1,5 +1,4 @@ import { ITestSuite } from "suman-types/dts/test-suite"; -import { ISumanConfig } from "suman-types/dts/global"; import { ISumanInputs } from "suman-types/dts/suman"; import { ITestDataObj } from "suman-types/dts/it"; export interface ITestBlockMethodCache { @@ -12,6 +11,7 @@ export declare class Suman { private __inject; testBlockMethodCache: ITestBlockMethodCache; iocData: Object; + force: boolean; fileName: string; slicedFileName: string; timestamp: number; @@ -38,4 +38,4 @@ export declare class Suman { logResult(test: ITestDataObj): void; } export declare type ISuman = Suman; -export declare const makeSuman: ($module: NodeModule, _interface: string, shouldCreateResultsDir: boolean, config: ISumanConfig) => Suman; +export declare const makeSuman: ($module: NodeModule, _interface: string, opts: any) => any; diff --git a/lib/suman.js b/lib/suman.js index e9c928a2..45c52f3b 100755 --- a/lib/suman.js +++ b/lib/suman.js @@ -40,6 +40,7 @@ var Suman = (function () { this.numHooksSkipped = 0; this.numHooksStubbed = 0; this.numBlocksSkipped = 0; + this.force = obj.force || false; var queue; this.getQueue = function () { if (!queue) { @@ -223,9 +224,9 @@ var Suman = (function () { test: test, type: 'LOG_RESULT', }); - var client = socketio_child_client_1.getClient(); var LOG_RESULT = suman_constants_1.constants.runner_message_type.LOG_RESULT; if (global.usingBrowserEtcEtc) { + var client = socketio_child_client_1.getClient(); client.emit(LOG_RESULT, JSON.parse(str)); } resultBroadcaster.emit(String(suman_events_1.events.TEST_CASE_END), test); @@ -245,7 +246,7 @@ var Suman = (function () { return Suman; }()); exports.Suman = Suman; -exports.makeSuman = function ($module, _interface, shouldCreateResultsDir, config) { +exports.makeSuman = function ($module, _interface, opts) { var liveSumanServer = false; if (process.argv.indexOf('--live_suman_server') > -1) { liveSumanServer = true; @@ -276,6 +277,7 @@ exports.makeSuman = function ($module, _interface, shouldCreateResultsDir, confi fileName: path.resolve($module.filename), usingLiveSumanServer: liveSumanServer, server: server, + force: opts.force, timestamp: timestamp, interface: _interface }); diff --git a/lib/suman.ts b/lib/suman.ts index d08ad80a..a5d35fc9 100755 --- a/lib/suman.ts +++ b/lib/suman.ts @@ -5,7 +5,7 @@ import {ITestSuite} from "suman-types/dts/test-suite"; import {IGlobalSumanObj, IPseudoError, ISumanConfig} from "suman-types/dts/global"; import {ITableData} from "suman-types/dts/table-data"; import {ISumanInputs} from "suman-types/dts/suman"; -import {ISuman, ITableDataCallbackObj, ISumanServerInfo} from "suman-types/dts/suman"; +import {ITableDataCallbackObj, ISumanServerInfo} from "suman-types/dts/suman"; //polyfills const process = require('suman-browser-polyfills/modules/process'); @@ -34,10 +34,8 @@ const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); import {findSumanServer} from './helpers/find-suman-server'; import {ITestDataObj} from "suman-types/dts/it"; import {constants} from '../config/suman-constants'; - const resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); import {getClient} from './index-helpers/socketio-child-client'; - let envTotal: number, envConfig: number; if (process.env.DEFAULT_PARALLEL_TOTAL_LIMIT && (envTotal = Number(process.env.DEFAULT_PARALLEL_TOTAL_LIMIT))) { @@ -62,6 +60,7 @@ export class Suman { private __inject: Object; testBlockMethodCache: ITestBlockMethodCache; iocData: Object; + force: boolean; fileName: string; slicedFileName: string; timestamp: number; @@ -106,6 +105,7 @@ export class Suman { this.numHooksSkipped = 0; this.numHooksStubbed = 0; this.numBlocksSkipped = 0; + this.force = obj.force || false; let queue: any; @@ -356,10 +356,10 @@ export class Suman { // str = str.replace(/(\r\n|\n|\r)/gm, ''); ///This javascript code removes all 3 types of line breaks // process.send(JSON.parse(str)); - const client = getClient(); const LOG_RESULT = constants.runner_message_type.LOG_RESULT; if (global.usingBrowserEtcEtc) { + const client = getClient(); // TODO: note for the web browser, we need to use this client.emit(LOG_RESULT, JSON.parse(str)); } @@ -388,8 +388,7 @@ export type ISuman = Suman; /////////////////////////////////////////////////////////////////////////////////////////////// -export const makeSuman = function ($module: NodeModule, _interface: string, - shouldCreateResultsDir: boolean, config: ISumanConfig) { +export const makeSuman = function ($module: NodeModule, _interface: string, opts: Objects) { let liveSumanServer = false; @@ -432,6 +431,7 @@ export const makeSuman = function ($module: NodeModule, _interface: string, fileName: path.resolve($module.filename), usingLiveSumanServer: liveSumanServer, server, + force: opts.force, timestamp, interface: _interface }); diff --git a/lib/test-suite-helpers/get-all-eaches.js b/lib/test-suite-helpers/get-all-eaches.js index cd7bef56..ce95a060 100755 --- a/lib/test-suite-helpers/get-all-eaches.js +++ b/lib/test-suite-helpers/get-all-eaches.js @@ -11,12 +11,12 @@ exports.getAllBeforesEaches = function (zuite) { zuite.alreadyHandledAfterAllParentHooks = true; beforeEaches.unshift(zuite.getAfterAllParentHooks()); } - function getParentBefores(parent) { + var getParentBefores = function (parent) { beforeEaches.unshift(parent.getBeforeEaches()); if (parent.parent) { getParentBefores(parent.parent); } - } + }; if (zuite.parent) { getParentBefores(zuite.parent); } @@ -25,12 +25,12 @@ exports.getAllBeforesEaches = function (zuite) { exports.getAllAfterEaches = function (zuite) { var afterEaches = []; afterEaches.push(zuite.getAfterEaches()); - function getParentAfters(parent) { + var getParentAfters = function (parent) { afterEaches.push(parent.getAfterEaches()); if (parent.parent) { getParentAfters(parent.parent); } - } + }; if (zuite.parent) { getParentAfters(zuite.parent); } diff --git a/lib/test-suite-helpers/get-all-eaches.ts b/lib/test-suite-helpers/get-all-eaches.ts index 960b65e0..da932cd2 100755 --- a/lib/test-suite-helpers/get-all-eaches.ts +++ b/lib/test-suite-helpers/get-all-eaches.ts @@ -34,12 +34,12 @@ export const getAllBeforesEaches = function (zuite: ITestSuite) { beforeEaches.unshift(zuite.getAfterAllParentHooks()); } - function getParentBefores(parent: ITestSuite) { + const getParentBefores = function (parent: ITestSuite) { beforeEaches.unshift(parent.getBeforeEaches()); if (parent.parent) { getParentBefores(parent.parent); } - } + }; if (zuite.parent) { getParentBefores(zuite.parent); @@ -53,12 +53,12 @@ export const getAllAfterEaches = function (zuite: ITestSuite) { const afterEaches: Array> = []; afterEaches.push(zuite.getAfterEaches()); - function getParentAfters(parent: ITestSuite) { + const getParentAfters = function (parent: ITestSuite) { afterEaches.push(parent.getAfterEaches()); if (parent.parent) { getParentAfters(parent.parent); } - } + }; if (zuite.parent) { getParentAfters(zuite.parent); diff --git a/lib/test-suite-helpers/make-handle-befores-afters.js b/lib/test-suite-helpers/make-handle-befores-afters.js index ec75c444..57298eef 100755 --- a/lib/test-suite-helpers/make-handle-befores-afters.js +++ b/lib/test-suite-helpers/make-handle-befores-afters.js @@ -28,6 +28,7 @@ exports.makeHandleBeforesAndAfters = function (suman, gracefulExit) { num: 0 }; var d = domain.create(); + _suman.activeDomain = d; d.sumanAllHook = true; d.sumanAllHookName = aBeforeOrAfter.desc || '(unknown all-hook name)'; var fini = handle_callback_helper_1.makeCallback(d, assertCount, null, aBeforeOrAfter, timerObj, gracefulExit, cb); diff --git a/lib/test-suite-helpers/make-handle-befores-afters.ts b/lib/test-suite-helpers/make-handle-befores-afters.ts index 36edb5f3..ccb752b6 100755 --- a/lib/test-suite-helpers/make-handle-befores-afters.ts +++ b/lib/test-suite-helpers/make-handle-befores-afters.ts @@ -19,7 +19,6 @@ const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); import su from 'suman-utils'; import chalk = require('chalk'); import {makeCallback} from './handle-callback-helper'; - const helpers = require('./handle-promise-generator'); const {constants} = require('../../config/suman-constants'); import {cloneError} from '../misc/clone-error'; @@ -51,6 +50,7 @@ export const makeHandleBeforesAndAfters = function (suman: ISuman, gracefulExit: }; const d = domain.create() as ISumanAllHookDomain; + _suman.activeDomain = d; d.sumanAllHook = true; d.sumanAllHookName = aBeforeOrAfter.desc || '(unknown all-hook name)'; diff --git a/lib/test-suite-helpers/make-handle-each.js b/lib/test-suite-helpers/make-handle-each.js index 88f9c1d5..08bc5c71 100755 --- a/lib/test-suite-helpers/make-handle-each.js +++ b/lib/test-suite-helpers/make-handle-each.js @@ -37,6 +37,7 @@ exports.makeHandleBeforeOrAfterEach = function (suman, gracefulExit) { num: 0 }; var d = domain.create(); + _suman.activeDomain = d; d.sumanEachHook = true; d.sumanEachHookName = aBeforeOrAfterEach.desc || '(unknown hook name)'; d.testDescription = test.desc || '(unknown test case name)'; @@ -51,22 +52,18 @@ exports.makeHandleBeforeOrAfterEach = function (suman, gracefulExit) { var stk = err.stack || err; var stck = typeof stk === 'string' ? stk : util.inspect(stk); var formatedStk = String(stck).split('\n').map(function (item) { return '\t' + item; }).join('\n'); - console.error(formatedStk); if (!dError) { dError = true; if (aBeforeOrAfterEach.fatal === false) { - var msg = ' => Suman non-fatal error => Error in hook and "fatal" option for the hook ' + - 'is set to false => \n' + formatedStk; - console.log('\n\n', msg, '\n\n'); - _suman.writeTestError(msg); + _suman.writeTestError(constants.SUMAN_HOOK_FATAL_WARNING_MESSAGE + formatedStk); fini(null); } else { - err = new Error(' => fatal error in hook => (to continue even in the event of an error ' + - 'in a hook, use option {fatal:false}) =>' + '\n\n' + formatedStk); - err.sumanFatal = true; - err.sumanExitCode = constants.EXIT_CODES.FATAL_HOOK_ERROR; - gracefulExit(err); + gracefulExit({ + sumanFatal: true, + sumanExitCode: constants.EXIT_CODES.FATAL_HOOK_ERROR, + stack: constants.SUMAN_HOOK_FATAL_MESSAGE + formatedStk + }); } } else { @@ -100,10 +97,16 @@ exports.makeHandleBeforeOrAfterEach = function (suman, gracefulExit) { var t = t_proto_hook_1.makeHookObj(aBeforeOrAfterEach, assertCount, handleError); fini.th = t; t.timeout = timeout; + t.test = {}; + t.test.desc = test.desc; + t.test.testId = test.testId; + if (aBeforeOrAfterEach.type === 'afterEach/teardownTest') { + t.test.result = test.error ? 'failed' : 'passed'; + t.test.error = test.error; + } t.data = test.data; - t.desc = test.desc; + t.desc = aBeforeOrAfterEach.desc; t.value = test.value; - t.testId = test.testId; t.state = 'pending'; t.shared = self.shared; t.$inject = suman.$inject; diff --git a/lib/test-suite-helpers/make-handle-each.ts b/lib/test-suite-helpers/make-handle-each.ts index ad1cd5d6..5fdf5d06 100755 --- a/lib/test-suite-helpers/make-handle-each.ts +++ b/lib/test-suite-helpers/make-handle-each.ts @@ -17,18 +17,15 @@ import util = require('util'); //npm import chalk = require('chalk'); - const fnArgs = require('function-arguments'); //project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); import su = require('suman-utils'); - const {constants} = require('../../config/suman-constants'); import {cloneError} from '../misc/clone-error'; import {makeHookObj} from './t-proto-hook'; import {makeCallback} from './handle-callback-helper'; - const helpers = require('./handle-promise-generator'); import {freezeExistingProps} from 'freeze-existing-props' @@ -64,6 +61,7 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit }; const d = domain.create() as ISumanEachHookDomain; + _suman.activeDomain = d; d.sumanEachHook = true; d.sumanEachHookName = aBeforeOrAfterEach.desc || '(unknown hook name)'; d.testDescription = test.desc || '(unknown test case name)'; @@ -84,24 +82,19 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit const stck = typeof stk === 'string' ? stk : util.inspect(stk); const formatedStk = String(stck).split('\n').map(item => '\t' + item).join('\n'); - console.error(formatedStk); - if (!dError) { dError = true; if (aBeforeOrAfterEach.fatal === false) { - const msg = ' => Suman non-fatal error => Error in hook and "fatal" option for the hook ' + - 'is set to false => \n' + formatedStk; - console.log('\n\n', msg, '\n\n'); - _suman.writeTestError(msg); + _suman.writeTestError(constants.SUMAN_HOOK_FATAL_WARNING_MESSAGE + formatedStk); fini(null); } else { //note we want to exit right away, that's why this is commented out :) - err = new Error(' => fatal error in hook => (to continue even in the event of an error ' + - 'in a hook, use option {fatal:false}) =>' + '\n\n' + formatedStk); - err.sumanFatal = true; - err.sumanExitCode = constants.EXIT_CODES.FATAL_HOOK_ERROR; - gracefulExit(err); //always fatal error in beforeEach/afterEach + gracefulExit({ + sumanFatal: true, + sumanExitCode: constants.EXIT_CODES.FATAL_HOOK_ERROR, + stack: constants.SUMAN_HOOK_FATAL_MESSAGE + formatedStk + }); } } else { @@ -149,10 +142,19 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit const t = makeHookObj(aBeforeOrAfterEach, assertCount, handleError); fini.th = t; t.timeout = timeout; + t.test = {}; + t.test.desc = test.desc; + t.test.testId = test.testId; + + if(aBeforeOrAfterEach.type === 'afterEach/teardownTest'){ + // these properties are sent to afterEach hooks, but not beforeEach hooks + t.test.result = test.error ? 'failed' : 'passed'; + t.test.error = test.error; + } + t.data = test.data; - t.desc = test.desc; + t.desc = aBeforeOrAfterEach.desc; t.value = test.value; - t.testId = test.testId; t.state = 'pending'; t.shared = self.shared; t.$inject = suman.$inject; diff --git a/lib/test-suite-helpers/make-handle-test.js b/lib/test-suite-helpers/make-handle-test.js index 485e9222..dfb055c3 100755 --- a/lib/test-suite-helpers/make-handle-test.js +++ b/lib/test-suite-helpers/make-handle-test.js @@ -45,6 +45,7 @@ exports.makeHandleTest = function (suman, gracefulExit) { timer: setTimeout(onTimeout, _suman.weAreDebugging ? 5000000 : test.timeout) }; var d = domain.create(); + _suman.activeDomain = d; d.sumanTestCase = true; d.sumanTestName = test.desc; var assertCount = { diff --git a/lib/test-suite-helpers/make-handle-test.ts b/lib/test-suite-helpers/make-handle-test.ts index b4996ff3..4bab8a79 100755 --- a/lib/test-suite-helpers/make-handle-test.ts +++ b/lib/test-suite-helpers/make-handle-test.ts @@ -30,7 +30,6 @@ const helpers = require('./handle-promise-generator'); import {cloneError} from '../misc/clone-error'; import {makeTestCase} from './t-proto-test'; import {freezeExistingProps} from 'freeze-existing-props' - const resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); ///////////////////////////////////////////////////////////////////////////////////// @@ -71,6 +70,7 @@ export const makeHandleTest = function (suman: ISuman, gracefulExit: Function) { }; const d = domain.create() as ISumanTestCaseDomain; + _suman.activeDomain = d; d.sumanTestCase = true; d.sumanTestName = test.desc; diff --git a/lib/test-suite-helpers/make-start-suite.js b/lib/test-suite-helpers/make-start-suite.js index 20c5f22d..01a5019b 100755 --- a/lib/test-suite-helpers/make-start-suite.js +++ b/lib/test-suite-helpers/make-start-suite.js @@ -10,7 +10,6 @@ var _suman = global.__suman = (global.__suman || {}); var implementationError = require('../helpers/implementation-error'); var constants = require('../../config/suman-constants').constants; var makeTheTrap = require('./make-the-trap').makeTheTrap; -var getQueue = require('../helpers/job-queue').getQueue; exports.makeStartSuite = function (suman, gracefulExit, handleBeforesAndAfters, notifyParentThatChildIsComplete) { return function startSuite(finished) { var self = this; diff --git a/lib/test-suite-helpers/make-start-suite.ts b/lib/test-suite-helpers/make-start-suite.ts index 75b37083..0ff92704 100755 --- a/lib/test-suite-helpers/make-start-suite.ts +++ b/lib/test-suite-helpers/make-start-suite.ts @@ -25,7 +25,6 @@ const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); const implementationError = require('../helpers/implementation-error'); const {constants} = require('../../config/suman-constants'); const {makeTheTrap} = require('./make-the-trap'); -const {getQueue} = require('../helpers/job-queue'); //////////////////////////////////////////////////////////////////////////////////// diff --git a/lib/test-suite-helpers/make-the-trap.js b/lib/test-suite-helpers/make-the-trap.js index 85a3f073..f8706653 100755 --- a/lib/test-suite-helpers/make-the-trap.js +++ b/lib/test-suite-helpers/make-the-trap.js @@ -47,7 +47,7 @@ exports.makeTheTrap = function (suman, gracefulExit) { } async.series([ function (cb) { - function handleTestContainer() { + var handleTestContainer = function () { handleTest(self, test, function (err, result) { implementationError(err); var $result = handleTestResult(result, test); @@ -60,7 +60,7 @@ exports.makeTheTrap = function (suman, gracefulExit) { process.nextTick(cb, null, result); } }); - } + }; if (delaySum) { setTimeout(handleTestContainer, delaySum); } diff --git a/lib/test-suite-helpers/make-the-trap.ts b/lib/test-suite-helpers/make-the-trap.ts index e44cfd5d..541f81f5 100755 --- a/lib/test-suite-helpers/make-the-trap.ts +++ b/lib/test-suite-helpers/make-the-trap.ts @@ -3,7 +3,7 @@ //dts import {ITestSuite} from "suman-types/dts/test-suite"; import {ISuman, Suman} from "../suman"; -import {IPseudoError} from "suman-types/dts/global"; +import {IPseudoError, IGlobalSumanObj} from "suman-types/dts/global"; import {IItOpts, ITestDataObj} from "suman-types/dts/it"; import {IBeforeEachObj} from "suman-types/dts/before-each"; import {IAFterEachObj} from "suman-types/dts/after-each"; @@ -20,7 +20,7 @@ import * as async from 'async'; import {events} from 'suman-events'; //project -const _suman = global.__suman = (global.__suman || {}); +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); const {makeHandleTestResults} = require('./handle-test-result'); const {makeHandleTest} = require('./make-handle-test'); const {getAllAfterEaches, getAllBeforesEaches} = require('./get-all-eaches'); @@ -77,7 +77,7 @@ export const makeTheTrap = function (suman: ISuman, gracefulExit: Function) { async.series([ function (cb: Function) { - function handleTestContainer() { + const handleTestContainer = function () { handleTest(self, test, function (err: IPseudoError, result: any) { implementationError(err); let $result = handleTestResult(result, test); @@ -90,7 +90,7 @@ export const makeTheTrap = function (suman: ISuman, gracefulExit: Function) { process.nextTick(cb, null, result); } }); - } + }; if (delaySum) { // if non-zero / non-falsy value setTimeout(handleTestContainer, delaySum); diff --git a/lib/test-suite-helpers/notify-parent-that-child-is-complete.js b/lib/test-suite-helpers/notify-parent-that-child-is-complete.js index ec83573a..b661362b 100755 --- a/lib/test-suite-helpers/notify-parent-that-child-is-complete.js +++ b/lib/test-suite-helpers/notify-parent-that-child-is-complete.js @@ -38,7 +38,6 @@ exports.makeNotifyParent = function (suman, gracefulExit, handleBeforesAndAfters async.mapSeries(parent.getAfters(), function (aBeforeOrAfter, cb) { handleBeforesAndAfters(child, aBeforeOrAfter, cb); }, function complete(err, results) { - debugger; implementationError(err); gracefulExit(results, function () { notifyParentThatChildIsComplete(parent, cb); diff --git a/lib/test-suite-helpers/notify-parent-that-child-is-complete.ts b/lib/test-suite-helpers/notify-parent-that-child-is-complete.ts index 380bdfc0..aea3bbc9 100755 --- a/lib/test-suite-helpers/notify-parent-that-child-is-complete.ts +++ b/lib/test-suite-helpers/notify-parent-that-child-is-complete.ts @@ -70,7 +70,6 @@ export const makeNotifyParent = function (suman: ISuman, gracefulExit: Function, function complete(err: IPseudoError, results: Array) { - debugger; implementationError(err); gracefulExit(results, function () { notifyParentThatChildIsComplete(parent, cb); diff --git a/lib/test-suite-helpers/t-proto.js b/lib/test-suite-helpers/t-proto.js index ff6d5c53..5d279c86 100755 --- a/lib/test-suite-helpers/t-proto.js +++ b/lib/test-suite-helpers/t-proto.js @@ -36,7 +36,7 @@ proto.wrapErrorFirst = proto.wrapErrFirst = function (fn) { }; }; proto.log = function () { - _suman._writeLog.apply(null, arguments); + _suman.writeLog.apply(null, arguments); }; proto.slow = function () { this.timeout(20000); diff --git a/lib/test-suite-helpers/t-proto.ts b/lib/test-suite-helpers/t-proto.ts index 072058cf..b783a727 100755 --- a/lib/test-suite-helpers/t-proto.ts +++ b/lib/test-suite-helpers/t-proto.ts @@ -53,7 +53,7 @@ proto.wrapErrorFirst = proto.wrapErrFirst = function (fn: Function) { }; proto.log = function() { - _suman._writeLog.apply(null, arguments); + _suman.writeLog.apply(null, arguments); }; proto.slow = function () { diff --git a/lib/test-suite-methods/make-after-each.js b/lib/test-suite-methods/make-after-each.js index 7b438cca..479463d4 100755 --- a/lib/test-suite-methods/make-after-each.js +++ b/lib/test-suite-methods/make-after-each.js @@ -19,6 +19,9 @@ var acceptableOptions = { cb: true, timeout: true, skip: true, + events: true, + successEvents: true, + errorEvents: true, __preParsed: true }; var handleBadOptions = function (opts) { diff --git a/lib/test-suite-methods/make-after-each.ts b/lib/test-suite-methods/make-after-each.ts index d11264f4..43a1ac1b 100755 --- a/lib/test-suite-methods/make-after-each.ts +++ b/lib/test-suite-methods/make-after-each.ts @@ -34,6 +34,9 @@ const acceptableOptions = { cb: true, timeout: true, skip: true, + events: true, + successEvents: true, + errorEvents: true, __preParsed: true }; diff --git a/lib/test-suite-methods/make-before-each.js b/lib/test-suite-methods/make-before-each.js index eb4a69f1..4f09d76c 100755 --- a/lib/test-suite-methods/make-before-each.js +++ b/lib/test-suite-methods/make-before-each.js @@ -18,6 +18,9 @@ var acceptableOptions = { plan: true, fatal: true, skip: true, + events: true, + successEvents: true, + errorEvents: true, __preParsed: true }; var handleBadOptions = function (opts) { diff --git a/lib/test-suite-methods/make-before-each.ts b/lib/test-suite-methods/make-before-each.ts index 239b607b..67538d88 100755 --- a/lib/test-suite-methods/make-before-each.ts +++ b/lib/test-suite-methods/make-before-each.ts @@ -38,6 +38,9 @@ const acceptableOptions = { plan: true, fatal: true, skip: true, + events: true, + successEvents: true, + errorEvents: true, __preParsed: true }; diff --git a/lib/test-suite-methods/make-before.js b/lib/test-suite-methods/make-before.js index 96f3055f..21035996 100755 --- a/lib/test-suite-methods/make-before.js +++ b/lib/test-suite-methods/make-before.js @@ -18,6 +18,9 @@ var acceptableOptions = { cb: true, timeout: true, skip: true, + events: true, + successEvents: true, + errorEvents: true, __preParsed: true }; var handleBadOptions = function (opts) { diff --git a/lib/test-suite-methods/make-before.ts b/lib/test-suite-methods/make-before.ts index 45cb3649..477b9181 100755 --- a/lib/test-suite-methods/make-before.ts +++ b/lib/test-suite-methods/make-before.ts @@ -42,6 +42,9 @@ const acceptableOptions = { cb: true, timeout: true, skip: true, + events: true, + successEvents: true, + errorEvents: true, __preParsed: true }; diff --git a/lib/test-suite-methods/make-describe.ts b/lib/test-suite-methods/make-describe.ts index 7af9ac47..f89e4d2d 100755 --- a/lib/test-suite-methods/make-describe.ts +++ b/lib/test-suite-methods/make-describe.ts @@ -65,13 +65,13 @@ const handleBadOptions = function (opts: IDescribeOpts) { }); }; -/////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// export const makeDescribe = function (suman: ISuman, gracefulExit: Function, TestSuiteMaker: TTestSuiteMaker, zuite: ITestSuite, notifyParentThatChildIsComplete: Function, blockInjector: Function): IDescribeFn { - ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////// return function ($$desc: string, $opts: IDescribeOpts) { diff --git a/lib/test-suite-methods/make-inject.js b/lib/test-suite-methods/make-inject.js index c656e0ba..ac65f412 100755 --- a/lib/test-suite-methods/make-inject.js +++ b/lib/test-suite-methods/make-inject.js @@ -18,6 +18,9 @@ var acceptableOptions = { cb: true, timeout: true, skip: true, + events: true, + successEvents: true, + errorEvents: true, __preParsed: true }; var handleBadOptions = function (opts) { diff --git a/lib/test-suite-methods/make-inject.ts b/lib/test-suite-methods/make-inject.ts index e47df7d2..3958ae7a 100755 --- a/lib/test-suite-methods/make-inject.ts +++ b/lib/test-suite-methods/make-inject.ts @@ -42,6 +42,9 @@ const acceptableOptions = { cb: true, timeout: true, skip: true, + events: true, + successEvents: true, + errorEvents: true, __preParsed: true }; diff --git a/lib/test-suite-methods/make-it.js b/lib/test-suite-methods/make-it.js index 007bfafd..5b4a9790 100755 --- a/lib/test-suite-methods/make-it.js +++ b/lib/test-suite-methods/make-it.js @@ -24,6 +24,9 @@ var acceptableOptions = { timeout: true, only: true, skip: true, + events: true, + successEvents: true, + errorEvents: true, __preParsed: true }; var handleBadOptions = function (opts) { diff --git a/lib/test-suite-methods/make-it.ts b/lib/test-suite-methods/make-it.ts index d94460e7..cf01f777 100755 --- a/lib/test-suite-methods/make-it.ts +++ b/lib/test-suite-methods/make-it.ts @@ -44,6 +44,9 @@ const acceptableOptions = { timeout: true, only: true, skip: true, + events: true, + successEvents: true, + errorEvents: true, __preParsed: true }; diff --git a/package.json b/package.json index 294d06c2..4132e9bb 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,10 @@ "should": "^11.2.0", "webpack": "^2.4.0" }, + "optionalDependencies": { + "suman-watch": "latest", + "play-sound": "^1.1.1" + }, "repository": { "type": "git", "url": "git+https://github.com/sumanjs/suman.git" diff --git a/scripts/suman-clis.sh b/scripts/suman-clis.sh index e1a0a892..1b269cff 100755 --- a/scripts/suman-clis.sh +++ b/scripts/suman-clis.sh @@ -65,7 +65,7 @@ function suman-inspect { handle_global_suman node_exec_args "$@" else echo "running node against local suman" - NODE_PATH=${NEW_NODE_PATH} PATH=${NEW_PATH} node --inspect-brk "$LOCAL_SUMAN" "$@"; + NODE_PATH="${NEW_NODE_PATH}" PATH="${NEW_PATH}" node --inspect-brk "$LOCAL_SUMAN" "$@"; fi } diff --git a/scripts/touch.sh b/scripts/touch.sh new file mode 100755 index 00000000..e5ff9db7 --- /dev/null +++ b/scripts/touch.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +touch cli.js diff --git a/suman-todos.txt b/suman-todos.txt index ce7d2dfd..36617d14 100755 --- a/suman-todos.txt +++ b/suman-todos.txt @@ -4,12 +4,33 @@ three SO profiles: 2. via facebook login on chrome 3. the1mills@yahoo.com on firefox "Olegzandr Denman" +/// + + in --series mode -> we should put currently executing test or hook in global space + especially for the browser. + +/// + + use es6 symbols to hide properties? + https://www.keithcirkel.co.uk/metaprogramming-in-es6-symbols/ + /// the runner hangs every few runs, there must be a race condition /// +@ORESoftware It depends on the version of node the running process uses. +If it's node 8, then you should be able to `kill -USR2 ${pidOfTheNodeProcess}` to enable the --inspect behavior after the fact. + + +/// + + suman-watch should be optionalDep? + suman-interactive should be optionalDep? + +/// + cd $(dirname "$0") [ ! -d "node_modules/babel-runtime" ] && npm install babel-runtime [ ! -d "node_modules/babel-core" ] && npm install babel-core @@ -25,8 +46,15 @@ cd $(dirname "$0") //// - suman --scripts abc + it.skipped() should be an alias of it.skip() + +//// + => give user choice as to use bash or zsh or whatever for suman watch + +//// + + suman --scripts abc => should run the script that's in suman.conf.js /// @@ -37,12 +65,10 @@ cd $(dirname "$0") /// babel: - removed these from {package.json}.devDependencies: - "babel-loader": "^6.4.1", - "babel-polyfill": "^6.23.0", - "babel-preset-latest": "^6.24.0", + "babel-polyfill": "^6.23.0", + "babel-preset-latest": "^6.24.0", /// @@ -54,28 +80,24 @@ cd $(dirname "$0") /// - before / beforeEach hooks should attach a value to suman.$inject if a value is returned + before / beforeEach hooks should attach a value to suman.$inject if a value is returned /// -// after always may not be run in the right order -async.eachSeries(allDescribeBlocks, function (block: ITestSuite, cb: Function) { + after always may not be run in the right order + async.eachSeries(allDescribeBlocks, function (block: ITestSuite, cb: Function) { /// - => afterEach should have test info, not just value/data + => afterEach should have test info, not just value/data //// - => test suman itself with suman, then we can make final adjustments before release - -/// - - => chai 4.0.2 works. + => test suman itself with suman, then we can make final adjustments before release /// - _suman.ctx => suman.ctx ? + => chai 4.0.2 works. /// @@ -83,17 +105,17 @@ async.eachSeries(allDescribeBlocks, function (block: ITestSuite, cb: Function) { /// - we should be able to create a test file with suman --create - and run the file, without running suman --init on a directory, see unnecessary error: + we should be able to create a test file with suman --create + and run the file, without running suman --init on a directory, see unnecessary error: - => Suman could *not* locate your ; perhaps you need to update your suman.conf.js file, please see: *** + => Suman could *not* locate your ; perhaps you need to update your suman.conf.js file, please see: *** => http://sumanjs.org/conf.html => We expected to find your here => - /Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman-types/suman + /Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman-types/suman - => If there is NO SUMAN HELPERS DIR, flip a boolean, and just use all the default files. + => If there is NO SUMAN HELPERS DIR, flip a boolean, and just use all the default files. - // >>>>> or just run the test with node instead of suman? + // >>>>> or just run the test with node instead of suman? /// @@ -121,7 +143,6 @@ Test.create('hotels2', {parallel: false}, function (it, before, beforeEach, desc }); - /// ⚑ Suman fatal error => making a graceful exit => @@ -140,12 +161,6 @@ Test.create('hotels2', {parallel: false}, function (it, before, beforeEach, desc => if error message is multi-line, it gets removed...for example when we call "'no success property on body => ' + util.inspect(x) " - -/// - - in --series mode -> we should put currently executing test or hook in global space - especially for the browser. - /// https://stackoverflow.com/a/1221870/5020949 @@ -169,24 +184,19 @@ node test/src/exp.js | grep -v [[suman]] /// - use es6 symbols to hide properties? - https://www.keithcirkel.co.uk/metaprogramming-in-es6-symbols/ - -/// - - before hooks can be stubbed? => before('merry'); + before hooks can be stubbed? => before('merry'); /// - improve tables -> they should work on Jenkins, etc. + improve tables -> they should work on Jenkins, etc. /// - enforceUniqueTestCaseNames:true + enforceUniqueTestCaseNames:true /// -fatal error in hook does not have cause or reason (the first line!): + fatal error in hook does not have cause or reason (the first line!): ⚑ Suman fatal error => making a graceful exit => Error: => fatal error in hook => (to continue even in the event of an error in a hook, use option {fatal:false}) => @@ -227,56 +237,51 @@ fatal error in hook does not have cause or reason (the first line!): /// -use git submodules to publish suman-types -https://git-scm.com/book/en/v2/Git-Tools-Submodules - -/// - - using suman.ctx instead of _suman.ctx would allow this - run Test.creates suman.ioc.js files in parallel? + use git submodules to publish suman-types + https://git-scm.com/book/en/v2/Git-Tools-Submodules /// - use https://github.com/tunnckoCore/parse-function, instead of function-arguments + use https://github.com/tunnckoCore/parse-function, instead of function-arguments /// - after hooks should be fatal:false by default? + after hooks should be fatal:false by default? /// - when `suman --init` is run, we should create a dir called .suman not suman - and suman-default-config.js should be updated to reflect that + when `suman --init` is run, we should create a dir called .suman not suman + and suman-default-config.js should be updated to reflect that /// - suman test/src/tap-output/tap-producer1.js --runner --use-tap => exit code is 56 - suman test/src/tap-output/tap-producer1.js --runner => exit code is 1 + suman test/src/tap-output/tap-producer1.js --runner --use-tap => exit code is 56 + suman test/src/tap-output/tap-producer1.js --runner => exit code is 1 // - in order for parallel-max to work properly, - the last test suite to be put on the queue, needs to wait. + in order for parallel-max to work properly, + the last test suite to be put on the queue, needs to wait. // - => absolute --parallel would just mean unleashing things in exec-suite.js so that a parent does *not* need to complete - before a child starts. + => absolute --parallel would just mean unleashing things in exec-suite.js so that a parent does *not* need to complete + before a child starts. // - --use-tap prevents tables from being printed by runner, weird. + --use-tap prevents tables from being printed by runner, weird. /// - "please report this on the Github issue..." => add a link to these instance in the codebase to sumanjs/suman#issues + "please report this on the Github issue..." => add a link to these instance in the codebase to sumanjs/suman#issues /// - when a command in run.sh fails, we need to send that stderr - to the runner, e.g.: + when a command in run.sh fails, we need to send that stderr + to the runner, e.g.: - => [suman child stderr] => ./suman/test/src/mocha/@run.sh: line 6: mocha: command not found + => [suman child stderr] => ./suman/test/src/mocha/@run.sh: line 6: mocha: command not found //// @@ -337,29 +342,29 @@ https://git-scm.com/book/en/v2/Git-Tools-Submodules at TestSuiteMaker.TestSuite.__invokeChildren (/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/lib/test-suite-helpers/make-test-suite.js:205:19) -//// +/// _suman.log and _suman.logError need to split everything by newline so that [suman] appears on each line -//// +/// suman child id should be a uuid not an integer -//// +/// suman needs to take a node path as argument SUMAN_NODEJS_EXEC_PATH=x -//// +/// use -- --seed instead of --user-args? -//// +/// if @run.sh exists for a file x, but the command is just "suman x", then the runner won't be used and @run.sh won't be used. If @run.sh is found, we must use the runner. -//// +/// put a "twitter like" button on the webpage Please Share on Twitter if you like #mockgoose @@ -379,14 +384,6 @@ https://git-scm.com/book/en/v2/Git-Tools-Submodules inject only works when we do not need to use a before/beforeEach to load data beforehand -//// - -it(x, t => { - - t.$inject => could contain the before values that are created by before/beforeEach - -}); - //// create $iocShared and $ioc diff --git a/suman.conf.js b/suman.conf.js index bd9f8723..4ed2ffe5 100755 --- a/suman.conf.js +++ b/suman.conf.js @@ -9,7 +9,7 @@ const numOfCPUs = os.cpus().length || 1; module.exports = Object.freeze({ - //☺,♫ + //☺,♫ // //regex matchAny: [/\.js$/, /.sh$/, /\.jar$/, /\.java$/, /\.go$/, /\.ts$/], @@ -19,8 +19,7 @@ module.exports = Object.freeze({ //string testDir: 'test', testSrcDir: 'test/src/dev/node', - testTargetDir: 'test/target', - sumanHelpersDir: 'test/_suman', + sumanHelpersDir: 'test/.suman', uniqueAppName: '', browser: 'Firefox', // browser to open test results with logsDir: process.env['SUMAN_LOGS_DIR'], @@ -76,36 +75,39 @@ module.exports = Object.freeze({ expireResultsAfter: 10000000, // test results will be deleted after this amount of time watch: { - - 'all-tests': './node_modules/.bin/suman', - 'unit-tests': './node_modules/.bin/suman test/unit/**/*.js', - - '//tests': { - 'default': { // (re) execute the test file that changed - script: function (p) { - return `./node_modules/.bin/suman ${p}` - }, - include: [], - exclude: ['^test.*'] + options: { + shellExecutable: 'bash', + soundFilePaths: { + runtimeError: path.resolve(process.env.HOME + '/fail-trombone-02.mp3'), + success: path.resolve(process.env.HOME + '/ta_da_sound.mp3'), + testFailure: path.resolve(process.env.HOME + '/fail-trombone-02.mp3') } }, - - '//project': { - script: './node_modules/.bin/suman', - include: [], - exclude: ['^test.*'], - + per: { + 'node-dev': { + exec: 'suman test/src/dev/node --verbosity=4', + includes: [__dirname], + excludes: ['/test/', /\.ts$/], + confOverride: {} + } }, - - 'default': { //run all tests when a file changes in project - script: './node_modules/.bin/suman', - include: [], - exclude: ['^test.*'] + 'browser-dev': { + exec: 'suman test/src/dev/browser', + includes: [__dirname], + excludes: ['/test/', /\.ts$/], + confOverride: {} } }, + //////////////////////////////////////////////////// + + scripts: { + // usage: $ suman --scripts example + example: 'export NODE_ENV=test; echo "I love 45"; echo "NODE_ENV value => ${NODE_ENV}"' + }, + reporters: { - 'tap': 'node_modules/suman/lib/reporters/tap-reporter' + 'tap': 'suman-reporters/modules/tap-reporter' }, // servers: { // list of servers to output test result data to, with the os.hostname() as the key diff --git a/.babelrc b/test/.babelrc similarity index 100% rename from .babelrc rename to test/.babelrc diff --git a/test/_suman/Dockerfile b/test/.suman/Dockerfile similarity index 100% rename from test/_suman/Dockerfile rename to test/.suman/Dockerfile diff --git a/test/_suman/gantt-2.hbs b/test/.suman/gantt-2.hbs similarity index 100% rename from test/_suman/gantt-2.hbs rename to test/.suman/gantt-2.hbs diff --git a/test/_suman/gantt-3.html b/test/.suman/gantt-3.html similarity index 100% rename from test/_suman/gantt-3.html rename to test/.suman/gantt-3.html diff --git a/test/_suman/gantt-4.html b/test/.suman/gantt-4.html similarity index 87% rename from test/_suman/gantt-4.html rename to test/.suman/gantt-4.html index 558a9600..78a964c4 100644 --- a/test/_suman/gantt-4.html +++ b/test/.suman/gantt-4.html @@ -220,7 +220,7 @@ "status": "KILLED" }]; - let tasksRaw = JSON.parse('[{"startDate":1506840133006,"endDate":1506840133540,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/1.test.js","status":"SUCCEEDED"},{"startDate":1506840133000,"endDate":1506840133540,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/2.test.js","status":"SUCCEEDED"}]'); + let tasksRaw = JSON.parse('[{"startDate":1507345161982,"endDate":1507345162813,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/2.test.js","status":"SUCCEEDED"},{"startDate":1507345161979,"endDate":1507345162739,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/3.test.js","status":"SUCCEEDED"},{"startDate":1507345161974,"endDate":1507345162813,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/1.test.js","status":"SUCCEEDED"},{"startDate":1507345161966,"endDate":1507345162738,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/4.test.js","status":"SUCCEEDED"},{"startDate":1507345161962,"endDate":1507345162612,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/5.test.js","status":"FAILED"}]'); let tasks = []; diff --git a/test/_suman/gantt.html b/test/.suman/gantt.html similarity index 100% rename from test/_suman/gantt.html rename to test/.suman/gantt.html diff --git a/test/_suman/logs/.readme b/test/.suman/logs/.readme similarity index 100% rename from test/_suman/logs/.readme rename to test/.suman/logs/.readme diff --git a/test/_suman/report/x.html b/test/.suman/report/x.html similarity index 100% rename from test/_suman/report/x.html rename to test/.suman/report/x.html diff --git a/test/_suman/reporters/tap.js b/test/.suman/reporters/tap.js similarity index 100% rename from test/_suman/reporters/tap.js rename to test/.suman/reporters/tap.js diff --git a/test/_suman/scripts/a.sh b/test/.suman/scripts/a.sh similarity index 100% rename from test/_suman/scripts/a.sh rename to test/.suman/scripts/a.sh diff --git a/test/_suman/scripts/b.sh b/test/.suman/scripts/b.sh similarity index 100% rename from test/_suman/scripts/b.sh rename to test/.suman/scripts/b.sh diff --git a/test/_suman/scripts/c.sh b/test/.suman/scripts/c.sh similarity index 100% rename from test/_suman/scripts/c.sh rename to test/.suman/scripts/c.sh diff --git a/test/_suman/suman.globals.d.ts b/test/.suman/suman.globals.d.ts similarity index 100% rename from test/_suman/suman.globals.d.ts rename to test/.suman/suman.globals.d.ts diff --git a/test/_suman/suman.globals.js b/test/.suman/suman.globals.js similarity index 100% rename from test/_suman/suman.globals.js rename to test/.suman/suman.globals.js diff --git a/test/_suman/suman.globals.ts b/test/.suman/suman.globals.ts similarity index 100% rename from test/_suman/suman.globals.ts rename to test/.suman/suman.globals.ts diff --git a/test/_suman/suman.groups-old.d.ts b/test/.suman/suman.groups-old.d.ts similarity index 100% rename from test/_suman/suman.groups-old.d.ts rename to test/.suman/suman.groups-old.d.ts diff --git a/test/_suman/suman.groups-old.js b/test/.suman/suman.groups-old.js similarity index 100% rename from test/_suman/suman.groups-old.js rename to test/.suman/suman.groups-old.js diff --git a/test/_suman/suman.groups-old.ts b/test/.suman/suman.groups-old.ts similarity index 100% rename from test/_suman/suman.groups-old.ts rename to test/.suman/suman.groups-old.ts diff --git a/test/_suman/suman.groups.d.ts b/test/.suman/suman.groups.d.ts similarity index 100% rename from test/_suman/suman.groups.d.ts rename to test/.suman/suman.groups.d.ts diff --git a/test/_suman/suman.groups.js b/test/.suman/suman.groups.js similarity index 100% rename from test/_suman/suman.groups.js rename to test/.suman/suman.groups.js diff --git a/test/_suman/suman.groups.ts b/test/.suman/suman.groups.ts similarity index 100% rename from test/_suman/suman.groups.ts rename to test/.suman/suman.groups.ts diff --git a/test/_suman/suman.hooks.d.ts b/test/.suman/suman.hooks.d.ts similarity index 100% rename from test/_suman/suman.hooks.d.ts rename to test/.suman/suman.hooks.d.ts diff --git a/test/_suman/suman.hooks.js b/test/.suman/suman.hooks.js similarity index 100% rename from test/_suman/suman.hooks.js rename to test/.suman/suman.hooks.js diff --git a/test/_suman/suman.hooks.ts b/test/.suman/suman.hooks.ts similarity index 100% rename from test/_suman/suman.hooks.ts rename to test/.suman/suman.hooks.ts diff --git a/test/_suman/suman.ioc.d.ts b/test/.suman/suman.ioc.d.ts similarity index 100% rename from test/_suman/suman.ioc.d.ts rename to test/.suman/suman.ioc.d.ts diff --git a/test/_suman/suman.ioc.js b/test/.suman/suman.ioc.js similarity index 100% rename from test/_suman/suman.ioc.js rename to test/.suman/suman.ioc.js diff --git a/test/_suman/suman.ioc.static.d.ts b/test/.suman/suman.ioc.static.d.ts similarity index 100% rename from test/_suman/suman.ioc.static.d.ts rename to test/.suman/suman.ioc.static.d.ts diff --git a/test/_suman/suman.ioc.static.js b/test/.suman/suman.ioc.static.js similarity index 100% rename from test/_suman/suman.ioc.static.js rename to test/.suman/suman.ioc.static.js diff --git a/test/_suman/suman.ioc.static.ts b/test/.suman/suman.ioc.static.ts similarity index 100% rename from test/_suman/suman.ioc.static.ts rename to test/.suman/suman.ioc.static.ts diff --git a/test/_suman/suman.ioc.ts b/test/.suman/suman.ioc.ts similarity index 100% rename from test/_suman/suman.ioc.ts rename to test/.suman/suman.ioc.ts diff --git a/test/_suman/suman.once.post.d.ts b/test/.suman/suman.once.post.d.ts similarity index 100% rename from test/_suman/suman.once.post.d.ts rename to test/.suman/suman.once.post.d.ts diff --git a/test/_suman/suman.once.post.js b/test/.suman/suman.once.post.js similarity index 100% rename from test/_suman/suman.once.post.js rename to test/.suman/suman.once.post.js diff --git a/test/_suman/suman.once.post.ts b/test/.suman/suman.once.post.ts similarity index 100% rename from test/_suman/suman.once.post.ts rename to test/.suman/suman.once.post.ts diff --git a/test/_suman/suman.once.pre.d.ts b/test/.suman/suman.once.pre.d.ts similarity index 100% rename from test/_suman/suman.once.pre.d.ts rename to test/.suman/suman.once.pre.d.ts diff --git a/test/_suman/suman.once.pre.js b/test/.suman/suman.once.pre.js similarity index 100% rename from test/_suman/suman.once.pre.js rename to test/.suman/suman.once.pre.js diff --git a/test/_suman/suman.once.pre.ts b/test/.suman/suman.once.pre.ts similarity index 100% rename from test/_suman/suman.once.pre.ts rename to test/.suman/suman.once.pre.ts diff --git a/test/_suman/suman.order.d.ts b/test/.suman/suman.order.d.ts similarity index 100% rename from test/_suman/suman.order.d.ts rename to test/.suman/suman.order.d.ts diff --git a/test/_suman/suman.order.js b/test/.suman/suman.order.js similarity index 100% rename from test/_suman/suman.order.js rename to test/.suman/suman.order.js diff --git a/test/_suman/suman.order.ts b/test/.suman/suman.order.ts similarity index 100% rename from test/_suman/suman.order.ts rename to test/.suman/suman.order.ts diff --git a/test/_suman/tsconfig.json b/test/.suman/tsconfig.json similarity index 100% rename from test/_suman/tsconfig.json rename to test/.suman/tsconfig.json diff --git a/test/src/dev/node/1.test.js b/test/src/dev/node/1.test.js index 20fecb76..7218c1f1 100644 --- a/test/src/dev/node/1.test.js +++ b/test/src/dev/node/1.test.js @@ -9,10 +9,8 @@ const Test = suman.init(module); let count = 0; const opts = {series: true, fixed: true}; - Test.create(opts, function (assert, describe, before, beforeEach, after, afterEach, it) { - it('sync test', t => { assert(true); }); @@ -22,7 +20,6 @@ Test.create(opts, function (assert, describe, before, beforeEach, after, afterEa h.assert.equal(count, 1); }); - describe('nested1', () => { // console.log('before => ', before); diff --git a/test/src/dev/node/3.test.js b/test/src/dev/node/3.test.js new file mode 100644 index 00000000..f0ece8cd --- /dev/null +++ b/test/src/dev/node/3.test.js @@ -0,0 +1,107 @@ +#!/usr/bin/env node +'use strict'; + +const suman = require('suman'); +const {Test} = suman.init(module); + +/////////////////////////////////////////////////////////////////////// + +Test.create(function (assert, describe, before, beforeEach, after, afterEach, it) { + + describe('here we go', function () { + + before(h => { + assert(true); + }); + + it('sync test', t => { + assert(true); + }); + + after(h => { + assert(true); + }); + + describe('here we go', function () { + + before(h => { + assert(true); + }); + + it('sync test', t => { + assert(true); + }); + + after(h => { + assert(true); + }); + + describe('here we go', function () { + + before(h => { + assert(true); + }); + + it('sync test', t => { + assert(true); + }); + + after(h => { + assert(true); + }); + + describe('here we go', function () { + + before(h => { + assert(true); + }); + + it('sync test', t => { + assert(true); + }); + + after(h => { + assert(true); + }); + + }); + + }); + + describe('here we go', function () { + + before(h => { + assert(true); + }); + + it('sync test', t => { + assert(true); + }); + + after(h => { + assert(true); + }); + + }); + + }); + + describe('here we go', function () { + + before(h => { + assert(true); + }); + + it('sync test', t => { + assert(true); + }); + + after(h => { + assert(true); + }); + + }); + + }); + +}); diff --git a/test/src/dev/node/4.test.js b/test/src/dev/node/4.test.js new file mode 100644 index 00000000..c24f4b9e --- /dev/null +++ b/test/src/dev/node/4.test.js @@ -0,0 +1,150 @@ +#!/usr/bin/env node +'use strict'; + +const suman = require('suman'); +const Test = suman.init(module); + +/////////////////////////////////////////////////////////////////////// + +let count = 0; + +Test.create(function (assert, describe, before, beforeEach, after, afterEach, it) { + + before(h => { + h.assert.equal(++count, 1); + }); + + it.cb('sync test', t => { + t.assert.equal(++count, 2); + t.done() + }); + + after.cb(h => { + h.assert.equal(++count, 26); + h.ctn(); + }); + + describe('here we go', function () { + + before(h => { + h.assert.equal(++count, 3); + }); + + it.cb('sync test', t => { + t.assert.equal(++count, 4); + t.done() + }); + + after.cb(h => { + h.assert.equal(++count, 25); + h.ctn(); + }); + + describe('here we go', function () { + + before(h => { + h.assert.equal(++count, 5); + }); + + it('sync test', t => { + t.assert.equal(++count, 6); + }); + + after(h => { + h.assert.equal(++count, 19); + }); + + describe('here we go', function () { + + before(h => { + h.assert.equal(++count, 7); + }); + + it('sync test', t => { + t.assert.equal(++count, 8); + }); + + after.cb(h => { + h.assert.equal(++count, 13); + h.ctn(); + }); + + after(h => { + h.assert.equal(++count, 14); + }); + + describe('here we go', function () { + + before(h => { + h.assert.equal(++count, 9); + }); + + it('sync test', t => { + t.assert.equal(++count, 10); + }); + + after.cb(h => { + h.assert.equal(++count, 11); + h.ctn(); + }); + + after(h => { + h.assert.equal(++count, 12); + }); + + }); + + }); + + describe('here we go', function () { + + before(h => { + h.assert.equal(++count, 15); + }); + + after.cb(h => { + h.assert.equal(++count, 17); + h.ctn(); + }); + + it('sync test', t => { + t.assert.equal(++count, 16); + }); + + after(h => { + h.assert.equal(++count, 18); + }); + + }); + + }); + + describe('here we go', function () { + + before(h => { + h.assert.equal(++count, 20); + }); + + after.cb(h => { + h.assert.equal(++count, 23); + h.ctn(); + }); + + it('sync test', t => { + t.assert.equal(++count, 21); + }); + + it.cb('sync test', t => { + t.assert.equal(++count, 22); + t.done(); + }); + + after(h => { + h.assert.equal(++count, 24); + }); + + }); + + }); + +}); diff --git a/test/src/dev/node/5.test.js b/test/src/dev/node/5.test.js new file mode 100644 index 00000000..b6267966 --- /dev/null +++ b/test/src/dev/node/5.test.js @@ -0,0 +1,174 @@ +#!/usr/bin/env node +'use strict'; + +const suman = require('suman'); +const {Test} = suman.init(module, { + forceParallel: true // parallel, not parallel-max +}); + +/////////////////////////////////////////////////////////////////////// + +let count = 0; + +Test.create(function (assert, describe, before, beforeEach, after, afterEach, it, util) { + + before(h => { + + }); + + it.cb('passing', t => { + t.done(); + }); + + it.cb('failing', t => { + t.done('this test failed'); + }); + + afterEach.cb(h => { + + if (h.test.desc === 'passing') { + h.assert.equal(h.test.result, 'passed'); + } + else { + h.assert.equal(h.test.result, 'failed'); + } + + h.ctn(); + }); + + describe('here we go', function () { + + before(h => { + + }); + + it.cb('failing', t => { + t.done('buggers') + }); + + afterEach.cb(h => { + + h.ctn(); + }); + + afterEach.cb(h => { + if (h.test.desc === 'passing') { + h.assert.equal(h.test.result, 'passed'); + } + else { + h.assert.equal(h.test.result, 'failed'); + } + h.ctn(); + }); + + describe('here we go', function () { + + before(h => { + + }); + + it('passing', t => { + + }); + + after(h => { + + }); + + describe('here we go', function () { + + before(h => { + + }); + + it('failing', t => { + return Promise.reject('zoomba'); + }); + + after.cb(h => { + h.ctn(); + }); + + after(h => { + + }); + + describe('here we go', function () { + + before(h => { + + }); + + it('passing', t => { + + }); + + it.skip('xxx', t => { + // skipped tests should not reach beforeEach/afterEach hooks + }); + + it('xxx'); // stubbed tests should not reach beforeEach/afterEach hooks + + after.cb(h => { + h.ctn(); + }); + + after(h => { + + }); + + }); + + }); + + describe('here we go', function () { + + before(h => { + + }); + + after.cb(h => { + h.ctn(); + }); + + it('passing', t => { + + }); + + after(h => { + + }); + + }); + + }); + + describe('here we go', function () { + + before(h => { + + }); + + after.cb(h => { + + h.ctn(); + }); + + it('passing', t => { + + }); + + it.cb('passing', t => { + + t.done(); + }); + + after(h => { + + }); + + }); + + }); + +}); diff --git a/test/src/exp/tap-output/@target/tap-producer1.js b/test/src/exp/tap-output/@target/tap-producer1.js index c34275bd..d69bd4fb 100755 --- a/test/src/exp/tap-output/@target/tap-producer1.js +++ b/test/src/exp/tap-output/@target/tap-producer1.js @@ -1,7 +1,7 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +exports.__esModule = true; var suman_1 = require("suman"); -var Test = suman_1.default.init(module); +var Test = suman_1["default"].init(module); console.log('zoom'); Test.create(function (it, before, describe, beforeEach, afterEach, after) { before('yup', [function (h) { @@ -10,6 +10,7 @@ Test.create(function (it, before, describe, beforeEach, afterEach, after) { describe('ruby tuesday', function () { }); it('zoom', function (t) { + // t.assert.deepEqual(false, true); throw new Error('whole me 3'); }) .it('rudolph', function (t) { diff --git a/test/src/exp/tap-output/@target/tap-producer2.js b/test/src/exp/tap-output/@target/tap-producer2.js index 53235672..ff644c00 100755 --- a/test/src/exp/tap-output/@target/tap-producer2.js +++ b/test/src/exp/tap-output/@target/tap-producer2.js @@ -1,12 +1,14 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +exports.__esModule = true; var suman_1 = require("suman"); -var Test = suman_1.default.init(module); +var Test = suman_1["default"].init(module); Test.create(function (it) { it('passes', function (t) { + // t.skip(); throw new Error('whole me 1'); }); it('fails', function (t) { + // t.skip(); throw new Error('whole me 2'); }); }); diff --git a/tsconfig.json b/tsconfig.json index 6dd8fd4f..06426f5b 100755 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,8 +3,8 @@ "declaration": true, "baseUrl": ".", "typeRoots": [ - "node_modules/@types", - "node_modules/suman-types/dts" + "./node_modules/@types", + "./node_modules/suman-types/dts" ], "allowJs": false, "target": "es5",