From 2b148f81557d5baa51285308b1ed1ceb2db1c87f Mon Sep 17 00:00:00 2001 From: Operations Research Engineering Software+ Date: Fri, 22 Dec 2017 00:27:14 -0800 Subject: [PATCH] Feature alexamil 1513501344142 (#231) * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * pdev:set * feature:merge:1513931196251 --- .travis.yml | 8 +- CONTRIBUTING.md | 10 + dev-scripts/exp/exp.js | 135 ++----- dev-scripts/exp/exp.sh | 12 +- dev-scripts/exp/exp3.d.ts | 11 +- dev-scripts/exp/exp3.js | 17 +- dev-scripts/exp/exp3.ts | 44 ++- dev-scripts/exp/exp4.d.ts | 4 + dev-scripts/exp/exp4.js | 85 +++-- dev-scripts/exp/exp4.ts | 49 +++ dev-scripts/exp/my-mocha.d.ts | 1 + dev-scripts/exp/my-mocha.js | 102 +++-- dev-scripts/exp/my-mocha.ts | 45 +++ dev-scripts/travis/after_script.sh | 13 + dev-scripts/travis/before_install.sh | 5 + dev-scripts/travis/install.sh | 14 + dev-scripts/travis/script.sh | 7 + lib/cli-commands/init-opt/index.js | 6 +- lib/default-conf-files/suman.default.conf.js | 2 +- lib/helpers/general.d.ts | 7 +- lib/helpers/general.js | 6 +- lib/helpers/general.ts | 16 +- lib/helpers/load-reporters-last-ditch.js | 10 +- lib/helpers/load-reporters.js | 14 +- lib/helpers/run-after-always.js | 11 +- lib/helpers/run-after-always.ts | 14 +- lib/index.d.ts | 7 +- lib/index.js | 29 +- lib/index.ts | 37 +- lib/injection/helpers.js | 8 +- lib/make-graceful-exit.js | 13 +- lib/make-graceful-exit.ts | 12 +- .../browser/add-to-run-queue.js | 4 +- .../browser/add-to-run-queue.ts | 5 +- .../browser/add-to-transpile-queue.js | 8 +- .../browser/add-to-transpile-queue.ts | 8 +- lib/runner-helpers/coverage-reporting.ts | 3 + lib/runner-helpers/handle-containerize.js | 4 +- lib/runner-helpers/handle-containerize.ts | 4 +- .../handle-multiple-processes.ts | 1 - .../handle-different-executables.js | 47 +-- .../handle-different-executables.ts | 51 ++- .../multiple-process-each-on-exit.js | 1 - .../multiple-process-each-on-exit.ts | 1 - lib/runner-helpers/run-child.js | 2 + lib/runner-helpers/run-child.ts | 2 + lib/runner-helpers/runner-utils.d.ts | 11 +- lib/runner-helpers/runner-utils.js | 47 ++- lib/runner-helpers/runner-utils.ts | 124 +++++-- lib/s.d.ts | 7 +- lib/s.js | 8 + lib/s.ts | 7 +- lib/schemas/@config.json | 1 + .../define-options-classes.d.ts | 2 +- .../define-options-classes.js | 6 +- .../define-options-classes.ts | 10 +- lib/test-suite-helpers/handle-injections.js | 17 +- lib/test-suite-helpers/handle-injections.ts | 22 +- .../handle-promise-generator.d.ts | 4 +- .../handle-promise-generator.js | 8 +- .../handle-promise-generator.ts | 8 +- lib/test-suite-helpers/make-fini-callbacks.js | 97 ++--- lib/test-suite-helpers/make-fini-callbacks.ts | 113 +++--- .../make-handle-befores-afters.d.ts | 4 +- .../make-handle-befores-afters.js | 17 +- .../make-handle-befores-afters.ts | 48 +-- lib/test-suite-helpers/make-handle-each.js | 35 +- lib/test-suite-helpers/make-handle-each.ts | 58 +-- lib/test-suite-helpers/make-handle-test.js | 29 +- lib/test-suite-helpers/make-handle-test.ts | 39 +- lib/test-suite-helpers/make-test-suite.d.ts | 40 ++ lib/test-suite-helpers/make-test-suite.js | 66 +++- lib/test-suite-helpers/make-test-suite.ts | 57 ++- lib/test-suite-helpers/make-the-trap.d.ts | 2 +- lib/test-suite-helpers/make-the-trap.js | 88 ++--- lib/test-suite-helpers/make-the-trap.ts | 195 +++++----- .../notify-parent-that-child-is-complete.js | 6 +- .../notify-parent-that-child-is-complete.ts | 7 +- lib/test-suite-helpers/suman-methods.d.ts | 3 +- lib/test-suite-helpers/suman-methods.ts | 5 +- lib/test-suite-helpers/t-proto-hook.d.ts | 2 - lib/test-suite-helpers/t-proto-hook.js | 36 -- lib/test-suite-helpers/t-proto-hook.ts | 67 ---- lib/test-suite-helpers/t-proto-inject.d.ts | 3 - lib/test-suite-helpers/t-proto-inject.js | 88 ----- lib/test-suite-helpers/t-proto-inject.ts | 140 ------- lib/test-suite-helpers/t-proto-test.d.ts | 6 - lib/test-suite-helpers/t-proto-test.js | 42 --- lib/test-suite-helpers/t-proto-test.ts | 84 ----- lib/test-suite-helpers/t-proto.d.ts | 1 - lib/test-suite-helpers/t-proto.js | 214 ----------- lib/test-suite-helpers/t-proto.ts | 270 -------------- lib/test-suite-methods/make-after.js | 2 +- lib/test-suite-methods/make-after.ts | 2 +- lib/test-suite-methods/make-before.js | 2 +- lib/test-suite-methods/make-before.ts | 2 +- lib/test-suite-methods/make-describe.d.ts | 3 +- lib/test-suite-methods/make-describe.js | 1 - lib/test-suite-methods/make-describe.ts | 4 +- lib/test-suite-methods/make-it.js | 1 + lib/test-suite-methods/make-it.ts | 1 + .../all-hook/all-hook-param.d.ts | 11 + .../all-hook/all-hook-param.js | 59 +++ .../all-hook/all-hook-param.ts | 84 +++++ lib/test-suite-params/base.d.ts | 45 +++ lib/test-suite-params/base.js | 267 ++++++++++++++ lib/test-suite-params/base.ts | 349 ++++++++++++++++++ .../each-hook/each-hook-param.d.ts | 11 + .../each-hook/each-hook-param.js | 58 +++ .../each-hook/each-hook-param.ts | 84 +++++ .../inject/inject-param.d.ts | 23 ++ lib/test-suite-params/inject/inject-param.js | 143 +++++++ lib/test-suite-params/inject/inject-param.ts | 201 ++++++++++ .../test-case/test-case-param.d.ts | 20 + .../test-case/test-case-param.js | 53 +++ .../test-case/test-case-param.ts | 86 +++++ suman-todos.txt | 19 +- test/.suman/.meta/gantt.html | 2 +- test/.suman/.meta/timeline.html | 2 +- test/src/dev/node/1.test.js | 4 + test/src/dev/node/2.test.js | 4 +- test/src/dev/node/3.test.js | 36 +- test/src/dev/node/5.test.js | 50 ++- test/src/dev/node/6.test.js | 2 +- test/src/dev/node/dep-injection/one.test.js | 13 + test/src/dev/node/events.test.js | 6 +- ...{injection2.test.js => injection2.test.ts} | 84 +++-- test/src/dev/node/supply/one.js | 32 ++ test/src/exp/before-each.js | 12 +- test/src/exp/es5-es6/other-tests/test6.js | 99 +++-- 130 files changed, 2974 insertions(+), 1942 deletions(-) create mode 100644 dev-scripts/exp/exp4.d.ts create mode 100644 dev-scripts/exp/exp4.ts create mode 100644 dev-scripts/exp/my-mocha.d.ts mode change 100755 => 100644 dev-scripts/exp/my-mocha.js create mode 100755 dev-scripts/exp/my-mocha.ts create mode 100755 dev-scripts/travis/after_script.sh create mode 100755 dev-scripts/travis/before_install.sh create mode 100755 dev-scripts/travis/install.sh create mode 100755 dev-scripts/travis/script.sh delete mode 100755 lib/test-suite-helpers/t-proto-hook.d.ts delete mode 100755 lib/test-suite-helpers/t-proto-hook.js delete mode 100755 lib/test-suite-helpers/t-proto-hook.ts delete mode 100644 lib/test-suite-helpers/t-proto-inject.d.ts delete mode 100644 lib/test-suite-helpers/t-proto-inject.js delete mode 100644 lib/test-suite-helpers/t-proto-inject.ts delete mode 100755 lib/test-suite-helpers/t-proto-test.d.ts delete mode 100755 lib/test-suite-helpers/t-proto-test.js delete mode 100755 lib/test-suite-helpers/t-proto-test.ts delete mode 100755 lib/test-suite-helpers/t-proto.d.ts delete mode 100755 lib/test-suite-helpers/t-proto.js delete mode 100755 lib/test-suite-helpers/t-proto.ts create mode 100644 lib/test-suite-params/all-hook/all-hook-param.d.ts create mode 100644 lib/test-suite-params/all-hook/all-hook-param.js create mode 100644 lib/test-suite-params/all-hook/all-hook-param.ts create mode 100644 lib/test-suite-params/base.d.ts create mode 100644 lib/test-suite-params/base.js create mode 100644 lib/test-suite-params/base.ts create mode 100644 lib/test-suite-params/each-hook/each-hook-param.d.ts create mode 100644 lib/test-suite-params/each-hook/each-hook-param.js create mode 100644 lib/test-suite-params/each-hook/each-hook-param.ts create mode 100644 lib/test-suite-params/inject/inject-param.d.ts create mode 100644 lib/test-suite-params/inject/inject-param.js create mode 100644 lib/test-suite-params/inject/inject-param.ts create mode 100644 lib/test-suite-params/test-case/test-case-param.d.ts create mode 100644 lib/test-suite-params/test-case/test-case-param.js create mode 100644 lib/test-suite-params/test-case/test-case-param.ts rename test/src/dev/node/{injection2.test.js => injection2.test.ts} (81%) mode change 100644 => 100755 create mode 100644 test/src/dev/node/supply/one.js diff --git a/.travis.yml b/.travis.yml index 3a8ce15b..0416fdd1 100755 --- a/.travis.yml +++ b/.travis.yml @@ -16,11 +16,11 @@ addons: packages: - g++-4.8 -before_install: 'if [[ `npm -v` != 4* ]]; then npm i -g npm@4; fi' +before_install: './dev-scripts/travis/before_install.sh' install: - - 'npm install --silent --no-optional > /dev/null 2>&1' -script: 'rm -rf node_modules && npm cache clean && npm install istanbul --silent > /dev/null 2>&1 && npm link -f --silent > /dev/null 2>&1 && npm link suman -f --silent > /dev/null 2>&1 && suman --force test/src/dev/node/injection.test.js' -after_script: 'npm install -g coveralls && cat coverage/lcov.info | coveralls' + - './dev-scripts/travis/install.sh' +script: './dev-scripts/travis/script.sh' +after_script: './dev-scripts/travis/after_script.sh' notifications: email: false slack: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aac9a888..9ad825ea 100755 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,3 +35,13 @@ Once you submit the PR to master, CI/CD tests will run, then if they pass, we de You can use this tool to clone all the SumanJS projects onto your machine: This project will run the ./build.sh file and ./contribute.sh file in each project. + + + +# Release steps + +1. update bash completion in case command line arguments have changed + +`$ suman --completion > scripts/suman-completion.sh` + +2. ? diff --git a/dev-scripts/exp/exp.js b/dev-scripts/exp/exp.js index 75c24562..a55b4569 100755 --- a/dev-scripts/exp/exp.js +++ b/dev-scripts/exp/exp.js @@ -1,118 +1,57 @@ #!/usr/bin/env node -const v = { - z: true, - foo: {two: 2} -}; - -let x = Object.setPrototypeOf({}, v); - -x.foo = 3; - -console.log(x); -console.log(v); - -function* foo() { - yield 1; - yield 2; - yield 3; -} - -for (let o of foo()) { - console.log(o); -} - -console.log(Object.keys(new Map({a: 'b'}))); - - x = {}; - -x.retries(5) -.foo() -.run(t => { +// (async function(){ +// +// let z= await 5; +// console.log('z => ',z); +// +// })(); -}); -describe('danger') -.run(function () {}); -const Promise = require('bluebird'); -const async = require('async'); +// Object.keys({a:'b','c':'cr'}).forEach(function(k){ +// console.log('k => ', k); +// throw 'boo'; +// }); -async.series({ - - a: async function (cb) { - return Promise.delay(500).then(v => 'zzz'); - }, - - b: async function (cb) { - // process.nextTick(cb, null, 'bbb'); - let c = await Promise.delay(500).then(v => 'hopkins'); - return c; - // cb(null, 'xxx'); - } +// +// const assert = require('assert'); +// assert.equal(typeof (()=>{}).prototype, 'undefined'); - }, - function (err, results) { +// that's cool that arrow functions don't have a prototype property +// why not create a special kind of function that has no prototype? +// we only use the prototype, 5% of the time, or less - if (err) throw err; - console.log('results => ', results); - process.exit(0); - }); +// the existing way -// inject(j => { -// -// return j.inject({ -// a: function(cb){ -// -// }, -// -// b: function (cb) { -// -// } -// }); +// let fn1 = function(){ // -// return [j.inject('av', function (cb) { -// -// -// })]; +// }; // -// // b.$injected.x = z; +// assert.equal(typeof fn1.prototype, 'object'); // -// }); - -// console.log(typeof [][Symbol.iterator]); - -// const x = { -// watch: { +// // why not a prototype-less function +// let fn2 = function(){ // +// }; // -// per: { // -// foo: { -// exec: 'suman test/*.js', -// include: [], -// exclude: [], -// confOverride: {}, -// env: {} -// }, +// const time = Date.now(); // -// bar: { -// exec: 'suman --browser test/front-end/*.js', -// include: [], -// exclude: [], -// confOverride: {} -// }, // -// baz: { -// exec: 'exec "${SUMAN_CHANGED_TEST_FILE}"', -// include: [], -// exclude: [], -// confOverride: { +// for(let i = 0; i < 1000000; i++){ +// var z = function () { // -// } -// } +// } +// } // -// } // -// } -// }; +// console.log(Date.now() - time); + + +let err = false; + +let z = !err; + + +console.log('z => ',z ); diff --git a/dev-scripts/exp/exp.sh b/dev-scripts/exp/exp.sh index f9ccecb3..f4a2f6af 100755 --- a/dev-scripts/exp/exp.sh +++ b/dev-scripts/exp/exp.sh @@ -6,4 +6,14 @@ #echo "global_modules => $global_modules" -sh $(dirname $0)/exp.js +#sh $(dirname $0)/exp.js + +json_array=\''["one","two","three"]'\'; + +function getJSON { + node -pe "JSON.parse($json_array).join('\n')" +} + +getJSON | while read line; do + echo "$line" +done diff --git a/dev-scripts/exp/exp3.d.ts b/dev-scripts/exp/exp3.d.ts index eeb4a0cd..cfad7d09 100644 --- a/dev-scripts/exp/exp3.d.ts +++ b/dev-scripts/exp/exp3.d.ts @@ -1,2 +1,9 @@ -declare type T = (x: number) => boolean; -declare let fn: (a: string, b: boolean, c: T) => void; +declare class Person { + name: string; + constructor(name: string); + greet(greeting: string): string; +} +interface Person { + hi: typeof Person.prototype.greet; +} +declare const p: Person; diff --git a/dev-scripts/exp/exp3.js b/dev-scripts/exp/exp3.js index 09e1ff62..56b17057 100644 --- a/dev-scripts/exp/exp3.js +++ b/dev-scripts/exp/exp3.js @@ -1,6 +1,11 @@ -var fn = function (a, b, c) { c(); }; -fn('yes', true, (function () { -})); -fn('yes', true, (function () { -})); -debugger; +var Person = (function () { + function Person(name) { + this.name = name; + } + Person.prototype.greet = function (greeting) { return greeting + ", " + this.name; }; + return Person; +}()); +Person.prototype.hi = Person.prototype.greet; +var p = new Person("Alice"); +console.log(p.greet("Hey")); +console.log(p.hi("Hi")); diff --git a/dev-scripts/exp/exp3.ts b/dev-scripts/exp/exp3.ts index 4947e834..2d89bf3d 100644 --- a/dev-scripts/exp/exp3.ts +++ b/dev-scripts/exp/exp3.ts @@ -1,15 +1,33 @@ +// +// type T = (x: number) => boolean; +// +// let fn = function(a: string, b: boolean, c: T){ c()}; +// +// fn('yes', true, (() => { +// +// }) as any); +// +// fn('yes', true, (() => { +// +// })); +// +// debugger; + + +class Person { + constructor(public name: string) {} + greet(greeting: string): string { return `${greeting}, ${this.name}`; } +} + +interface Person { + hi: typeof Person.prototype.greet; +} + + +Person.prototype.hi = Person.prototype.greet; + +const p = new Person("Alice"); +console.log(p.greet("Hey")); +console.log(p.hi("Hi")); -type T = (x: number) => boolean; - -let fn = function(a: string, b: boolean, c: T){ c()}; - -fn('yes', true, (() => { - -}) as any); - -fn('yes', true, (() => { - -})); - -debugger; diff --git a/dev-scripts/exp/exp4.d.ts b/dev-scripts/exp/exp4.d.ts new file mode 100644 index 00000000..a2d121d1 --- /dev/null +++ b/dev-scripts/exp/exp4.d.ts @@ -0,0 +1,4 @@ +declare const suman: any; +declare const Test: any; +declare const async: any; +declare let count: number; diff --git a/dev-scripts/exp/exp4.js b/dev-scripts/exp/exp4.js index be5060c0..d3554f26 100644 --- a/dev-scripts/exp/exp4.js +++ b/dev-scripts/exp/exp4.js @@ -1,27 +1,64 @@ #!/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 (b, test) { - - test('tomorrow', t => { - - t.done(); - debugger; - // const x = t.skirt.foo; - // console.log(x); - t.assert(true); - t.assert.equal(true, true); - t.expect(function () {}).to.not.throw(); - - }); - +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var suman = require('suman'); +var Test = suman.init(module, { + forceParallel: true +}).Test; +var async = require('async'); +var count = 0; +async.series({ + a: function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, 300]; + case 1: + _a.sent(); + return [2, 5]; + } + }); + }); + } +}, function (err, results) { + if (err) { + throw err; + } + console.log('results => ', results); + Test.create(function (b, test) { + }); }); diff --git a/dev-scripts/exp/exp4.ts b/dev-scripts/exp/exp4.ts new file mode 100644 index 00000000..16ad3be2 --- /dev/null +++ b/dev-scripts/exp/exp4.ts @@ -0,0 +1,49 @@ +#!/usr/bin/env node +'use strict'; + +const suman = require('suman'); +const {Test} = suman.init(module, { + forceParallel: true // parallel, not parallel-max +}); + +const async = require('async'); + +/////////////////////////////////////////////////////////////////////// + +let count = 0; + +async.series({ + a: async function () { + await 300; + return 5; + } + }, + function (err, results) { + + if(err){ + throw err; + } + + console.log('results => ', results); + + Test.create(function (b, test) { + + // test('tomorrow', t => { + // + // // t.done(); + // debugger; + // // const x = t.skirt.foo; + // // console.log(x); + // t.assert(true); + // t.assert.equal(true, true); + // t.expect(function () {}).to.not.throw(); + // + // }); + + + + }); + + + }); + diff --git a/dev-scripts/exp/my-mocha.d.ts b/dev-scripts/exp/my-mocha.d.ts new file mode 100644 index 00000000..4b43407b --- /dev/null +++ b/dev-scripts/exp/my-mocha.d.ts @@ -0,0 +1 @@ +declare const async: any; diff --git a/dev-scripts/exp/my-mocha.js b/dev-scripts/exp/my-mocha.js old mode 100755 new mode 100644 index f52a71d2..4b365127 --- a/dev-scripts/exp/my-mocha.js +++ b/dev-scripts/exp/my-mocha.js @@ -1,38 +1,70 @@ #!/usr/bin/env node - -// const fs = require('fs'); -// const assert = require('assert'); -// console.log(process.argv); -// -// fs.open(__filename, 'r+', function (err, fd) { -// -// if (err) throw err; -// -// const b = Buffer.alloc(4); -// -// fs.read(fd, b, 0, 4, 0, function (err, bytesRead, buffer) { -// -// if (err) throw err; -// -// console.log('data: ', bytesRead); -// console.log('buffer: ', String(buffer)); -// assert(buffer === b); -// -// }); -// }); -// - -const a = function (o,z,k) { - Array.from(arguments).forEach(function (a, index) { - console.log(index, a); - }); +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); }; - -const b = function (o,z,k) { - a.apply(null,arguments.slice()); +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } }; - - -b(1,2,3); - - +var async = require('async'); +async.series({ + one: function () { + return __awaiter(this, void 0, void 0, function () { + var x; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, 1]; + case 1: + x = _a.sent(); + return [2, x]; + } + }); + }); + }, + two: function () { + return __awaiter(this, void 0, void 0, function () { + var x; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, 2]; + case 1: + x = _a.sent(); + return [2, x]; + } + }); + }); + } +}, function (err, results) { + if (err) { + throw err; + } + console.log('results =>', results); +}); diff --git a/dev-scripts/exp/my-mocha.ts b/dev-scripts/exp/my-mocha.ts new file mode 100755 index 00000000..16c9b18b --- /dev/null +++ b/dev-scripts/exp/my-mocha.ts @@ -0,0 +1,45 @@ +#!/usr/bin/env node + +// const fs = require('fs'); +// const assert = require('assert'); +// console.log(process.argv); +// +// fs.open(__filename, 'r+', function (err, fd) { +// +// if (err) throw err; +// +// const b = Buffer.alloc(4); +// +// fs.read(fd, b, 0, 4, 0, function (err, bytesRead, buffer) { +// +// if (err) throw err; +// +// console.log('data: ', bytesRead); +// console.log('buffer: ', String(buffer)); +// assert(buffer === b); +// +// }); +// }); +// + +const async = require('async'); + +async.series({ + one: async function(){ + let x = await 1; + return x; + }, + two: async function(){ + let x = await 2; + return x; + } + }, + function(err, results){ + + if(err){ + throw err; + } + + console.log('results =>', results); + }); + diff --git a/dev-scripts/travis/after_script.sh b/dev-scripts/travis/after_script.sh new file mode 100755 index 00000000..7a64a16a --- /dev/null +++ b/dev-scripts/travis/after_script.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + + +set -e; + +which_coveralls="$(which coveralls)"; + +if [[ -z "$which_coveralls" ]]; then + npm install -g coveralls +fi + + +cat coverage/lcov.info | coveralls diff --git a/dev-scripts/travis/before_install.sh b/dev-scripts/travis/before_install.sh new file mode 100755 index 00000000..a9e6ec07 --- /dev/null +++ b/dev-scripts/travis/before_install.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +if [[ `npm -v` != 5* ]]; then + npm i -g npm@5; +fi diff --git a/dev-scripts/travis/install.sh b/dev-scripts/travis/install.sh new file mode 100755 index 00000000..6757793f --- /dev/null +++ b/dev-scripts/travis/install.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +#set -e; + +rm -rf node_modules +npm cache verify # npm cache clean + +npm install --silent --no-optional + +which_istanbul="$(which istanbul)" + +if [[ -z "$which_istanbul" ]]; then + npm install -g istanbul --silent +fi diff --git a/dev-scripts/travis/script.sh b/dev-scripts/travis/script.sh new file mode 100755 index 00000000..b9084922 --- /dev/null +++ b/dev-scripts/travis/script.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e; + +npm link -f --silent > /dev/null 2>&1 +npm link suman -f --silent > /dev/null 2>&1 +suman --force test/src/dev/node/injection.test.js diff --git a/lib/cli-commands/init-opt/index.js b/lib/cli-commands/init-opt/index.js index c7666358..97deeaa8 100755 --- a/lib/cli-commands/init-opt/index.js +++ b/lib/cli-commands/init-opt/index.js @@ -87,9 +87,9 @@ exports.run = function (opts, projectRoot, cwd) { } try { if (!fforce) { - var p = path.resolve(projectRoot + '/' + (conf ? (conf.sumanHelpersDir || '/suman') : '/suman')); - _suman.log.info(' => Looking for existing suman helpers dir here => "' + p + '"'); - var files = fs.readdirSync(p); + var p_1 = path.resolve(projectRoot + '/' + (conf ? (conf.sumanHelpersDir || '/suman') : '/suman')); + _suman.log.info(' => Looking for existing suman helpers dir here => "' + p_1 + '"'); + var files = fs.readdirSync(p_1); sumanHelperDirFound = true; files.forEach(function (file) { if (!sumanAlreadyInittedBecauseConfFileExists) { diff --git a/lib/default-conf-files/suman.default.conf.js b/lib/default-conf-files/suman.default.conf.js index 973a3ab3..707cc470 100755 --- a/lib/default-conf-files/suman.default.conf.js +++ b/lib/default-conf-files/suman.default.conf.js @@ -20,7 +20,7 @@ module.exports = { logsDir: process.env['SUMAN_LOGS_DIR'], //boolean - viewGantt: true, + viewGantt: false, retriesEnabled: false, useColorByDefault: true, debugHooks: true, diff --git a/lib/helpers/general.d.ts b/lib/helpers/general.d.ts index 479de86f..74ec8306 100755 --- a/lib/helpers/general.d.ts +++ b/lib/helpers/general.d.ts @@ -3,9 +3,6 @@ import { ISumanConfig, ISumanOpts } from "suman-types/dts/global"; import { IAllOpts, ITestSuite } from "suman-types/dts/test-suite"; import { Suman } from "../suman"; import { ISumanServerInfo } from "suman-types/dts/suman"; -export interface ICloneErrorFn { - (err: Error, newMessage: string, stripAllButTestFilePathMatch?: boolean): IPseudoError; -} export declare const handleSetupComplete: (test: ITestSuite, type: string) => void; export declare const makeRequireFile: (projectRoot: string) => (v: string) => void; export declare const extractVals: (val: any) => { @@ -17,7 +14,7 @@ export declare const extractVals: (val: any) => { export declare const makeHandleAsyncReporters: (reporterRets: any[]) => (cb: Function) => any; export declare const makeRunGenerator: (fn: Function, ctx: any) => () => Promise; export declare const asyncHelper: (key: string, resolve: Function, reject: Function, $args: any[], ln: number, fn: Function) => any; -export declare const implementationError: (err: IPseudoError, isThrow: boolean) => void; +export declare const implementationError: (err: IPseudoError, isThrow?: boolean) => void; export declare const loadSumanConfig: (configPath: string, opts: Object) => any; export declare const resolveSharedDirs: (sumanConfig: ISumanConfig, projectRoot: string, sumanOpts: ISumanOpts) => any; export declare const loadSharedObjects: (pathObj: Object, projectRoot: string, sumanOpts: ISumanOpts) => any; @@ -25,7 +22,7 @@ export declare const vetPaths: (paths: string[]) => void; export declare const fatalRequestReply: (obj: Object, $cb: Function) => any; export declare const findSumanServer: (serverName?: string) => ISumanServerInfo; export declare const makeOnSumanCompleted: (suman: Suman) => (code: number, msg: string) => void; -export declare const cloneError: ICloneErrorFn; +export declare const cloneError: (err: Error, newMessage: string, strip?: boolean) => IPseudoError; export declare const parseArgs: (args: any[], fnIsRequired?: boolean) => { arrayDeps: IAllOpts[]; args: any[]; diff --git a/lib/helpers/general.js b/lib/helpers/general.js index 6ef6c0b3..3c23a46a 100755 --- a/lib/helpers/general.js +++ b/lib/helpers/general.js @@ -228,7 +228,7 @@ exports.asyncHelper = function (key, resolve, reject, $args, ln, fn) { }; exports.implementationError = function (err, isThrow) { if (err) { - err = new Error(' => Suman implementation error => Please report!' + '\n' + (err.stack || err)); + err = new Error('Suman implementation error => Please report!' + '\n' + (err.stack || err)); _suman.log.error(err.stack); _suman.writeTestError(err.stack); if (isThrow) { @@ -602,11 +602,11 @@ exports.makeOnSumanCompleted = function (suman) { }); }; }; -exports.cloneError = function (err, newMessage, stripAllButTestFilePathMatch) { +exports.cloneError = function (err, newMessage, strip) { var obj = {}; obj.message = newMessage || "Suman implementation error: \"newMessage\" is not defined. Please report: " + suman_constants_1.constants.SUMAN_ISSUE_TRACKER_URL + "."; var temp; - if (stripAllButTestFilePathMatch !== false) { + if (strip !== false) { temp = su.createCleanStack(String(err.stack || err)); } else { diff --git a/lib/helpers/general.ts b/lib/helpers/general.ts index eb2ce0fd..97459955 100755 --- a/lib/helpers/general.ts +++ b/lib/helpers/general.ts @@ -46,12 +46,6 @@ const rb = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); import {getClient} from '../index-helpers/socketio-child-client'; const fnArgs = require('function-arguments'); -////////////////////////////////////////////////////////////////////////////// - -export interface ICloneErrorFn { - (err: Error, newMessage: string, stripAllButTestFilePathMatch?: boolean): IPseudoError -} - /////////////////////////////////////////////////////////////////////////////////////////////////// export const handleSetupComplete = function (test: ITestSuite, type: string) { @@ -299,9 +293,9 @@ export const asyncHelper = }; -export const implementationError = function (err: IPseudoError, isThrow: boolean) { +export const implementationError = function (err: IPseudoError, isThrow?: boolean) { if (err) { - err = new Error(' => Suman implementation error => Please report!' + '\n' + (err.stack || err)); + err = new Error('Suman implementation error => Please report!' + '\n' + (err.stack || err)); _suman.log.error(err.stack); _suman.writeTestError(err.stack); if (isThrow) { @@ -810,19 +804,19 @@ export const makeOnSumanCompleted = function (suman: ISuman) { }; }; -export const cloneError: ICloneErrorFn = function (err, newMessage, stripAllButTestFilePathMatch) { +export const cloneError = function (err: Error, newMessage: string, strip?: boolean) { const obj = {} as IPseudoError; obj.message = newMessage || `Suman implementation error: "newMessage" is not defined. Please report: ${constants.SUMAN_ISSUE_TRACKER_URL}.`; let temp; - if (stripAllButTestFilePathMatch !== false) { + if (strip !== false) { temp = su.createCleanStack(String(err.stack || err)); } else { temp = String(err.stack || err).split('\n'); } - temp[0] = newMessage; + temp[0] = newMessage; obj.message = newMessage; obj.stack = temp.join('\n'); return obj; diff --git a/lib/helpers/load-reporters-last-ditch.js b/lib/helpers/load-reporters-last-ditch.js index 74d1a7fd..5852b641 100755 --- a/lib/helpers/load-reporters-last-ditch.js +++ b/lib/helpers/load-reporters-last-ditch.js @@ -25,11 +25,11 @@ var loadReporter = function (rpath) { catch (err) { fullPath = require.resolve(path.resolve(_suman.projectRoot + '/' + rpath)); } - var fn_1 = require(fullPath); - fn_1 = getReporterFn(fn_1); - assert(typeof fn_1 === 'function', 'Suman implementation error - reporter module format fail.'); - fn_1.reporterPath = fullPath; - return fn_1; + var fn = require(fullPath); + fn = getReporterFn(fn); + assert(typeof fn === 'function', 'Suman implementation error - reporter module format fail.'); + fn.reporterPath = fullPath; + return fn; } catch (err) { _suman.log.error("could not load reporter at path \"" + rpath + "\"."); diff --git a/lib/helpers/load-reporters.js b/lib/helpers/load-reporters.js index e5353732..d940ac8d 100755 --- a/lib/helpers/load-reporters.js +++ b/lib/helpers/load-reporters.js @@ -54,11 +54,11 @@ exports.loadReporters = function (sumanOpts, projectRoot, sumanConfig) { catch (err) { fullPath = require.resolve(path.resolve(projectRoot + '/' + rpath)); } - var fn_1 = require(fullPath); - fn_1 = getReporterFn(fn_1); - assert(typeof fn_1 === 'function', ' (Supposed) reporter module does not export a function, at path = "' + rpath + '"'); - fn_1.reporterPath = fullPath; - sumanReporterFns.push(fn_1); + var fn = require(fullPath); + fn = getReporterFn(fn); + assert(typeof fn === 'function', ' (Supposed) reporter module does not export a function, at path = "' + rpath + '"'); + fn.reporterPath = fullPath; + sumanReporterFns.push(fn); return true; } catch (err) { @@ -108,8 +108,8 @@ exports.loadReporters = function (sumanOpts, projectRoot, sumanConfig) { } else { if (!loadReporterViaPath(item)) { - var p = path.resolve('/suman-reporters/modules/' + item).substr(1); - loadReporterViaPath(p); + var p_1 = path.resolve('/suman-reporters/modules/' + item).substr(1); + loadReporterViaPath(p_1); } } }); diff --git a/lib/helpers/run-after-always.js b/lib/helpers/run-after-always.js index 410b236d..78aebed3 100755 --- a/lib/helpers/run-after-always.js +++ b/lib/helpers/run-after-always.js @@ -8,8 +8,7 @@ var async = require("async"); var suman_utils_1 = require("suman-utils"); var helpers = require('../test-suite-helpers/handle-promise-generator'); var general_1 = require("./general"); -var t_proto_hook_1 = require("../test-suite-helpers/t-proto-hook"); -var freeze_existing_props_1 = require("freeze-existing-props"); +var all_hook_param_1 = require("../test-suite-params/all-hook/all-hook-param"); var suman_constants_1 = require("../../config/suman-constants"); var _suman = global.__suman = (global.__suman || {}); exports.runAfterAlways = function (suman, cb) { @@ -84,7 +83,7 @@ exports.runAfterAlways = function (suman, cb) { err = err ? ('Also, you have this error => ' + err.stack || err) : ''; handleError(new Error('Callback mode for this test-case/hook is not enabled, use .cb to enabled it.\n' + err)); } - var t = t_proto_hook_1.makeHookObj(anAfter, assertCount, handleError); + var t = new all_hook_param_1.AllHookParam(anAfter, assertCount, handleError, fini); fini.thot = t; t.timeout = timeout; t.fatal = function fatal(err) { @@ -94,7 +93,7 @@ exports.runAfterAlways = function (suman, cb) { var arg; if (isGeneratorFn) { var handleGenerator = helpers.makeHandleGenerator(fini); - arg = [freeze_existing_props_1.freezeExistingProps(t)]; + arg = t; handleGenerator(anAfter.fn, arg, anAfter.ctx); } else if (anAfter.cb) { @@ -123,14 +122,14 @@ exports.runAfterAlways = function (suman, cb) { fini(null, false); } }; - arg = Object.setPrototypeOf(d_1, freeze_existing_props_1.freezeExistingProps(t)); + arg = Object.setPrototypeOf(d_1, t); if (anAfter.fn.call(anAfter.ctx, arg)) { _suman.writeTestError(general_1.cloneError(anAfter.warningErr, suman_constants_1.constants.warnings.RETURNED_VAL_DESPITE_CALLBACK_MODE, true).stack); } } else { var handlePotentialPromise = helpers.handleReturnVal(fini, fnStr); - arg = freeze_existing_props_1.freezeExistingProps(t); + arg = t; handlePotentialPromise(anAfter.fn.call(anAfter.ctx, arg), warn); } }); diff --git a/lib/helpers/run-after-always.ts b/lib/helpers/run-after-always.ts index a6fc556d..1d35ce28 100755 --- a/lib/helpers/run-after-always.ts +++ b/lib/helpers/run-after-always.ts @@ -21,7 +21,8 @@ import su from 'suman-utils'; const helpers = require('../test-suite-helpers/handle-promise-generator'); import {cloneError} from './general'; -import {makeHookObj} from '../test-suite-helpers/t-proto-hook'; +// import {makeHookParam} from '../test-suite-helpers/t-proto-hook'; +import {AllHookParam} from '../test-suite-params/all-hook/all-hook-param'; import {freezeExistingProps} from 'freeze-existing-props' import {constants} from '../../config/suman-constants'; @@ -136,7 +137,7 @@ export const runAfterAlways = function (suman: ISuman, cb: Function) { handleError(new Error('Callback mode for this test-case/hook is not enabled, use .cb to enabled it.\n' + err)); } - const t = makeHookObj(anAfter, assertCount, handleError); + const t = new AllHookParam(anAfter, assertCount, handleError, fini); fini.thot = t; t.timeout = timeout; @@ -149,7 +150,8 @@ export const runAfterAlways = function (suman: ISuman, cb: Function) { if (isGeneratorFn) { const handleGenerator = helpers.makeHandleGenerator(fini); - arg = [freezeExistingProps(t)]; + // arg = [freezeExistingProps(t)]; + arg = t; handleGenerator(anAfter.fn, arg, anAfter.ctx); } else if (anAfter.cb) { @@ -184,7 +186,8 @@ export const runAfterAlways = function (suman: ISuman, cb: Function) { }; - arg = Object.setPrototypeOf(d, freezeExistingProps(t)); + // arg = Object.setPrototypeOf(d, freezeExistingProps(t)); + arg = Object.setPrototypeOf(d, t); if (anAfter.fn.call(anAfter.ctx, arg)) { //check to see if we have a defined return value _suman.writeTestError(cloneError(anAfter.warningErr, @@ -194,7 +197,8 @@ export const runAfterAlways = function (suman: ISuman, cb: Function) { } else { const handlePotentialPromise = helpers.handleReturnVal(fini, fnStr); - arg = freezeExistingProps(t); + // arg = freezeExistingProps(t); + arg =t; handlePotentialPromise(anAfter.fn.call(anAfter.ctx, arg), warn); } diff --git a/lib/index.d.ts b/lib/index.d.ts index df24886a..14393f03 100755 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -1,14 +1,13 @@ import { IInitFn } from "suman-types/dts/index-init"; -import { IHookOrTestCaseParam } from "suman-types/dts/test-suite"; import * as s from './s'; export { s }; import sumanRun = require('./helpers/suman-run'); import { ISumanRunFn } from "./helpers/suman-run"; export declare const init: IInitFn; -export declare const autoPass: (t: IHookOrTestCaseParam) => void; -export declare const autoFail: (t: IHookOrTestCaseParam) => Promise; +export declare const autoPass: (t: any) => void; +export declare const autoFail: (t: any) => Promise; export declare const run: sumanRun.ISumanRunFn; -export declare const once: any; +export declare const once: (fn: Function) => (cb: Function) => void; export declare const version: any; export interface ISumanExports { s: typeof s; diff --git a/lib/index.js b/lib/index.js index 377f9c01..4aea7781 100755 --- a/lib/index.js +++ b/lib/index.js @@ -161,6 +161,10 @@ exports.init = function ($module, $opts, sumanOptsOverride, confOverride) { if (initMap.get($module)) { return initMap.get($module); } + if ($module.sumanInitted) { + throw new Error("suman.init() already called for this module with filename => " + $module.filename); + } + $module.sumanInitted = true; if (typeof _suman.sumanConfig === 'string') { _suman.sumanConfig = JSON.parse(_suman.sumanConfig); } @@ -207,26 +211,35 @@ exports.init = function ($module, $opts, sumanOptsOverride, confOverride) { if (String(k).trim().startsWith('$')) { throw new Error('Suman options override object key must not start with "$" character.'); } - sumanOptsOverride['$' + String(k).trim()] = sumanOptsOverride[k]; - delete sumanOptsOverride[k]; + _sumanOpts['$' + String(k).trim()] = sumanOptsOverride[k]; }); - _sumanOpts = Object.assign(_suman.sumanOpts, sumanOptsOverride, _suman.sumanOpts); } if (confOverride) { - assert(su.isObject(confOverride), 'Suman conf override value must be a plain object.'); + assert(su.isObject(confOverride), 'Suman config override value must be a plain object.'); _sumanConfig = Object.assign({}, _suman.sumanConfig, confOverride); } - _suman.sumanInitStartDate = (_suman.sumanInitStartDate || Date.now()); + _suman.sumanInitStartDate = _suman.sumanInitStartDate || Date.now(); if (!loaded) { } if ($opts) { assert(su.isObject($opts), 'Please pass an options object as a second argument to suman.init()'); } var opts = $opts || {}; - if ($module.sumanInitted) { - throw new Error("suman.init() already called for this module with filename => " + $module.filename); + if (opts.override) { + if (opts.override.config) { + assert(su.isObject(opts.override.config), 'config override value must be a plain object.'); + _sumanConfig = Object.assign({}, _suman.sumanConfig, opts.override.config); + } + if (opts.override.opts) { + assert(su.isObject(opts.override.opts), 'opts override value must be a plain object.'); + Object.keys(opts.override.opts).forEach(function (k) { + if (String(k).trim().startsWith('$')) { + throw new Error('Suman options override object key must not start with "$" character.'); + } + _sumanOpts['$' + String(k).trim()] = opts.override.opts[k]; + }); + } } - $module.sumanInitted = true; opts.integrants && assert(Array.isArray(opts.integrants), "'integrants' option must be an array."); opts.pre && assert(Array.isArray(opts.pre), "'pre' option must be an array."); var $integrants = (opts.integrants || opts.pre || []).filter(function (i) { return i; }).map(function (item) { diff --git a/lib/index.ts b/lib/index.ts index 3e018037..72ae17e0 100755 --- a/lib/index.ts +++ b/lib/index.ts @@ -240,6 +240,12 @@ export const init: IInitFn = function ($module, $opts, sumanOptsOverride, confOv return initMap.get($module) as any; } + if ($module.sumanInitted) { + throw new Error(`suman.init() already called for this module with filename => ${$module.filename}`); + } + + $module.sumanInitted = true; + if (typeof _suman.sumanConfig === 'string') { _suman.sumanConfig = JSON.parse(_suman.sumanConfig); } @@ -297,21 +303,21 @@ export const init: IInitFn = function ($module, $opts, sumanOptsOverride, confOv if (String(k).trim().startsWith('$')) { throw new Error('Suman options override object key must not start with "$" character.'); } - sumanOptsOverride['$' + String(k).trim()] = sumanOptsOverride[k]; - delete sumanOptsOverride[k]; + _sumanOpts['$' + String(k).trim()] = sumanOptsOverride[k]; }); // this is correct, although it seems wrong given that sumanOpts is referenced twice // we need to keep the reference to _suman.sumanOpts, instead of reassigning - _sumanOpts = Object.assign(_suman.sumanOpts, sumanOptsOverride, _suman.sumanOpts); + // _sumanOpts = Object.assign(_suman.sumanOpts, sumanOptsOverride, _suman.sumanOpts); + // _sumanOpts = Object.assign(_suman.sumanOpts, sumanOptsOverride); } if (confOverride) { - assert(su.isObject(confOverride), 'Suman conf override value must be a plain object.'); + assert(su.isObject(confOverride), 'Suman config override value must be a plain object.'); _sumanConfig = Object.assign({}, _suman.sumanConfig, confOverride); } - _suman.sumanInitStartDate = (_suman.sumanInitStartDate || Date.now()); + _suman.sumanInitStartDate = _suman.sumanInitStartDate || Date.now(); // TODO: could potention figure out what original test module is via suman.init call, instead of // requiring that user pass it explicitly @@ -327,11 +333,23 @@ export const init: IInitFn = function ($module, $opts, sumanOptsOverride, confOv } const opts: IInitOpts = $opts || {}; - if ($module.sumanInitted) { - throw new Error(`suman.init() already called for this module with filename => ${$module.filename}`); - } - $module.sumanInitted = true; + if(opts.override){ + if(opts.override.config){ + assert(su.isObject(opts.override.config),'config override value must be a plain object.'); + _sumanConfig = Object.assign({}, _suman.sumanConfig, opts.override.config); + } + if(opts.override.opts){ + assert(su.isObject(opts.override.opts), 'opts override value must be a plain object.'); + Object.keys(opts.override.opts).forEach(function (k) { + if (String(k).trim().startsWith('$')) { + throw new Error('Suman options override object key must not start with "$" character.'); + } + _sumanOpts['$' + String(k).trim()] = opts.override.opts[k]; + }); + } + } + opts.integrants && assert(Array.isArray(opts.integrants), `'integrants' option must be an array.`); opts.pre && assert(Array.isArray(opts.pre), `'pre' option must be an array.`); @@ -487,7 +505,6 @@ export const init: IInitFn = function ($module, $opts, sumanOptsOverride, confOv } return defObj; - } }; diff --git a/lib/injection/helpers.js b/lib/injection/helpers.js index e8f1200d..71b7345f 100755 --- a/lib/injection/helpers.js +++ b/lib/injection/helpers.js @@ -7,7 +7,7 @@ var constants = require('../../config/suman-constants').constants; var values = null; exports.getCoreAndDeps = function () { if (!values) { - var p = new Proxy({}, { + var p_1 = new Proxy({}, { get: function (target, prop) { var trimmed = String(prop).trim(); try { @@ -26,9 +26,9 @@ exports.getCoreAndDeps = function () { } }); values = { - $core: p, - $deps: p, - $require: p + $core: p_1, + $deps: p_1, + $require: p_1 }; } return values; diff --git a/lib/make-graceful-exit.js b/lib/make-graceful-exit.js index 8ab5e82b..50ac2004 100755 --- a/lib/make-graceful-exit.js +++ b/lib/make-graceful-exit.js @@ -2,6 +2,7 @@ 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 async = require("async"); var chalk = require("chalk"); @@ -37,16 +38,22 @@ exports.makeGracefulExit = function (suman) { } var big = errs.filter(function (err) { if (err && err.isFromTest && !_suman.sumanOpts.bail) { - return undefined; + _suman.log.warning('The following error will be ignored because it was a test case error and bail is not true.'); + _suman.log.warning(err.stack || util.inspect(err)); + return false; } else if (err && err.sumanFatal === false) { - return undefined; + _suman.log.warning('The following error will be ignored because "sumanFatal" was set to false.'); + _suman.log.warning(err.stack || util.inspect(err)); + return false; } else if (err) { return true; } else { - return undefined; + _suman.log.warning('An error will be ignored because it is falsy:'); + _suman.log.warning(util.inspect(err)); + return false; } }) .map(function (err) { diff --git a/lib/make-graceful-exit.ts b/lib/make-graceful-exit.ts index 999c9660..519c4ae4 100755 --- a/lib/make-graceful-exit.ts +++ b/lib/make-graceful-exit.ts @@ -62,18 +62,24 @@ export const makeGracefulExit = function (suman: ISuman) { const big = errs.filter(function (err) { if (err && err.isFromTest && !_suman.sumanOpts.bail) { - return undefined; //explicit for your pleasure + _suman.log.warning('The following error will be ignored because it was a test case error and bail is not true.'); + _suman.log.warning(err.stack || util.inspect(err)); + return false; } else if (err && err.sumanFatal === false) { - return undefined; //explicit for your pleasure + _suman.log.warning('The following error will be ignored because "sumanFatal" was set to false.'); + _suman.log.warning(err.stack || util.inspect(err)); + return false; } else if (err) { //explicit for your pleasure return true; } else { + _suman.log.warning('An error will be ignored because it is falsy:'); + _suman.log.warning(util.inspect(err)); //explicit for your pleasure - return undefined; + return false; } }) .map(function (err: IPseudoError) { diff --git a/lib/runner-helpers/browser/add-to-run-queue.js b/lib/runner-helpers/browser/add-to-run-queue.js index 13ed8e3b..dd9c5490 100755 --- a/lib/runner-helpers/browser/add-to-run-queue.js +++ b/lib/runner-helpers/browser/add-to-run-queue.js @@ -9,7 +9,7 @@ var su = require("suman-utils"); var suman_events_1 = require("suman-events"); var _suman = global.__suman = (global.__suman || {}); var prepend_transform_1 = require("prepend-transform"); -var uuidV4 = require("uuid/v4"); +var uuid = require("uuid"); var suman_constants_1 = require("../../../config/suman-constants"); var runChildPath = require.resolve(__dirname + '/../run-child.js'); var rb = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); @@ -45,7 +45,7 @@ exports.makeAddToRunQueue = function (runnerObj, args, runQueue, projectRoot, cp var n, hashbang = false; var extname = path.extname(shortFile); var $childId = childId++; - var childUuid = uuidV4(); + var childUuid = uuid.v4(); var inherit = sumanOpts.$forceInheritStdio ? 'inherit' : ''; if (inherit) { _suman.log.info('we are inheriting stdio of child, because of sumanception.'); diff --git a/lib/runner-helpers/browser/add-to-run-queue.ts b/lib/runner-helpers/browser/add-to-run-queue.ts index c356f14a..fd1dec65 100755 --- a/lib/runner-helpers/browser/add-to-run-queue.ts +++ b/lib/runner-helpers/browser/add-to-run-queue.ts @@ -28,8 +28,7 @@ import {events} from 'suman-events'; const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); import {getTapParser,getTapJSONParser} from '../handle-tap'; import pt from 'prepend-transform'; -import uuidV4 = require('uuid/v4'); -import {findPathOfRunDotSh} from '../runner-utils' +import uuid = require('uuid'); import {constants} from "../../../config/suman-constants"; const runChildPath = require.resolve(__dirname + '/../run-child.js'); const rb = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); @@ -80,7 +79,7 @@ export const makeAddToRunQueue = function (runnerObj: Object, args: Array>) { - const uuid = String(uuidV4()); + const uuidV4 = String(uuid.v4()); const file = fileShortAndFull[0]; const shortFile = fileShortAndFull[1]; const filePathFromProjectRoot = fileShortAndFull[2]; @@ -65,8 +65,8 @@ export const makeAddToTranspileQueue = function (f: string, transpileQueue: Asyn } }; - const gd = ganttHash[uuid] = { - uuid: uuid, + const gd = ganttHash[uuidV4] = { + uuid: uuidV4, fullFilePath: String(file), shortFilePath: String(shortFile), filePathFromProjectRoot: String(filePathFromProjectRoot), diff --git a/lib/runner-helpers/coverage-reporting.ts b/lib/runner-helpers/coverage-reporting.ts index 20f8cdc6..1ccbd137 100755 --- a/lib/runner-helpers/coverage-reporting.ts +++ b/lib/runner-helpers/coverage-reporting.ts @@ -32,7 +32,10 @@ export const handleTestCoverageReporting = function (cb: Function) { _suman.log.info(chalk.blue.bold('Suman is running the Istanbul collated report.')); _suman.log.info(chalk.blue.bold('To disable automatic report generation, use "--no-coverage-report".')); const coverageDir = path.resolve(_suman.projectRoot + '/coverage/suman_by_timestamp/' + _suman.timestamp); + + const args = ['report', '--dir', coverageDir, '--include', '**/*coverage.json', 'lcov']; + // const args = ['report', '--dir', coverageDir, '--include', '**/*coverage.json']; const k = cp.spawn(_suman.istanbulExecPath || 'istanbul', args, { cwd: _suman.projectRoot diff --git a/lib/runner-helpers/handle-containerize.js b/lib/runner-helpers/handle-containerize.js index f98be90d..dc42f82c 100755 --- a/lib/runner-helpers/handle-containerize.js +++ b/lib/runner-helpers/handle-containerize.js @@ -13,7 +13,7 @@ var async = require("async"); var noFilesFoundError = require('../helpers/no-files-found-error'); var chalk = require("chalk"); var _suman = global.__suman = (global.__suman || {}); -var runnerUtils = require('./runner-utils'); +var ru = require("./runner-utils"); var resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); var prepend_transform_1 = require("prepend-transform"); exports.makeContainerize = function (runnerObj, tableRows, messages, forkedCPs, handleMessage, beforeExitRunOncePost, makeExit) { @@ -102,7 +102,7 @@ exports.makeContainerize = function (runnerObj, tableRows, messages, forkedCPs, SUITES_DESIGNATOR: basename } }; - var tr = runnerUtils.findPathOfTransformDotSh(file); + var tr = ru.findPathOfTransformDotSh(file); if (tr) { transpileQueue.push(function (cb) { suman_utils_1.default.makePathExecutable(tr, function (err) { diff --git a/lib/runner-helpers/handle-containerize.ts b/lib/runner-helpers/handle-containerize.ts index 2e773fb1..3838cf2b 100755 --- a/lib/runner-helpers/handle-containerize.ts +++ b/lib/runner-helpers/handle-containerize.ts @@ -26,7 +26,7 @@ import * as chalk from 'chalk'; //project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); -const runnerUtils = require('./runner-utils'); +import * as ru from './runner-utils'; const resultBroadcaster = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); import {pt} from 'prepend-transform'; @@ -164,7 +164,7 @@ export const makeContainerize = } }; - const tr = runnerUtils.findPathOfTransformDotSh(file); + const tr = ru.findPathOfTransformDotSh(file); if (tr) { diff --git a/lib/runner-helpers/handle-multiple-processes.ts b/lib/runner-helpers/handle-multiple-processes.ts index 2f2425c3..4c1ed591 100755 --- a/lib/runner-helpers/handle-multiple-processes.ts +++ b/lib/runner-helpers/handle-multiple-processes.ts @@ -58,7 +58,6 @@ export const makeHandleMultipleProcesses = function (runnerObj: IRunnerObj, tabl const logsDir = _suman.sumanConfig.logsDir || _suman.sumanHelperDirRoot + '/logs'; const sumanCPLogs = path.resolve(logsDir + '/runs/'); const f = path.resolve(sumanCPLogs + '/' + _suman.timestamp + '-' + _suman.runId); - const args: Array = ['--user-args', sumanOpts.user_args]; const runQueue = makeRunQueue(); const onExitFn = makeOnExitFn(runnerObj, tableRows, messages, forkedCPs, beforeExitRunOncePost, makeExit, runQueue); diff --git a/lib/runner-helpers/multi-process/handle-different-executables.js b/lib/runner-helpers/multi-process/handle-different-executables.js index d267ddcf..868f0a8e 100644 --- a/lib/runner-helpers/multi-process/handle-different-executables.js +++ b/lib/runner-helpers/multi-process/handle-different-executables.js @@ -8,6 +8,7 @@ var cp = require("child_process"); var fs = require("fs"); var chalk = require("chalk"); var semver = require("semver"); +var su = require("suman-utils"); var _suman = global.__suman = (global.__suman || {}); exports.makeHandleDifferentExecutables = function (projectRoot, sumanOpts, runnerObj) { var execFile = path.resolve(__dirname + '/../run-child.js'); @@ -104,7 +105,7 @@ exports.makeHandleDifferentExecutables = function (projectRoot, sumanOpts, runne if (sumanOpts.coverage) { var coverageDir = path.resolve(_suman.projectRoot + '/coverage/suman_by_timestamp/' + _suman.timestamp + '/suman_by_process/' + String(shortFile).replace(/\//g, '-')); - var argzz = ['cover', execFile, '--dir', coverageDir, '--'].concat(argz); + var argzz = ['cover', execFile, '--report=json', '--dir', coverageDir, '--'].concat(argz); n = cp.spawn(istanbulExecPath, argzz, cpOptions); } else if (hasHasbang && !hashbangIsNode) { @@ -115,7 +116,11 @@ exports.makeHandleDifferentExecutables = function (projectRoot, sumanOpts, runne _suman.log.info(); _suman.log.info("perl bash python or ruby file? '" + chalk.magenta(file) + "'"); if (!isExecutable) { - _suman.log.warning('warning: file may not be executable: ', file); + console.error('\n'); + _suman.log.warning("Warning: test file with the following path may not be executable:"); + _suman.log.warning(chalk.magenta(file)); + su.vgt(6) && _suman.log.warning('fs.Stats for this file were:\n', util.inspect(stats)); + console.error(); } n = cp.spawn('bash', [], cpOptions); n.usingHashbang = true; @@ -158,34 +163,20 @@ exports.makeHandleDifferentExecutables = function (projectRoot, sumanOpts, runne } } else { - var onSpawnError = function (err) { - if (err && String(err.message).match(/EACCES/i)) { - _suman.log.warning(); - _suman.log.warning("Test file with the following path may not be executable, or does not have the right permissions:"); - _suman.log.warning(chalk.magenta(file)); - _suman.log.warning(chalk.gray('fs.Stats for this file were:'), util.inspect(stats)); - } - else if (err) { - _suman.log.error(err.message || err); - } - }; - _suman.log.info(); - _suman.log.info("perl bash python or ruby file? '" + chalk.magenta(file) + "'"); - try { - n = cp.spawn(file, argz, cpOptions); - n.usingHashbang = true; - } - catch (err) { - onSpawnError(err); - return cb(err, n); - } if (!isExecutable) { - n.once('error', function () { - _suman.log.warning("Test file with the following path may not be executable:"); - _suman.log.warning(chalk.magenta(file)); - _suman.log.warning('fs.Stats for this file were:\n', util.inspect(stats)); - }); + console.error('\n'); + _suman.log.warning("Warning: Test file with the following path may not be executable:"); + _suman.log.warning(chalk.magenta(file)); + su.vgt(6) && _suman.log.warning('fs.Stats for this file were:\n', util.inspect(stats)); + console.error(); + } + if (su.vgt(5)) { + _suman.log.info(); + _suman.log.info("perl bash python or ruby file? '" + chalk.magenta(file) + "'"); } + n = cp.spawn('bash', [], cpOptions); + n.stdin.end("\n" + file + " " + argz.join(' ') + ";\n"); + n.usingHashbang = true; } cb(null, n); }); diff --git a/lib/runner-helpers/multi-process/handle-different-executables.ts b/lib/runner-helpers/multi-process/handle-different-executables.ts index acffab14..315c27da 100644 --- a/lib/runner-helpers/multi-process/handle-different-executables.ts +++ b/lib/runner-helpers/multi-process/handle-different-executables.ts @@ -177,13 +177,14 @@ export const makeHandleDifferentExecutables = function (projectRoot: string, sum let coverageDir = path.resolve(_suman.projectRoot + '/coverage/suman_by_timestamp/' + _suman.timestamp + '/suman_by_process/' + String(shortFile).replace(/\//g, '-')); - let argzz = ['cover', execFile, '--dir', coverageDir, '--'].concat(argz); + let argzz = ['cover', execFile, '--report=json', '--dir', coverageDir, '--'].concat(argz); //'--include-all-sources' n = cp.spawn(istanbulExecPath, argzz, cpOptions) as ISumanChildProcess; } else if (hasHasbang && !hashbangIsNode) { + _suman.log.warning(); _suman.log.warning('The following file has a ".js" extension but appears to have a hashbang which is not the node executable:'); _suman.log.warning('Hashbang: ', firstLine); @@ -194,7 +195,11 @@ export const makeHandleDifferentExecutables = function (projectRoot: string, sum _suman.log.info(`perl bash python or ruby file? '${chalk.magenta(file)}'`); if (!isExecutable) { - _suman.log.warning('warning: file may not be executable: ', file); + console.error('\n'); + _suman.log.warning(`Warning: test file with the following path may not be executable:`); + _suman.log.warning(chalk.magenta(file)); + su.vgt(6) && _suman.log.warning('fs.Stats for this file were:\n', util.inspect(stats)); + console.error(); } n = cp.spawn('bash', [], cpOptions) as ISumanChildProcess; @@ -253,38 +258,24 @@ export const makeHandleDifferentExecutables = function (projectRoot: string, sum } else { - let onSpawnError = function (err: Error) { - if (err && String(err.message).match(/EACCES/i)) { - _suman.log.warning(); - _suman.log.warning(`Test file with the following path may not be executable, or does not have the right permissions:`); - _suman.log.warning(chalk.magenta(file)); - _suman.log.warning(chalk.gray('fs.Stats for this file were:'), util.inspect(stats)); - } - else if (err) { - _suman.log.error(err.message || err); - } - }; + if (!isExecutable) { + console.error('\n'); + _suman.log.warning(`Warning: Test file with the following path may not be executable:`); + _suman.log.warning(chalk.magenta(file)); + su.vgt(6) && _suman.log.warning('fs.Stats for this file were:\n', util.inspect(stats)); + console.error(); + } // .sh .bash .py, perl, ruby, etc - _suman.log.info(); - _suman.log.info(`perl bash python or ruby file? '${chalk.magenta(file)}'`); - - try { - n = cp.spawn(file, argz, cpOptions) as ISumanChildProcess; - n.usingHashbang = true; - } - catch (err) { - onSpawnError(err); - return cb(err, n); + if(su.vgt(5)){ + _suman.log.info(); + _suman.log.info(`perl bash python or ruby file? '${chalk.magenta(file)}'`); } - if (!isExecutable) { - n.once('error', function () { - _suman.log.warning(`Test file with the following path may not be executable:`); - _suman.log.warning(chalk.magenta(file)); - _suman.log.warning('fs.Stats for this file were:\n', util.inspect(stats)); - }); - } + // n = cp.spawn(file, argz, cpOptions) as ISumanChildProcess; + n = cp.spawn('bash', [], cpOptions) as ISumanChildProcess; + n.stdin.end(`\n${file} ${argz.join(' ')};\n`); + n.usingHashbang = true; } cb(null, n); diff --git a/lib/runner-helpers/multiple-process-each-on-exit.js b/lib/runner-helpers/multiple-process-each-on-exit.js index 089ec3e8..fa1cfd9e 100755 --- a/lib/runner-helpers/multiple-process-each-on-exit.js +++ b/lib/runner-helpers/multiple-process-each-on-exit.js @@ -13,7 +13,6 @@ var async = require("async"); var noFilesFoundError = require('../helpers/no-files-found-error'); var chalk = require("chalk"); var _suman = global.__suman = (global.__suman || {}); -var runnerUtils = require('./runner-utils'); var coverage_reporting_1 = require("./coverage-reporting"); var constants = require('../../config/suman-constants').constants; var queues_1 = require("./shared/queues"); diff --git a/lib/runner-helpers/multiple-process-each-on-exit.ts b/lib/runner-helpers/multiple-process-each-on-exit.ts index f6b14814..55d130dd 100755 --- a/lib/runner-helpers/multiple-process-each-on-exit.ts +++ b/lib/runner-helpers/multiple-process-each-on-exit.ts @@ -28,7 +28,6 @@ import {IGanttData} from "./socket-cp-hash"; //project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); -const runnerUtils = require('./runner-utils'); import {handleTestCoverageReporting} from './coverage-reporting'; const {constants} = require('../../config/suman-constants'); import {getTranspileQueue, getRunQueue} from './shared/queues'; diff --git a/lib/runner-helpers/run-child.js b/lib/runner-helpers/run-child.js index 8e9138ea..5308a7c5 100755 --- a/lib/runner-helpers/run-child.js +++ b/lib/runner-helpers/run-child.js @@ -99,6 +99,8 @@ var useTSNodeRegister = sumanOpts.$useTSNodeRegister; if (useTSNodeRegister) { _suman.log.warning(chalk.magenta(' => We are using ts-node-register.')); require('ts-node').register({ + allowJS: true, + allowJs: true, ignore: /node_modules/ }); } diff --git a/lib/runner-helpers/run-child.ts b/lib/runner-helpers/run-child.ts index 6c65aebb..23766eee 100755 --- a/lib/runner-helpers/run-child.ts +++ b/lib/runner-helpers/run-child.ts @@ -159,6 +159,8 @@ const useTSNodeRegister = sumanOpts.$useTSNodeRegister; if (useTSNodeRegister) { _suman.log.warning(chalk.magenta(' => We are using ts-node-register.')); require('ts-node').register({ + allowJS: true, + allowJs: true, // This will override `node_modules` ignoring - you can alternatively pass // an array of strings to be explicitly matched or a regex / glob ignore: /node_modules/ diff --git a/lib/runner-helpers/runner-utils.d.ts b/lib/runner-helpers/runner-utils.d.ts index 2360dd2d..50002c14 100755 --- a/lib/runner-helpers/runner-utils.d.ts +++ b/lib/runner-helpers/runner-utils.d.ts @@ -1,7 +1,10 @@ -export interface IFindShFunctions { - (p: string): string | null; +import { IAtConfig } from 'suman-types/dts/at-config'; +export interface IFindConfig { + 'config': IAtConfig; + 'runPath': string; } -export declare const findPathOfRunDotSh: IFindShFunctions; -export declare const findPathOfTransformDotSh: IFindShFunctions; +export declare const findPathOfRunDotSh: (p: string) => string; +export declare const findPathAndConfigOfRunDotSh: (p: string) => IFindConfig; +export declare const findPathOfTransformDotSh: (p: string) => string; declare const $exports: any; export default $exports; diff --git a/lib/runner-helpers/runner-utils.js b/lib/runner-helpers/runner-utils.js index 8601f42f..107f3b7a 100755 --- a/lib/runner-helpers/runner-utils.js +++ b/lib/runner-helpers/runner-utils.js @@ -40,7 +40,43 @@ exports.findPathOfRunDotSh = function (p) { } p = path.resolve(p + '/../'); } - return undefined; + return null; +}; +exports.findPathAndConfigOfRunDotSh = function (p) { + var ret = { + 'config': null, + 'runPath': null + }; + var root = _suman.projectRoot; + var ln = root.length; + while (p.length >= ln) { + var dirname = path.dirname(p); + var map = _suman.markersMap[dirname]; + if (map && map['@config.json']) { + try { + var v = void 0, config = require(path.resolve(dirname, '@config.json')); + if (v = config['@run']) { + if (v.prevent) { + _suman.log.warning('File with the following path was prevented from running with a setting in @config.json.'); + _suman.log.warning(p); + } + if (v.plugin && v.plugin.value) { + var plugin = require(v.plugin.value); + ret.runPath = plugin.getRunPath(); + } + else if (v.plugin) { + throw new Error('"plugin" should be an object with a "value" property.'); + } + } + } + catch (err) { + _suman.log.warning('Your @config.json file may be malformed at path: ', dirname); + _suman.log.error(err.message || err); + } + } + p = path.resolve(p + '/../'); + } + return ret; }; exports.findPathOfTransformDotSh = function (p) { if (String(p).match(/\/@target\//)) { @@ -56,8 +92,7 @@ exports.findPathOfTransformDotSh = function (p) { } if (map && map['@config.json']) { try { - var config = require(path.resolve(dirname, '@config.json')); - var v = void 0; + var v = void 0, config = require(path.resolve(dirname, '@config.json')); if (v = config['@transform']) { if (v.prevent) { return null; @@ -66,15 +101,19 @@ exports.findPathOfTransformDotSh = function (p) { var plugin = require(v.plugin.value); return plugin.getTransformPath(); } + else if (v.plugin) { + throw new Error('"plugin" should be an object with a "value" property.'); + } } } catch (err) { + _suman.log.warning('Your @config.json file may be malformed at path: ', dirname); _suman.log.error(err.message || err); } } p = path.resolve(p + '/../'); } - return undefined; + return null; }; var $exports = module.exports; exports.default = $exports; diff --git a/lib/runner-helpers/runner-utils.ts b/lib/runner-helpers/runner-utils.ts index 835c222c..567bb673 100755 --- a/lib/runner-helpers/runner-utils.ts +++ b/lib/runner-helpers/runner-utils.ts @@ -1,5 +1,8 @@ 'use strict'; +//dts +import {IAtConfig} from 'suman-types/dts/at-config'; + //polyfills const process = require('suman-browser-polyfills/modules/process'); const global = require('suman-browser-polyfills/modules/global'); @@ -8,35 +11,35 @@ const global = require('suman-browser-polyfills/modules/global'); import util = require('util'); import path = require('path'); - //project const _suman = global.__suman = (global.__suman || {}); -//////////////////////////////////////////////////// - -export interface IFindShFunctions { - (p: string): string | null +export interface IFindConfig { + 'config': IAtConfig, + 'runPath': string } -export const findPathOfRunDotSh: IFindShFunctions = function (p) { +//////////////////////////////////////////////////// +export const findPathOfRunDotSh = function (p: string) : string { + if(String(p).match(/\/@target\//)){ return null; } - + const root = _suman.projectRoot; const ln = root.length; - + while (p.length >= ln) { - + let dirname = path.dirname(p); let map = _suman.markersMap[dirname]; if (map && map['@run.sh']) { return path.resolve(dirname, '@run.sh'); } - + if (map && map['@config.json']) { - + try{ let config = require(path.resolve(dirname, '@config.json')); let v; @@ -59,64 +62,115 @@ export const findPathOfRunDotSh: IFindShFunctions = function (p) { _suman.log.error(err.message || err); } } - + p = path.resolve(p + '/../') - + } - + // explicit for your pleasure - return undefined; + return null; }; -export const findPathOfTransformDotSh: IFindShFunctions = function (p) { +export const findPathAndConfigOfRunDotSh = function (p: string): IFindConfig { + + const ret = { + 'config': null, + 'runPath': null + }; + + + const root = _suman.projectRoot; + const ln = root.length; + + while (p.length >= ln) { + + let dirname = path.dirname(p); + let map = _suman.markersMap[dirname]; + + if (map && map['@config.json']) { + + try { + let v, config = require(path.resolve(dirname, '@config.json')); + if (v = config['@run']) { + if (v.prevent) { + // user has decided to prevent running these files + _suman.log.warning('File with the following path was prevented from running with a setting in @config.json.'); + _suman.log.warning(p); + } + if (v.plugin && v.plugin.value) { + let plugin = require(v.plugin.value); + ret.runPath = plugin.getRunPath(); + } + else if (v.plugin) { + throw new Error('"plugin" should be an object with a "value" property.') + } + } + } + catch (err) { + _suman.log.warning('Your @config.json file may be malformed at path: ', dirname); + _suman.log.error(err.message || err); + } + } + + p = path.resolve(p + '/../') + + } + + // explicit for your pleasure + return ret; +}; - if(String(p).match(/\/@target\//)){ +export const findPathOfTransformDotSh = function (p: string): string | null { + + if (String(p).match(/\/@target\//)) { return null; } - + const root = _suman.projectRoot; const ln = root.length; - + while (p.length >= ln) { - + let dirname = path.dirname(p); let map = _suman.markersMap[dirname]; if (map && map['@transform.sh']) { return path.resolve(dirname, '@transform.sh'); } - + // @transform.sh file takes precedence over @config.json file in same dir if (map && map['@config.json']) { - - try{ - let config = require(path.resolve(dirname, '@config.json')); - let v; - if(v = config['@transform']){ - if(v.prevent){ + + try { + let v, config = require(path.resolve(dirname, '@config.json')); + if (v = config['@transform']) { + if (v.prevent) { // user has decided to prevent any transform for this file return null; } - if(v.plugin && v.plugin.value){ + if (v.plugin && v.plugin.value) { let plugin = require(v.plugin.value); return plugin.getTransformPath(); } + else if (v.plugin) { + throw new Error('"plugin" should be an object with a "value" property.') + } } } - catch(err){ + catch (err) { + _suman.log.warning('Your @config.json file may be malformed at path: ', dirname); _suman.log.error(err.message || err); } } - + p = path.resolve(p + '/../') - + } - + // explicit for your pleasure - return undefined; - + return null; + }; - const $exports = module.exports; export default $exports; diff --git a/lib/s.d.ts b/lib/s.d.ts index 4c973261..5f6e99a5 100644 --- a/lib/s.d.ts +++ b/lib/s.d.ts @@ -1,5 +1,8 @@ -export { ITestCaseParam, ITestSuite } from 'suman-types/dts/test-suite'; -export { IHookParam } from 'suman-types/dts/test-suite'; +export { InjectParam } from "../lib/test-suite-params/inject/inject-param"; +export { EachHookParam } from "../lib/test-suite-params/each-hook/each-hook-param"; +export { AllHookParam } from "../lib/test-suite-params/all-hook/all-hook-param"; +export { TestCaseParam } from "../lib/test-suite-params/test-case/test-case-param"; +export { ITestSuite } from 'suman-types/dts/test-suite'; export { ItFn, ITestDataObj } from 'suman-types/dts/it'; export { IDescribeFn, IDescribeOpts, TDescribeHook } from "suman-types/dts/describe"; export { IBeforeFn } from 'suman-types/dts/before'; diff --git a/lib/s.js b/lib/s.js index 211e0fd7..515632aa 100644 --- a/lib/s.js +++ b/lib/s.js @@ -1,5 +1,13 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +var inject_param_1 = require("../lib/test-suite-params/inject/inject-param"); +exports.InjectParam = inject_param_1.InjectParam; +var each_hook_param_1 = require("../lib/test-suite-params/each-hook/each-hook-param"); +exports.EachHookParam = each_hook_param_1.EachHookParam; +var all_hook_param_1 = require("../lib/test-suite-params/all-hook/all-hook-param"); +exports.AllHookParam = all_hook_param_1.AllHookParam; +var test_case_param_1 = require("../lib/test-suite-params/test-case/test-case-param"); +exports.TestCaseParam = test_case_param_1.TestCaseParam; var define_options_classes_1 = require("./test-suite-helpers/define-options-classes"); exports.DefineObject = define_options_classes_1.DefineObject; var define_options_classes_2 = require("./test-suite-helpers/define-options-classes"); diff --git a/lib/s.ts b/lib/s.ts index 4d457c91..48a5afaa 100644 --- a/lib/s.ts +++ b/lib/s.ts @@ -3,8 +3,11 @@ import chai = require('chai'); import AssertStatic = Chai.AssertStatic; -export {ITestCaseParam, ITestSuite} from 'suman-types/dts/test-suite'; -export {IHookParam} from 'suman-types/dts/test-suite'; +export {InjectParam} from "../lib/test-suite-params/inject/inject-param"; +export {EachHookParam} from "../lib/test-suite-params/each-hook/each-hook-param"; +export {AllHookParam} from "../lib/test-suite-params/all-hook/all-hook-param"; +export {TestCaseParam} from "../lib/test-suite-params/test-case/test-case-param"; +export {ITestSuite} from 'suman-types/dts/test-suite'; export {ItFn, ITestDataObj} from 'suman-types/dts/it'; export {IDescribeFn, IDescribeOpts, TDescribeHook} from "suman-types/dts/describe"; export {IBeforeFn} from 'suman-types/dts/before'; diff --git a/lib/schemas/@config.json b/lib/schemas/@config.json index e69de29b..0967ef42 100644 --- a/lib/schemas/@config.json +++ b/lib/schemas/@config.json @@ -0,0 +1 @@ +{} diff --git a/lib/test-suite-helpers/define-options-classes.d.ts b/lib/test-suite-helpers/define-options-classes.d.ts index 2043b062..9ade361c 100644 --- a/lib/test-suite-helpers/define-options-classes.d.ts +++ b/lib/test-suite-helpers/define-options-classes.d.ts @@ -35,7 +35,7 @@ export declare class DefineObjectTestOrHook extends DefineObject { errorEvent(...args: string[]): this; } export declare class DefineOptionsInjectHook extends DefineObjectTestOrHook { - run(fn: T | TAfterEachHook): this; + run(fn: TBeforeEachHook | TAfterEachHook): this; } export declare class DefineObjectAllHook extends DefineObjectTestOrHook { first(v: boolean): this; diff --git a/lib/test-suite-helpers/define-options-classes.js b/lib/test-suite-helpers/define-options-classes.js index 3e1ff552..e93a51ce 100644 --- a/lib/test-suite-helpers/define-options-classes.js +++ b/lib/test-suite-helpers/define-options-classes.js @@ -26,7 +26,7 @@ var DefineObject = (function () { }; DefineObject.prototype.plan = function (v) { assert(Number.isInteger(v), 'Argument to plan must be an integer.'); - this.opts.planCount = v; + this.opts.plan = v; return this; }; DefineObject.prototype.desc = function (v) { @@ -255,7 +255,7 @@ var DefineObjectContext = (function (_super) { } this.opts.__toBeSourcedForIOC = this.opts.__toBeSourcedForIOC || {}; var self = this; - Array.from(arguments).forEach(function (a) { + args.forEach(function (a) { if (Array.isArray(a)) { self.source.apply(self, a); } @@ -273,7 +273,7 @@ var DefineObjectContext = (function (_super) { for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } - this.opts.names = Array.from(arguments).reduce(function (a, b) { + this.opts.names = args.reduce(function (a, b) { return a.concat(b); }, []); return this; diff --git a/lib/test-suite-helpers/define-options-classes.ts b/lib/test-suite-helpers/define-options-classes.ts index c1d6d012..b99e45c0 100644 --- a/lib/test-suite-helpers/define-options-classes.ts +++ b/lib/test-suite-helpers/define-options-classes.ts @@ -37,7 +37,7 @@ export class DefineObject { plan(v: number): this { assert(Number.isInteger(v), 'Argument to plan must be an integer.'); - this.opts.planCount = v; + this.opts.plan = v; return this; } @@ -196,7 +196,7 @@ export class DefineObjectTestOrHook extends DefineObject { export class DefineOptionsInjectHook extends DefineObjectTestOrHook { - run(fn: T | TAfterEachHook): this { + run(fn: TBeforeEachHook | TAfterEachHook): this { const name = this.opts.desc || '(unknown DefineObject name)'; // const opts = JSON.parse(su.customStringify(this.opts)); this.exec.call(null, name, Object.assign({}, this.opts), fn); @@ -208,7 +208,6 @@ export class DefineOptionsInjectHook extends DefineObjectTestOrHook { export class DefineObjectAllHook extends DefineObjectTestOrHook { - first(v: boolean): this { assert.equal(typeof v, 'boolean', 'Value for "first" must be a boolean.'); this.opts.first = v; @@ -233,7 +232,6 @@ export class DefineObjectAllHook extends DefineObjectTestOrHook { this.exec.call(null, name, Object.assign({}, this.opts), fn); return this; } - } export class DefineObjectEachHook extends DefineObjectTestOrHook { @@ -269,7 +267,7 @@ export class DefineObjectContext extends DefineObject { source(...args: string[]): this { this.opts.__toBeSourcedForIOC = this.opts.__toBeSourcedForIOC || {}; const self = this; // transpiles better this way - Array.from(arguments).forEach(function (a) { + args.forEach(function (a) { if (Array.isArray(a)) { // break into any arrays, recursively self.source(...a); @@ -286,7 +284,7 @@ export class DefineObjectContext extends DefineObject { } names(...args: string[]): this { - this.opts.names = Array.from(arguments).reduce(function (a, b) { + this.opts.names = args.reduce(function (a, b) { return a.concat(b); }, []); return this; diff --git a/lib/test-suite-helpers/handle-injections.js b/lib/test-suite-helpers/handle-injections.js index 095d3560..bf2e6ed3 100644 --- a/lib/test-suite-helpers/handle-injections.js +++ b/lib/test-suite-helpers/handle-injections.js @@ -5,7 +5,7 @@ var global = require('suman-browser-polyfills/modules/global'); var async = require("async"); var su = require("suman-utils"); var _suman = global.__suman = (global.__suman || {}); -var t_proto_inject_1 = require("./t-proto-inject"); +var inject_param_1 = require("../test-suite-params/inject/inject-param"); var suman_constants_1 = require("../../config/suman-constants"); var weAreDebugging = su.weAreDebugging; exports.handleInjections = function (suite, cb) { @@ -26,13 +26,16 @@ exports.handleInjections = function (suite, cb) { var injections = suite.getInjections(); async.eachSeries(injections, function (inj, cb) { var callable = true, timeoutVal = weAreDebugging ? 5000000 : inj.timeout; - var to = setTimeout(function () { + var onTimeout = function () { first(new Error("Injection hook timeout. " + ('For injection with name => ' + inj.desc))); - }, timeoutVal); + }; + var timerObj = { + timer: setTimeout(onTimeout, timeoutVal) + }; var first = function (err) { if (callable) { callable = false; - clearTimeout(to); + clearTimeout(timerObj.timer); process.nextTick(cb, err); } else if (err) { @@ -43,7 +46,7 @@ exports.handleInjections = function (suite, cb) { var values = []; var assertCount = { num: 0 }; return new Promise(function (resolve, reject) { - var injParam = t_proto_inject_1.makeInjectObj(inj, assertCount, suite, values, reject, resolve); + var injParam = new inject_param_1.InjectParam(inj, assertCount, suite, values, reject, resolve); injParam.fatal = reject; if (inj.cb) { var d = function (err, results) { @@ -68,13 +71,13 @@ exports.handleInjections = function (suite, cb) { } }) .then(function () { - debugger; + var seed = Promise.resolve(null); var p = values.reduce(function (a, b) { return Promise.resolve(b.val) .then(function (v) { return addValuesToSuiteInjections(b.k, v); }); - }, null); + }, seed); return p.then(function () { first(null); }); diff --git a/lib/test-suite-helpers/handle-injections.ts b/lib/test-suite-helpers/handle-injections.ts index c4354a9a..6644bfa9 100644 --- a/lib/test-suite-helpers/handle-injections.ts +++ b/lib/test-suite-helpers/handle-injections.ts @@ -21,7 +21,8 @@ import su = require('suman-utils'); //project const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); -import {makeInjectObj} from './t-proto-inject'; +// import {makeInjectParam} from './t-proto-inject'; +import {InjectParam} from "../test-suite-params/inject/inject-param"; import {constants} from "../../config/suman-constants"; const weAreDebugging = su.weAreDebugging; @@ -64,14 +65,20 @@ export const handleInjections = function (suite: ITestSuite, cb: ErrorCallback ' + inj.desc}`)); - }, timeoutVal); + }; + + const timerObj = { + timer: setTimeout(onTimeout, timeoutVal) + }; + + // const to = setTimeout(, timeoutVal); const first = function (err: IPseudoError) { if (callable) { callable = false; - clearTimeout(to); + clearTimeout(timerObj.timer); process.nextTick(cb, err); } else if (err) { @@ -85,7 +92,7 @@ export const handleInjections = function (suite: ITestSuite, cb: ErrorCallback (val: any, warn: boolean, d: ISumanDomain) => void; -export declare const handleGenerator: (fn: Function, args: any[]) => any; +export declare const handleReturnVal: (done: Function, fnStr: string, testOrHook: ITestDataObj | IHookObj) => (val: any, warn: boolean, d: ISumanDomain) => void; +export declare const handleGenerator: (fn: Function, arg: any) => any; diff --git a/lib/test-suite-helpers/handle-promise-generator.js b/lib/test-suite-helpers/handle-promise-generator.js index 282bd021..ae993911 100755 --- a/lib/test-suite-helpers/handle-promise-generator.js +++ b/lib/test-suite-helpers/handle-promise-generator.js @@ -9,10 +9,10 @@ var _suman = global.__suman = (global.__suman || {}); var general_1 = require("../helpers/general"); var defaultSuccessEvents = ['success', 'finish', 'close', 'end', 'done']; var defaultErrorEvents = ['error']; -exports.handleReturnVal = function (done, str, testOrHook) { +exports.handleReturnVal = function (done, fnStr, testOrHook) { return function handle(val, warn, d) { if ((!val || (typeof val.then !== 'function')) && warn) { - _suman.writeTestError('\n Suman warning: you may have forgotten to return a Promise => \n' + str + '\n'); + _suman.writeTestError('\n Suman warning: you may have forgotten to return a Promise => \n' + fnStr + '\n'); } if (su.isObservable(val)) { val.subscribe(function onNext(val) { @@ -75,7 +75,7 @@ exports.handleReturnVal = function (done, str, testOrHook) { } }; }; -exports.handleGenerator = function (fn, args) { +exports.handleGenerator = function (fn, arg) { var gen = general_1.makeRunGenerator(fn, null); - return gen.apply(null, args); + return gen.call(null, arg); }; diff --git a/lib/test-suite-helpers/handle-promise-generator.ts b/lib/test-suite-helpers/handle-promise-generator.ts index 2847487d..2e1842f5 100755 --- a/lib/test-suite-helpers/handle-promise-generator.ts +++ b/lib/test-suite-helpers/handle-promise-generator.ts @@ -28,12 +28,12 @@ const defaultErrorEvents = ['error']; ///////////////////////////////////////////////////////////////////////////////////////// -export const handleReturnVal = function (done: Function, str: string, testOrHook: ITestDataObj | IHookObj) { +export const handleReturnVal = function (done: Function, fnStr: string, testOrHook: ITestDataObj | IHookObj) { return function handle(val: any, warn: boolean, d: ISumanDomain) { if ((!val || (typeof val.then !== 'function')) && warn) { - _suman.writeTestError('\n Suman warning: you may have forgotten to return a Promise => \n' + str + '\n'); + _suman.writeTestError('\n Suman warning: you may have forgotten to return a Promise => \n' + fnStr + '\n'); } if (su.isObservable(val)) { @@ -134,9 +134,9 @@ export const handleReturnVal = function (done: Function, str: string, testOrHook } }; -export const handleGenerator = function (fn: Function, args: Array) { +export const handleGenerator = function (fn: Function, arg: any) { const gen = makeRunGenerator(fn, null); - return gen.apply(null, args); + return gen.call(null, arg); }; diff --git a/lib/test-suite-helpers/make-fini-callbacks.js b/lib/test-suite-helpers/make-fini-callbacks.js index 768bd144..43df5b09 100644 --- a/lib/test-suite-helpers/make-fini-callbacks.js +++ b/lib/test-suite-helpers/make-fini-callbacks.js @@ -4,7 +4,6 @@ var process = require('suman-browser-polyfills/modules/process'); var global = require('suman-browser-polyfills/modules/global'); var util = require("util"); var assert = require("assert"); -var su = require("suman-utils"); var chalk = require("chalk"); var _suman = global.__suman = (global.__suman || {}); var constants = require('../../config/suman-constants').constants; @@ -16,44 +15,52 @@ var missingHookOrTest = function () { _suman.writeTestError(mzg.stack); return mzg; }; -var planHelper = function (e, testOrHook, assertCount) { +var planHelper = function (testOrHook, assertCount) { if (testOrHook.planCountExpected !== undefined) { - assert(Number.isInteger(testOrHook.planCountExpected), 'Suman usage error => "plan" option must be an integer.'); + try { + assert(Number.isInteger(testOrHook.planCountExpected), 'Suman usage error => "plan" option must be an integer.'); + } + catch (err) { + return err; + } } if (Number.isInteger(testOrHook.planCountExpected) && testOrHook.planCountExpected !== assertCount.num) { - testOrHook.errorPlanCount = 'Error => Expected plan count was ' + testOrHook.planCountExpected + - ' but actual assertion/confirm count was ' + assertCount.num; - var newErr = general_1.cloneError(testOrHook.warningErr, testOrHook.errorPlanCount); - e = e ? new Error(su.getCleanErrStr(e) + '\n' + newErr.stack) : newErr; + var errorPlanCount = 'Error => Expected plan count was ' + testOrHook.planCountExpected + + ', but actual assertion/confirm count was ' + assertCount.num; + return general_1.cloneError(testOrHook.warningErr, errorPlanCount, false); } - return e; }; var throwsHelper = function (err, test, hook) { var testOrHook = (test || hook); - if (testOrHook.throws !== undefined) { - assert(testOrHook.throws instanceof RegExp, 'Suman usage error => "throws" option must be a RegExp instance.'); - var z = void 0; - if (!err) { - z = testOrHook.didNotThrowErrorWithExpectedMessage = - 'Error => Expected to throw an error matching regex (' + testOrHook.throws + ') , ' + - 'but did not throw or pass any error.'; - err = general_1.cloneError(testOrHook.warningErr, z); - if (hook) { - err.sumanFatal = true; - err.sumanExitCode = constants.EXIT_CODES.HOOK_DID_NOT_THROW_EXPECTED_ERROR; - } - } - else if (err && !String(err.stack || err).match(testOrHook.throws)) { - z = testOrHook.didNotThrowErrorWithExpectedMessage = - 'Error => Expected to throw an error matching regex (' + testOrHook.throws + ') , ' + - 'but did not throw or pass any error.'; - var newErr = general_1.cloneError(testOrHook.warningErr, z); - err = new Error(err.stack + '\n' + newErr.stack); - } - else { - err = null; + if (testOrHook.throws === undefined) { + return err; + } + try { + assert(testOrHook.throws instanceof RegExp, 'Suman error => "throws" option must be a RegExp instance.'); + } + catch (e) { + return e; + } + if (!err) { + var z = testOrHook.didNotThrowErrorWithExpectedMessage = + 'Error => Expected to throw an error matching regex (' + testOrHook.throws + ') , ' + + 'but did not throw or pass any error.'; + err = general_1.cloneError(testOrHook.warningErr, z); + if (hook) { + err.sumanFatal = true; + err.sumanExitCode = constants.EXIT_CODES.HOOK_DID_NOT_THROW_EXPECTED_ERROR; } } + else if (err && !String(err.stack || err).match(testOrHook.throws)) { + var z = testOrHook.didNotThrowErrorWithExpectedMessage = + 'Error => Expected to throw an error matching regex (' + testOrHook.throws + ') , ' + + 'but did not throw or pass any error.'; + var newErr = general_1.cloneError(testOrHook.warningErr, z); + err = new Error(err.stack + '\n' + newErr.stack); + } + else { + err = null; + } return err; }; exports.makeAllHookCallback = function (d, assertCount, hook, timerObj, gracefulExit, cb) { @@ -85,14 +92,13 @@ exports.makeAllHookCallback = function (d, assertCount, hook, timerObj, graceful } } try { - err = planHelper(err, hook, assertCount); + err = !err && planHelper(hook, assertCount); err = throwsHelper(err, null, hook); } - catch ($err) { - err = $err; + catch (e) { + err = e; } if (allHookFini.thot) { - debugger; allHookFini.thot.emit('done', err); allHookFini.thot.removeAllListeners(); } @@ -107,13 +113,13 @@ exports.makeAllHookCallback = function (d, assertCount, hook, timerObj, graceful } clearTimeout(timerObj.timer); if (err) { - err.sumanFatal = err.sumanFatal || !!((hook && hook.fatal !== false) || _suman.sumanOpts.bail); + err.sumanFatal = Boolean(err.sumanFatal || hook.fatal !== false || sumanOpts.bail); if (sumanOpts.bail) { err.sumanExitCode = constants.EXIT_CODES.HOOK_ERROR_AND_BAIL_IS_TRUE; } } gracefulExit(err, function () { - process.nextTick(cb, null, err); + cb(null, err); }); } else { @@ -159,11 +165,11 @@ exports.makeEachHookCallback = function (d, assertCount, hook, timerObj, gracefu } } try { - err = planHelper(err, hook, assertCount); + err = !err && planHelper(hook, assertCount); err = throwsHelper(err, null, hook); } - catch ($err) { - err = $err; + catch (e) { + err = e; } if (eachHookFini.thot) { eachHookFini.thot.emit('done', err); @@ -191,7 +197,7 @@ exports.makeEachHookCallback = function (d, assertCount, hook, timerObj, gracefu } } gracefulExit(err, function () { - process.nextTick(cb, null, err); + cb(null, err); }); } else { @@ -227,14 +233,13 @@ exports.makeTestCaseCallback = function (d, assertCount, test, timerObj, gracefu } if (++calledCount === 1) { try { - err = planHelper(err, test, assertCount); + err = !err && planHelper(test, assertCount); err = throwsHelper(err, test, null); } catch ($err) { err = $err; } if (testCaseFini.thot) { - debugger; testCaseFini.thot.emit('done', err); testCaseFini.thot.removeAllListeners(); } @@ -249,9 +254,9 @@ exports.makeTestCaseCallback = function (d, assertCount, test, timerObj, gracefu } clearTimeout(timerObj.timer); if (err) { - err.sumanFatal = err.sumanFatal || _suman.sumanOpts.bail; + err.sumanFatal = err.sumanFatal || sumanOpts.bail; test.error = err; - if (_suman.sumanOpts.bail) { + if (sumanOpts.bail) { err.sumanExitCode = constants.EXIT_CODES.TEST_ERROR_AND_BAIL_IS_TRUE; } } @@ -259,7 +264,9 @@ exports.makeTestCaseCallback = function (d, assertCount, test, timerObj, gracefu test.complete = true; test.dateComplete = Date.now(); } - process.nextTick(cb, null, err); + gracefulExit(err, function () { + cb(null, err); + }); } else { if (err) { diff --git a/lib/test-suite-helpers/make-fini-callbacks.ts b/lib/test-suite-helpers/make-fini-callbacks.ts index e4a4143e..5e6f7634 100755 --- a/lib/test-suite-helpers/make-fini-callbacks.ts +++ b/lib/test-suite-helpers/make-fini-callbacks.ts @@ -33,63 +33,71 @@ const missingHookOrTest = function () { return mzg; }; -const planHelper = function (e: IPseudoError, testOrHook: ITestDataObj | IHookObj, assertCount: IAssertObj) { +const planHelper = function (testOrHook: ITestDataObj | IHookObj, assertCount: IAssertObj) { if (testOrHook.planCountExpected !== undefined) { - assert(Number.isInteger(testOrHook.planCountExpected), 'Suman usage error => "plan" option must be an integer.'); + try { + assert(Number.isInteger(testOrHook.planCountExpected), 'Suman usage error => "plan" option must be an integer.'); + } + catch (err) { + return err; + } } if (Number.isInteger(testOrHook.planCountExpected) && testOrHook.planCountExpected !== assertCount.num) { - testOrHook.errorPlanCount = 'Error => Expected plan count was ' + testOrHook.planCountExpected + - ' but actual assertion/confirm count was ' + assertCount.num; + let errorPlanCount = 'Error => Expected plan count was ' + testOrHook.planCountExpected + + ', but actual assertion/confirm count was ' + assertCount.num; - const newErr = cloneError(testOrHook.warningErr, testOrHook.errorPlanCount); - e = e ? new Error(su.getCleanErrStr(e) + '\n' + newErr.stack) : newErr; + return cloneError(testOrHook.warningErr, errorPlanCount, false); } - return e; }; const throwsHelper = function (err: IPseudoError, test: ITestDataObj, hook: IHookObj) { const testOrHook: ITestDataObj | IHookObj = (test || hook); - if (testOrHook.throws !== undefined) { + if (testOrHook.throws === undefined) { + return err; + } + + try { + assert(testOrHook.throws instanceof RegExp, 'Suman error => "throws" option must be a RegExp instance.'); + } + catch (e) { + return e; + } + + if (!err) { - assert(testOrHook.throws instanceof RegExp, 'Suman usage error => "throws" option must be a RegExp instance.'); + let z = testOrHook.didNotThrowErrorWithExpectedMessage = + 'Error => Expected to throw an error matching regex (' + testOrHook.throws + ') , ' + + 'but did not throw or pass any error.'; - let z; - if (!err) { - - z = testOrHook.didNotThrowErrorWithExpectedMessage = - 'Error => Expected to throw an error matching regex (' + testOrHook.throws + ') , ' + - 'but did not throw or pass any error.'; - - err = cloneError(testOrHook.warningErr, z); - - if (hook) { - err.sumanFatal = true; - err.sumanExitCode = constants.EXIT_CODES.HOOK_DID_NOT_THROW_EXPECTED_ERROR; - } - - } - else if (err && !String(err.stack || err).match(testOrHook.throws)) { - - z = testOrHook.didNotThrowErrorWithExpectedMessage = - 'Error => Expected to throw an error matching regex (' + testOrHook.throws + ') , ' + - 'but did not throw or pass any error.'; - - let newErr = cloneError(testOrHook.warningErr, z); - err = new Error(err.stack + '\n' + newErr.stack); - - } - else { - // err matches expected error, so we can ignore error now - err = null; + err = cloneError(testOrHook.warningErr, z); + + if (hook) { + err.sumanFatal = true; + err.sumanExitCode = constants.EXIT_CODES.HOOK_DID_NOT_THROW_EXPECTED_ERROR; } } + else if (err && !String(err.stack || err).match(testOrHook.throws)) { + + let z = testOrHook.didNotThrowErrorWithExpectedMessage = + 'Error => Expected to throw an error matching regex (' + testOrHook.throws + ') , ' + + 'but did not throw or pass any error.'; + + let newErr = cloneError(testOrHook.warningErr, z); + err = new Error(err.stack + '\n' + newErr.stack); + + } + else { + // err matches expected error, so we can ignore error now + err = null; + } + return err; }; @@ -135,15 +143,14 @@ export const makeAllHookCallback = function (d: ISumanDomain, assertCount: IAsse } try { - err = planHelper(err, hook, assertCount); + err = !err && planHelper(hook, assertCount); err = throwsHelper(err, null, hook); } - catch ($err) { - err = $err; + catch (e) { + err = e; } if (allHookFini.thot) { - debugger; allHookFini.thot.emit('done', err); allHookFini.thot.removeAllListeners(); } @@ -163,7 +170,7 @@ export const makeAllHookCallback = function (d: ISumanDomain, assertCount: IAsse if (err) { - err.sumanFatal = err.sumanFatal || !!((hook && hook.fatal !== false) || _suman.sumanOpts.bail); + err.sumanFatal = Boolean(err.sumanFatal || hook.fatal !== false || sumanOpts.bail); if (sumanOpts.bail) { err.sumanExitCode = constants.EXIT_CODES.HOOK_ERROR_AND_BAIL_IS_TRUE; @@ -171,7 +178,7 @@ export const makeAllHookCallback = function (d: ISumanDomain, assertCount: IAsse } gracefulExit(err, function () { - process.nextTick(cb, null, err); + cb(null, err); }); } @@ -243,11 +250,11 @@ export const makeEachHookCallback = function (d: ISumanDomain, assertCount: IAss } try { - err = planHelper(err, hook, assertCount); + err = !err && planHelper(hook, assertCount); err = throwsHelper(err, null, hook); } - catch ($err) { - err = $err; + catch (e) { + err = e; } if (eachHookFini.thot) { @@ -283,7 +290,7 @@ export const makeEachHookCallback = function (d: ISumanDomain, assertCount: IAss } gracefulExit(err, function () { - process.nextTick(cb, null, err); + cb(null, err); }); } @@ -344,7 +351,7 @@ export const makeTestCaseCallback = function (d: ISumanDomain, assertCount: IAss if (++calledCount === 1) { try { - err = planHelper(err, test, assertCount); + err = !err && planHelper(test, assertCount); err = throwsHelper(err, test, null); } catch ($err) { @@ -352,7 +359,6 @@ export const makeTestCaseCallback = function (d: ISumanDomain, assertCount: IAss } if (testCaseFini.thot) { - debugger; testCaseFini.thot.emit('done', err); testCaseFini.thot.removeAllListeners(); } @@ -372,10 +378,10 @@ export const makeTestCaseCallback = function (d: ISumanDomain, assertCount: IAss if (err) { - err.sumanFatal = err.sumanFatal || _suman.sumanOpts.bail; + err.sumanFatal = err.sumanFatal || sumanOpts.bail; test.error = err; - if (_suman.sumanOpts.bail) { + if (sumanOpts.bail) { err.sumanExitCode = constants.EXIT_CODES.TEST_ERROR_AND_BAIL_IS_TRUE; } } @@ -384,7 +390,10 @@ export const makeTestCaseCallback = function (d: ISumanDomain, assertCount: IAss test.dateComplete = Date.now(); } - process.nextTick(cb, null, err); + gracefulExit(err, function () { + cb(null, err); + }); + } else { diff --git a/lib/test-suite-helpers/make-handle-befores-afters.d.ts b/lib/test-suite-helpers/make-handle-befores-afters.d.ts index c5b7db77..7bbf56b1 100755 --- a/lib/test-suite-helpers/make-handle-befores-afters.d.ts +++ b/lib/test-suite-helpers/make-handle-befores-afters.d.ts @@ -1 +1,3 @@ -export declare const makeHandleBeforesAndAfters: (suman: any, gracefulExit: Function) => (self: any, aBeforeOrAfter: any, cb: Function, retryData?: any) => void; +import { IOnceHookObj, ITestSuite } from "suman-types/dts/test-suite"; +import { Suman } from "../suman"; +export declare const makeHandleBeforesAndAfters: (suman: Suman, gracefulExit: Function) => (self: ITestSuite, aBeforeOrAfter: IOnceHookObj, cb: Function, retryData?: any) => void; diff --git a/lib/test-suite-helpers/make-handle-befores-afters.js b/lib/test-suite-helpers/make-handle-befores-afters.js index df8acaa8..63550e7c 100755 --- a/lib/test-suite-helpers/make-handle-befores-afters.js +++ b/lib/test-suite-helpers/make-handle-befores-afters.js @@ -12,8 +12,7 @@ var make_fini_callbacks_1 = require("./make-fini-callbacks"); var helpers = require('./handle-promise-generator'); var constants = require('../../config/suman-constants').constants; var general_1 = require("../helpers/general"); -var t_proto_hook_1 = require("./t-proto-hook"); -var freeze_existing_props_1 = require("freeze-existing-props"); +var all_hook_param_1 = require("../test-suite-params/all-hook/all-hook-param"); exports.makeHandleBeforesAndAfters = function (suman, gracefulExit) { return function handleBeforesAndAfters(self, aBeforeOrAfter, cb, retryData) { if (_suman.uncaughtExceptionTriggered) { @@ -105,39 +104,35 @@ exports.makeHandleBeforesAndAfters = function (suman, gracefulExit) { err = err ? ('Also, you have this error => ' + err.stack || err) : ''; handleError(new Error('Callback mode for this test-case/hook is not enabled, use .cb to enabled it.\n' + err)); }; - var t = t_proto_hook_1.makeHookObj(aBeforeOrAfter, assertCount, handleError, handlePossibleError); + var t = new all_hook_param_1.AllHookParam(aBeforeOrAfter, assertCount, handleError, handlePossibleError); t.__shared = self.shared; t.supply = self.supply; t.desc = aBeforeOrAfter.desc; fini.thot = t; t.timeout = timeout; - t.fatal = function fatal(err) { - err = err || new Error('Suman placeholder error since this function was not explicitly passed an error object as first argument.'); - handleError(err, null); - }; var arg; if (isGeneratorFn) { var handle = helpers.handleReturnVal(handlePossibleError, fnStr, aBeforeOrAfter); - arg = [freeze_existing_props_1.freezeExistingProps(t)]; + arg = t; handle(helpers.handleGenerator(aBeforeOrAfter.fn, arg)); } else if (aBeforeOrAfter.cb) { t.callbackMode = true; - var dne = function done(err) { + var dne = function (err) { t.callbackMode ? handlePossibleError(err) : handleNonCallbackMode(err); }; t.done = dne; t.ctn = t.pass = function (err) { t.callbackMode ? fini(null) : handleNonCallbackMode(err); }; - arg = Object.setPrototypeOf(dne, freeze_existing_props_1.freezeExistingProps(t)); + arg = Object.setPrototypeOf(dne, t); if (aBeforeOrAfter.fn.call(null, arg)) { _suman.writeTestError(general_1.cloneError(aBeforeOrAfter.warningErr, constants.warnings.RETURNED_VAL_DESPITE_CALLBACK_MODE, true).stack); } } else { var handle = helpers.handleReturnVal(handlePossibleError, fnStr, aBeforeOrAfter); - arg = freeze_existing_props_1.freezeExistingProps(t); + arg = t; handle(aBeforeOrAfter.fn.call(null, arg), warn); } }); diff --git a/lib/test-suite-helpers/make-handle-befores-afters.ts b/lib/test-suite-helpers/make-handle-befores-afters.ts index 40fde7f6..0ef839bd 100755 --- a/lib/test-suite-helpers/make-handle-befores-afters.ts +++ b/lib/test-suite-helpers/make-handle-befores-afters.ts @@ -1,9 +1,9 @@ 'use strict'; //dts -import {IHandleError, IOnceHookObj, ITestSuite} from "dts/test-suite"; -import {ISuman} from "suman-types/dts/suman"; +import {IHandleError, IOnceHookObj, ITestSuite} from "suman-types/dts/test-suite"; import {IGlobalSumanObj, IPseudoError, ISumanAllHookDomain, ISumanDomain} from "suman-types/dts/global"; +import {ISuman, Suman} from "../suman"; //polyfills const process = require('suman-browser-polyfills/modules/process'); @@ -24,7 +24,8 @@ import {makeAllHookCallback} from './make-fini-callbacks'; const helpers = require('./handle-promise-generator'); const {constants} = require('../../config/suman-constants'); import {cloneError} from '../helpers/general'; -import {makeHookObj} from './t-proto-hook'; +// import {makeHookParam} from './t-proto-hook'; +import {AllHookParam} from "../test-suite-params/all-hook/all-hook-param"; import {freezeExistingProps} from 'freeze-existing-props'; ///////////////////////////////////////////////////////////////////////////////////// @@ -70,7 +71,7 @@ export const makeHandleBeforesAndAfters = function (suman: ISuman, gracefulExit: let dError = false; - const handleError: IHandleError = function (err: IPseudoError) { + const handleError: IHandleError = (err: IPseudoError) => { if (aBeforeOrAfter.dynamicallySkipped === true) { return fini(null); @@ -88,15 +89,9 @@ export const makeHandleBeforesAndAfters = function (suman: ISuman, gracefulExit: _suman.log.error('maximum retries attempted.'); } } - - const errMessage = err && (err.stack || err.message|| util.inspect(err)); - err = cloneError(aBeforeOrAfter.warningErr, errMessage, false); - // err = err || new Error('unknown hook error.'); - // - // if (typeof err === 'string') { - // err = new Error(err); - // } + const errMessage = err && (err.stack || err.message || util.inspect(err)); + err = cloneError(aBeforeOrAfter.warningErr, errMessage, false); const stk = err.stack || err; const formatedStk = typeof stk === 'string' ? stk : util.inspect(stk); @@ -126,13 +121,13 @@ export const makeHandleBeforesAndAfters = function (suman: ISuman, gracefulExit: } }; - const handlePossibleError = function (err: Error | IPseudoError) { + const handlePossibleError = (err: Error | IPseudoError) => { err ? handleError(err) : fini(null) }; d.on('error', handleError); - process.nextTick(function () { + process.nextTick(() => { const {sumanOpts} = _suman; @@ -143,7 +138,7 @@ export const makeHandleBeforesAndAfters = function (suman: ISuman, gracefulExit: // need to d.run instead process.next so that errors thrown in same-tick get trapped by "Node.js domains in browser" // process.nextTick is necessary in the first place, so that async module does not experience Zalgo - d.run(function runAllHook() { + d.run(function runAllHook(){ _suman.activeDomain = d; let warn = false; @@ -154,35 +149,30 @@ export const makeHandleBeforesAndAfters = function (suman: ISuman, gracefulExit: const isGeneratorFn = su.isGeneratorFn(aBeforeOrAfter.fn); - const timeout = function (val: number) { + const timeout = (val: number) => { clearTimeout(timerObj.timer); assert(val && Number.isInteger(val), 'value passed to timeout() must be an integer.'); timerObj.timer = setTimeout(onTimeout, _suman.weAreDebugging ? 5000000 : val); }; - const handleNonCallbackMode = function (err: IPseudoError) { + const handleNonCallbackMode = (err: IPseudoError) => { err = err ? ('Also, you have this error => ' + err.stack || err) : ''; handleError(new Error('Callback mode for this test-case/hook is not enabled, use .cb to enabled it.\n' + err)); }; - const t = makeHookObj(aBeforeOrAfter, assertCount, handleError, handlePossibleError); + const t = new AllHookParam(aBeforeOrAfter, assertCount, handleError, handlePossibleError); t.__shared = self.shared; t.supply = self.supply; t.desc = aBeforeOrAfter.desc; fini.thot = t; t.timeout = timeout; - t.fatal = function fatal(err: IPseudoError) { - err = err || new Error( - 'Suman placeholder error since this function was not explicitly passed an error object as first argument.' - ); - handleError(err, null); - }; let arg; if (isGeneratorFn) { const handle = helpers.handleReturnVal(handlePossibleError, fnStr, aBeforeOrAfter); - arg = [freezeExistingProps(t)]; + // arg = [freezeExistingProps(t)]; + arg = t; handle(helpers.handleGenerator(aBeforeOrAfter.fn, arg)); } else if (aBeforeOrAfter.cb) { @@ -194,7 +184,7 @@ export const makeHandleBeforesAndAfters = function (suman: ISuman, gracefulExit: // throw aBeforeOrAfter.NO_DONE; // } - const dne = function done(err: IPseudoError) { + const dne = (err: IPseudoError) => { t.callbackMode ? handlePossibleError(err) : handleNonCallbackMode(err); }; @@ -204,7 +194,8 @@ export const makeHandleBeforesAndAfters = function (suman: ISuman, gracefulExit: t.callbackMode ? fini(null) : handleNonCallbackMode(err); }; - arg = Object.setPrototypeOf(dne, freezeExistingProps(t)); + // arg = Object.setPrototypeOf(dne, freezeExistingProps(t)); + arg = Object.setPrototypeOf(dne, t); if (aBeforeOrAfter.fn.call(null, arg)) { //check to see if we have a defined return value _suman.writeTestError(cloneError(aBeforeOrAfter.warningErr, constants.warnings.RETURNED_VAL_DESPITE_CALLBACK_MODE, true).stack); @@ -213,7 +204,8 @@ export const makeHandleBeforesAndAfters = function (suman: ISuman, gracefulExit: } else { const handle = helpers.handleReturnVal(handlePossibleError, fnStr, aBeforeOrAfter); - arg = freezeExistingProps(t); + // arg = freezeExistingProps(t); + arg = t; handle(aBeforeOrAfter.fn.call(null, arg), warn); } diff --git a/lib/test-suite-helpers/make-handle-each.js b/lib/test-suite-helpers/make-handle-each.js index 5b61ebf1..5b0fbd03 100755 --- a/lib/test-suite-helpers/make-handle-each.js +++ b/lib/test-suite-helpers/make-handle-each.js @@ -11,10 +11,9 @@ var _suman = global.__suman = (global.__suman || {}); var su = require("suman-utils"); var constants = require('../../config/suman-constants').constants; var general_1 = require("../helpers/general"); -var t_proto_hook_1 = require("./t-proto-hook"); +var each_hook_param_1 = require("../test-suite-params/each-hook/each-hook-param"); var make_fini_callbacks_1 = require("./make-fini-callbacks"); var helpers = require('./handle-promise-generator'); -var freeze_existing_props_1 = require("freeze-existing-props"); exports.makeHandleBeforeOrAfterEach = function (suman, gracefulExit) { return function handleBeforeOrAfterEach(self, test, aBeforeOrAfterEach, cb, retryData) { if (_suman.uncaughtExceptionTriggered) { @@ -23,7 +22,10 @@ exports.makeHandleBeforeOrAfterEach = function (suman, gracefulExit) { } var sumanOpts = _suman.sumanOpts; aBeforeOrAfterEach.alreadyInitiated = true; - if (test.skipped || test.stubbed || test.failed) { + if (test.skipped || test.stubbed) { + return process.nextTick(cb); + } + if (test.failed && aBeforeOrAfterEach.type === 'beforeEach/setupTest') { return process.nextTick(cb); } var onTimeout = function () { @@ -125,7 +127,7 @@ exports.makeHandleBeforeOrAfterEach = function (suman, gracefulExit) { err = err ? ('Also, you have this error => ' + err.stack || err) : ''; handleError(new Error('Callback mode for this test-case/hook is not enabled, use .cb to enabled it.\n' + err)); }; - var t = t_proto_hook_1.makeHookObj(aBeforeOrAfterEach, assertCount, handleError, handlePossibleError); + var t = new each_hook_param_1.EachHookParam(aBeforeOrAfterEach, assertCount, handleError, handlePossibleError); fini.thot = t; t.timeout = timeout; t.test = {}; @@ -133,7 +135,7 @@ exports.makeHandleBeforeOrAfterEach = function (suman, gracefulExit) { t.test.testId = test.testId; if (aBeforeOrAfterEach.type === 'afterEach/teardownTest') { t.test.result = test.error ? 'failed' : 'passed'; - t.test.error = test.error; + t.test.error = test.error || null; } t.data = test.data; t.desc = aBeforeOrAfterEach.desc; @@ -141,37 +143,30 @@ exports.makeHandleBeforeOrAfterEach = function (suman, gracefulExit) { t.state = 'pending'; t.__shared = self.shared; t.supply = t.__supply = self.supply; - t.fatal = function fatal(err) { - err = err || new Error('Stand-in error, since user did not provide one.'); - if (typeof err !== 'object') - err = new Error(util.inspect(err)); - err.sumanFatal = true; - handleError(err); - }; - var args; + var arg; if (isGeneratorFn) { var handlePotentialPromise = helpers.handleReturnVal(handlePossibleError, fnStr, aBeforeOrAfterEach); - args = [freeze_existing_props_1.freezeExistingProps(t)]; - handlePotentialPromise(helpers.handleGenerator(aBeforeOrAfterEach.fn, args)); + arg = t; + handlePotentialPromise(helpers.handleGenerator(aBeforeOrAfterEach.fn, arg)); } else if (aBeforeOrAfterEach.cb) { t.callbackMode = true; - var dne = function done(err) { + var dne = function (err) { t.callbackMode ? handlePossibleError(err) : handleNonCallbackMode(err); }; t.done = dne; t.ctn = t.pass = function () { t.callbackMode ? fini(null) : handleNonCallbackMode(undefined); }; - args = Object.setPrototypeOf(dne, freeze_existing_props_1.freezeExistingProps(t)); - if (aBeforeOrAfterEach.fn.call(null, args)) { + arg = Object.setPrototypeOf(dne, t); + if (aBeforeOrAfterEach.fn.call(null, arg)) { _suman.writeTestError(general_1.cloneError(aBeforeOrAfterEach.warningErr, constants.warnings.RETURNED_VAL_DESPITE_CALLBACK_MODE, true).stack); } } else { var handlePotentialPromise = helpers.handleReturnVal(handlePossibleError, fnStr, aBeforeOrAfterEach); - args = freeze_existing_props_1.freezeExistingProps(t); - handlePotentialPromise(aBeforeOrAfterEach.fn.call(null, args), false); + arg = t; + handlePotentialPromise(aBeforeOrAfterEach.fn.call(null, arg), false); } }); }); diff --git a/lib/test-suite-helpers/make-handle-each.ts b/lib/test-suite-helpers/make-handle-each.ts index 6c53cc80..7ae87b6e 100755 --- a/lib/test-suite-helpers/make-handle-each.ts +++ b/lib/test-suite-helpers/make-handle-each.ts @@ -24,7 +24,8 @@ const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); import su = require('suman-utils'); const {constants} = require('../../config/suman-constants'); import {cloneError} from '../helpers/general'; -import {makeHookObj} from './t-proto-hook'; +// import {makeHookParam} from './t-proto-hook'; +import {EachHookParam} from "../test-suite-params/each-hook/each-hook-param"; import {makeEachHookCallback} from './make-fini-callbacks'; const helpers = require('./handle-promise-generator'); import {freezeExistingProps} from 'freeze-existing-props' @@ -44,12 +45,19 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit const {sumanOpts} = _suman; aBeforeOrAfterEach.alreadyInitiated = true; - if (test.skipped || test.stubbed || test.failed) { + if (test.skipped || test.stubbed) { + return process.nextTick(cb); + } + + if (test.failed && aBeforeOrAfterEach.type === 'beforeEach/setupTest') { // if test.failed => another beforeEach hook failed, so test failed + // if this is a beforeEach hook, we can skip it + // on the other hand this is an afterEach hook, + // we should continue processing afterEach hooks even if the test failed. return process.nextTick(cb); } - const onTimeout = function () { + const onTimeout = () => { const err = cloneError(aBeforeOrAfterEach.warningErr, constants.warnings.HOOK_TIMED_OUT_ERROR); err.sumanExitCode = constants.EXIT_CODES.HOOK_TIMED_OUT_ERROR; fini(err, true); @@ -77,7 +85,7 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit fini.retryFn = retryData ? retryData.retryFn : handleBeforeOrAfterEach.bind(null, arguments); } - const handlePossibleError = function (err: Error | IPseudoError) { + const handlePossibleError = (err: Error | IPseudoError) => { if (err) { if (typeof err !== 'object') err = new Error(util.inspect(err)); err.sumanFatal = Boolean(sumanOpts.bail); @@ -88,7 +96,7 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit } }; - const handleError: IHandleError = function (err: IPseudoError) { + const handleError: IHandleError = (err: IPseudoError) => { if (aBeforeOrAfterEach.dynamicallySkipped === true) { err && _suman.log.warning('Hook was dynamically skipped, but error occurred:', err.message || util.inspect(err)); @@ -108,12 +116,12 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit } } - const errMessage = err && (err.stack || err.message|| util.inspect(err)); + const errMessage = err && (err.stack || err.message || util.inspect(err)); err = cloneError(aBeforeOrAfterEach.warningErr, errMessage, false); // console.log('error => ', err); // console.log('aBeforeOrAfterEach.warningErr => ', aBeforeOrAfterEach.warningErr); - + // // err = err || new Error('unknown/falsy hook error.'); // // if (typeof err === 'string') { @@ -153,7 +161,7 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit d.on('error', handleError); - process.nextTick(function () { + process.nextTick(() => { _suman.activeDomain = d; @@ -171,8 +179,6 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit isAsyncAwait = true; } - //TODO: need to implement all assert methods - const timeout = function (val: number) { clearTimeout(timerObj.timer); assert(val && Number.isInteger(val), 'value passed to timeout() must be an integer.'); @@ -184,7 +190,7 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit handleError(new Error('Callback mode for this test-case/hook is not enabled, use .cb to enabled it.\n' + err)); }; - const t = makeHookObj(aBeforeOrAfterEach, assertCount, handleError, handlePossibleError); + const t = new EachHookParam(aBeforeOrAfterEach, assertCount, handleError, handlePossibleError); fini.thot = t; t.timeout = timeout; t.test = {}; @@ -194,7 +200,7 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit 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.test.error = test.error || null; } t.data = test.data; @@ -204,19 +210,13 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit t.__shared = self.shared; t.supply = t.__supply = self.supply; - t.fatal = function fatal(err: IPseudoError) { - err = err || new Error('Stand-in error, since user did not provide one.'); - if (typeof err !== 'object') err = new Error(util.inspect(err)); - err.sumanFatal = true; - handleError(err); - }; - - let args; + let arg; if (isGeneratorFn) { const handlePotentialPromise = helpers.handleReturnVal(handlePossibleError, fnStr, aBeforeOrAfterEach); - args = [freezeExistingProps(t)]; - handlePotentialPromise(helpers.handleGenerator(aBeforeOrAfterEach.fn, args)); + // arg = freezeExistingProps(t); + arg = t; + handlePotentialPromise(helpers.handleGenerator(aBeforeOrAfterEach.fn, arg)); } else if (aBeforeOrAfterEach.cb) { @@ -227,21 +227,22 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit // throw aBeforeOrAfter.NO_DONE; // } - const dne = function done(err: IPseudoError) { + const dne = function (err: IPseudoError) { t.callbackMode ? handlePossibleError(err) : handleNonCallbackMode(err); }; t.done = dne; - t.ctn = t.pass = function () { + t.ctn = t.pass = () => { // t.pass doesn't make sense since this is not a test case, but for user friendliness // this is like t.done() except by design no error will ever get passed t.callbackMode ? fini(null) : handleNonCallbackMode(undefined); }; - args = Object.setPrototypeOf(dne, freezeExistingProps(t)); + // arg = Object.setPrototypeOf(dne, freezeExistingProps(t)); + arg = Object.setPrototypeOf(dne, t); - if (aBeforeOrAfterEach.fn.call(null, args)) { + if (aBeforeOrAfterEach.fn.call(null, arg)) { _suman.writeTestError(cloneError(aBeforeOrAfterEach.warningErr, constants.warnings.RETURNED_VAL_DESPITE_CALLBACK_MODE, true).stack); } @@ -249,8 +250,9 @@ export const makeHandleBeforeOrAfterEach = function (suman: ISuman, gracefulExit else { const handlePotentialPromise = helpers.handleReturnVal(handlePossibleError, fnStr, aBeforeOrAfterEach); - args = freezeExistingProps(t); - handlePotentialPromise(aBeforeOrAfterEach.fn.call(null, args), false); + // arg = freezeExistingProps(t); + arg = t; + handlePotentialPromise(aBeforeOrAfterEach.fn.call(null, arg), false); } }); diff --git a/lib/test-suite-helpers/make-handle-test.js b/lib/test-suite-helpers/make-handle-test.js index 1dd3de38..08b986fc 100755 --- a/lib/test-suite-helpers/make-handle-test.js +++ b/lib/test-suite-helpers/make-handle-test.js @@ -15,8 +15,7 @@ var constants = require('../../config/suman-constants').constants; var make_fini_callbacks_1 = require("./make-fini-callbacks"); var helpers = require('./handle-promise-generator'); var general_1 = require("../helpers/general"); -var t_proto_test_1 = require("./t-proto-test"); -var freeze_existing_props_1 = require("freeze-existing-props"); +var test_case_param_1 = require("../test-suite-params/test-case/test-case-param"); var rb = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); exports.makeHandleTest = function (suman, gracefulExit) { return function handleTest(self, test, cb, retryData) { @@ -123,7 +122,7 @@ exports.makeHandleTest = function (suman, gracefulExit) { err = err ? ('Also, you have this error => ' + err.stack || err) : ''; handleErr(new Error('Callback mode for this test-case/hook is not enabled, use .cb to enabled it.\n' + err)); }; - var t = t_proto_test_1.makeTestCase(test, assertCount, handleErr, handlePossibleError); + var t = new test_case_param_1.TestCaseParam(test, assertCount, handleErr, handlePossibleError); fini.thot = t; t.throw = $throw; t.timeout = timeout; @@ -131,20 +130,16 @@ exports.makeHandleTest = function (suman, gracefulExit) { t.__supply = self.supply; t.supply = new Proxy(self.__supply, { set: function (target, property, value, receiver) { - throw new Error('cannot set any properties on t.$inject (in test cases).'); + handleErr(new Error('cannot set any properties on t.supply (in test cases).')); + return false; } }); - t.fatal = function fatal(err) { - err = err || new Error('t.fatal() was called by the developer.'); - err.sumanFatal = true; - handleErr(err); - }; test.dateStarted = Date.now(); - var args; + var arg; if (isGeneratorFn) { var handlePotentialPromise = helpers.handleReturnVal(handlePossibleError, fnStr, test); - args = [freeze_existing_props_1.freezeExistingProps(t)]; - handlePotentialPromise(helpers.handleGenerator(test.fn, args)); + arg = t; + handlePotentialPromise(helpers.handleGenerator(test.fn, arg)); } else if (test.cb === true) { t.callbackMode = true; @@ -155,7 +150,7 @@ exports.makeHandleTest = function (suman, gracefulExit) { t.pass = t.ctn = function () { t.callbackMode ? fini(null) : handleNonCallbackMode(null); }; - t.fail = function fail(err) { + t.fail = function (err) { if (!t.callbackMode) { handleNonCallbackMode(err); } @@ -164,15 +159,15 @@ exports.makeHandleTest = function (suman, gracefulExit) { 'was passed as first arg to the fail function.)')); } }; - args = Object.setPrototypeOf(dne, freeze_existing_props_1.freezeExistingProps(t)); - if (test.fn.call(null, args)) { + arg = Object.setPrototypeOf(dne, t); + if (test.fn.call(null, arg)) { _suman.writeTestError(general_1.cloneError(test.warningErr, constants.warnings.RETURNED_VAL_DESPITE_CALLBACK_MODE, true).stack); } } else { var handlePotentialPromise = helpers.handleReturnVal(handlePossibleError, fnStr, test); - args = freeze_existing_props_1.freezeExistingProps(t); - handlePotentialPromise(test.fn.call(null, args), warn, d); + arg = t; + handlePotentialPromise(test.fn.call(null, arg), warn, d); } }); }); diff --git a/lib/test-suite-helpers/make-handle-test.ts b/lib/test-suite-helpers/make-handle-test.ts index 4563e623..6da4bbd6 100755 --- a/lib/test-suite-helpers/make-handle-test.ts +++ b/lib/test-suite-helpers/make-handle-test.ts @@ -28,7 +28,8 @@ const {constants} = require('../../config/suman-constants'); import {makeTestCaseCallback} from './make-fini-callbacks'; const helpers = require('./handle-promise-generator'); import {cloneError} from '../helpers/general'; -import {makeTestCase} from './t-proto-test'; +import {TestCaseParam} from "../test-suite-params/test-case/test-case-param"; +// import {makeTestCaseParam} from './t-proto-test'; import {freezeExistingProps} from 'freeze-existing-props' const rb = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); @@ -173,7 +174,7 @@ export const makeHandleTest = function (suman: ISuman, gracefulExit: Function) { timerObj.timer = setTimeout(onTimeout, _suman.weAreDebugging ? 5000000 : val); }; - const $throw = function (str: any) { + const $throw = (str: any) => { handleErr(str instanceof Error ? str : new Error(str)); }; @@ -182,7 +183,7 @@ export const makeHandleTest = function (suman: ISuman, gracefulExit: Function) { handleErr(new Error('Callback mode for this test-case/hook is not enabled, use .cb to enabled it.\n' + err)); }; - const t = makeTestCase(test, assertCount, handleErr, handlePossibleError); + const t = new TestCaseParam(test, assertCount, handleErr, handlePossibleError); fini.thot = t; t.throw = $throw; t.timeout = timeout; @@ -190,28 +191,22 @@ export const makeHandleTest = function (suman: ISuman, gracefulExit: Function) { t.__supply = self.supply; t.supply = new Proxy(self.__supply, { set(target, property, value, receiver) { - throw new Error('cannot set any properties on t.$inject (in test cases).'); + handleErr(new Error('cannot set any properties on t.supply (in test cases).')); + return false; } }); - ////////////// note: unfortunately these fns cannot be moved to prototype ///////////////// - - t.fatal = function fatal(err: IPseudoError) { - err = err || new Error('t.fatal() was called by the developer.'); - err.sumanFatal = true; - handleErr(err); - }; - //////////////////////////////////////////////////////////////////////////////////////////// test.dateStarted = Date.now(); - let args; + let arg; if (isGeneratorFn) { const handlePotentialPromise = helpers.handleReturnVal(handlePossibleError, fnStr, test); - args = [freezeExistingProps(t)]; - handlePotentialPromise(helpers.handleGenerator(test.fn, args)); + // arg = freezeExistingProps(t); + arg = t; + handlePotentialPromise(helpers.handleGenerator(test.fn, arg)); } else if (test.cb === true) { @@ -228,11 +223,11 @@ export const makeHandleTest = function (suman: ISuman, gracefulExit: Function) { t.done = dne; - t.pass = t.ctn = function () { + t.pass = t.ctn = () => { t.callbackMode ? fini(null) : handleNonCallbackMode(null); }; - t.fail = function fail(err: Error) { + t.fail = (err: Error) => { if (!t.callbackMode) { handleNonCallbackMode(err); } @@ -242,16 +237,18 @@ export const makeHandleTest = function (suman: ISuman, gracefulExit: Function) { } }; - args = Object.setPrototypeOf(dne, freezeExistingProps(t)); - if (test.fn.call(null, args)) { ///run the fn, but if it returns something, then add warning + // arg = Object.setPrototypeOf(dne, freezeExistingProps(t)); + arg = Object.setPrototypeOf(dne, t); + if (test.fn.call(null, arg)) { ///run the fn, but if it returns something, then add warning _suman.writeTestError(cloneError(test.warningErr, constants.warnings.RETURNED_VAL_DESPITE_CALLBACK_MODE, true).stack); } } else { const handlePotentialPromise = helpers.handleReturnVal(handlePossibleError, fnStr, test); - args = freezeExistingProps(t); - handlePotentialPromise(test.fn.call(null, args), warn, d); + // arg = freezeExistingProps(t); + arg = t; + handlePotentialPromise(test.fn.call(null, arg), warn, d); } }); diff --git a/lib/test-suite-helpers/make-test-suite.d.ts b/lib/test-suite-helpers/make-test-suite.d.ts index 6662bfcb..ace2a8cf 100755 --- a/lib/test-suite-helpers/make-test-suite.d.ts +++ b/lib/test-suite-helpers/make-test-suite.d.ts @@ -1,4 +1,44 @@ +import { ITestSuite } from 'suman-types/dts/test-suite'; import { Suman } from '../suman'; +export declare class TestBlockBase { + opts: Object; + testId: number; + childCompletionCount: number; + allChildBlocksCompleted: boolean; + isSetupComplete: boolean; + parallel: boolean; + skipped: boolean; + fixed: boolean; + only: boolean; + filename: string; + getAfterAllParentHooks: Function; + completedChildrenMap: Map; + parent?: ITestSuite; + describe: Function; + context: Function; + suite: Function; + before: Function; + beforeAll: Function; + beforeEach: Function; + after: Function; + afterAll: Function; + afterEach: Function; + it: Function; + test: Function; + testBlockMethodCache: Object; + protected mergeAfters: Function; + protected getAfters: Function; + protected getAfterEaches: Function; + protected getBefores: Function; + protected getBeforeEaches: Function; + protected injectedValues: Object; + protected getInjectedValue: Function; + protected getInjections: Function; + protected getChildren: Function; + protected getTests: Function; + protected getParallelTests: Function; + protected getAftersLast: Function; +} export interface ISumanSymbols { [key: string]: symbol; } diff --git a/lib/test-suite-helpers/make-test-suite.js b/lib/test-suite-helpers/make-test-suite.js index c3743a75..dfd949c6 100755 --- a/lib/test-suite-helpers/make-test-suite.js +++ b/lib/test-suite-helpers/make-test-suite.js @@ -22,6 +22,7 @@ var TestBlockBase = (function () { } return TestBlockBase; }()); +exports.TestBlockBase = TestBlockBase; var makeRunChild = function (val) { return function runChild(child, cb) { child._run(val, cb); @@ -97,7 +98,7 @@ exports.makeTestSuite = function (suman, gracefulExit, handleBeforesAndAfters, n } return this.shared.get(k); }; - TestBlock.prototype.gets = function () { + TestBlock.prototype.getValues = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; @@ -107,6 +108,18 @@ exports.makeTestSuite = function (suman, gracefulExit, handleBeforesAndAfters, n return self.shared.get(k); }); }; + TestBlock.prototype.getMap = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var self = this; + var ret = {}; + args.forEach(function (k) { + ret[k] = self.shared.get(k); + }); + return ret; + }; TestBlock.prototype.getAfterAllParentHooks = function () { return this[exports.TestBlockSymbols.getAfterAllParentHooks]; }; @@ -135,19 +148,56 @@ exports.makeTestSuite = function (suman, gracefulExit, handleBeforesAndAfters, n } }; TestBlock.prototype.getInjectedValues = function () { - var _this = this; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } + var self = this; + return args.map(function (a) { + return self.getInjectedValue(a); + }); + }; + TestBlock.prototype.getInjectedMap = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var self = this; + var ret = {}; + args.forEach(function (a) { + ret[a] = self.getInjectedValue(a); + }); + return ret; + }; + TestBlock.prototype.getSourcedValue = function (v) { + if (v in this.ioc) { + return this.ioc[v]; + } + else if (this.parent) { + return this.parent.getSourcedValue(v); + } + }; + TestBlock.prototype.getSourcedValues = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var self = this; return args.map(function (a) { - if (a in _this.injectedValues) { - return _this.injectedValues[a]; - } - else if (_this.parent) { - return _this.parent.getInjectedValue(a); - } + return self.getSourcedValue(a); + }); + }; + TestBlock.prototype.getSourcedMap = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var self = this; + var ret = {}; + args.forEach(function (a) { + ret[a] = self.getSourcedValue(a); }); + return ret; }; TestBlock.prototype.getInjections = function () { return this[exports.TestBlockSymbols.injections]; diff --git a/lib/test-suite-helpers/make-test-suite.ts b/lib/test-suite-helpers/make-test-suite.ts index c55d3c7e..b1fe865a 100755 --- a/lib/test-suite-helpers/make-test-suite.ts +++ b/lib/test-suite-helpers/make-test-suite.ts @@ -39,7 +39,7 @@ import {makeStartSuite} from './make-start-suite'; type ITestSuiteConstructor = (obj: ITestSuiteMakerOpts) => void; -class TestBlockBase { +export class TestBlockBase { // public opts: Object; testId: number; @@ -198,13 +198,22 @@ export const makeTestSuite = function (suman: ISuman, gracefulExit: Function, return this.shared.get(k); } - gets(...args: Array) { + getValues(...args: Array) { const self = this; return args.map(function (k) { return self.shared.get(k); }); } + getMap(...args: Array) { + const self = this; + const ret = {} as any; + args.forEach(function (k) { + ret[k] = self.shared.get(k); + }); + return ret; + } + getAfterAllParentHooks() { return this[TestBlockSymbols.getAfterAllParentHooks]; } @@ -243,14 +252,44 @@ export const makeTestSuite = function (suman: ISuman, gracefulExit: Function, } getInjectedValues(...args: string[]) { - return args.map(a => { - if (a in this.injectedValues) { - return this.injectedValues[a]; - } - else if (this.parent) { - return this.parent.getInjectedValue(a); - } + const self = this; + return args.map(function (a) { + return self.getInjectedValue(a); + }); + } + + getInjectedMap(...args: string[]) { + const self = this; + const ret = {} as any; + args.forEach(function (a) { + ret[a] = self.getInjectedValue(a); + }); + return ret; + } + + getSourcedValue(v: string): any { + if (v in this.ioc) { + return this.ioc[v]; + } + else if (this.parent) { + return this.parent.getSourcedValue(v); + } + } + + getSourcedValues(...args: string[]) { + const self = this; + return args.map(function (a) { + return self.getSourcedValue(a); + }); + } + + getSourcedMap(...args: string[]) { + const self = this; + const ret = {} as any; + args.forEach(function (a) { + ret[a] = self.getSourcedValue(a); }); + return ret; } getInjections() { diff --git a/lib/test-suite-helpers/make-the-trap.d.ts b/lib/test-suite-helpers/make-the-trap.d.ts index 816c32fa..2eba446b 100755 --- a/lib/test-suite-helpers/make-the-trap.d.ts +++ b/lib/test-suite-helpers/make-the-trap.d.ts @@ -1,4 +1,4 @@ import { ITestSuite } from "suman-types/dts/test-suite"; import { Suman } from "../suman"; import { IItOpts, ITestDataObj } from "suman-types/dts/it"; -export declare const makeTheTrap: (suman: Suman, gracefulExit: Function) => (self: ITestSuite, test: ITestDataObj, opts: IItOpts, cb: Function) => any; +export declare const makeTheTrap: (suman: Suman, gracefulExit: Function) => (self: ITestSuite, test: ITestDataObj, opts: Partial, cb: Function) => any; diff --git a/lib/test-suite-helpers/make-the-trap.js b/lib/test-suite-helpers/make-the-trap.js index 82fdcbfd..397736f9 100755 --- a/lib/test-suite-helpers/make-the-trap.js +++ b/lib/test-suite-helpers/make-the-trap.js @@ -11,7 +11,7 @@ var _suman = global.__suman = (global.__suman || {}); var make_handle_test_1 = require("./make-handle-test"); var make_handle_each_1 = require("./make-handle-each"); var general_1 = require("../helpers/general"); -var rb = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); +var rb = _suman.resultBroadcaster = _suman.resultBroadcaster || new EE(); var testErrors = _suman.testErrors = _suman.testErrors || []; var errors = _suman.sumanRuntimeErrors = _suman.sumanRuntimeErrors || []; var getAllBeforesEaches = function (zuite) { @@ -62,51 +62,45 @@ var stckMapFn = function (item, index) { return su.padWithXSpaces(4) + item; } }; -var makeHandleTestResults = function (suman) { - return function handleTestError(err, test) { - if (_suman.uncaughtExceptionTriggered) { - _suman.log.error("runtime error => \"UncaughtException:Triggered\" => halting program.\n[" + __filename + "]"); - return; +var handleTestError = function (err, test) { + if (_suman.uncaughtExceptionTriggered) { + _suman.log.error("runtime error => \"UncaughtException:Triggered\" => halting program.\n[" + __filename + "]"); + return; + } + if (err) { + if (err instanceof Error) { + test.error = err; + test.errorDisplay = String(err.stack).split('\n') + .concat("\t" + su.repeatCharXTimes('_', 70)) + .map(stckMapFn) + .filter(function (item) { return item; }) + .join('\n') + .concat('\n'); } - test.error = null; - if (err) { - var sumanFatal = err.sumanFatal; - if (err instanceof Error) { - test.error = err; - test.errorDisplay = String(err.stack).split('\n') - .concat("\t" + su.repeatCharXTimes('_', 70)) - .map(stckMapFn) - .filter(function (item) { return item; }) - .join('\n') - .concat('\n'); - } - else if (typeof err.stack === 'string') { - test.error = err; - test.errorDisplay = String(err.stack).split('\n') - .concat("\t" + su.repeatCharXTimes('_', 70)) - .map(stckMapFn) - .filter(function (item) { return item; }) - .join('\n') - .concat('\n'); - } - else { - throw new Error('Suman internal implementation error => invalid error format, please report this.'); - } - if (su.isSumanDebug()) { - _suman.writeTestError('\n\nTest error: ' + test.desc + '\n\t' + 'stack: ' + test.error.stack + '\n\n'); - } - testErrors.push(test.error); + else if (typeof err.stack === 'string') { + test.error = err; + test.errorDisplay = String(err.stack).split('\n') + .concat("\t" + su.repeatCharXTimes('_', 70)) + .map(stckMapFn) + .filter(function (item) { return item; }) + .join('\n') + .concat('\n'); } - if (test.error) { - test.error.isFromTest = true; + else { + throw new Error('Suman internal implementation error => invalid error format, please report this.'); } - suman.logResult(test); - return test.error; - }; + if (su.isSumanDebug()) { + _suman.writeTestError('\n\nTest error: ' + test.desc + '\n\t' + 'stack: ' + test.error.stack + '\n\n'); + } + testErrors.push(test.error); + } + if (test.error) { + test.error.isFromTest = true; + } + return test.error; }; exports.makeTheTrap = function (suman, gracefulExit) { var handleTest = make_handle_test_1.makeHandleTest(suman, gracefulExit); - var handleTestResult = makeHandleTestResults(suman); var handleBeforeOrAfterEach = make_handle_each_1.makeHandleBeforeOrAfterEach(suman, gracefulExit); return function runTheTrap(self, test, opts, cb) { if (_suman.uncaughtExceptionTriggered) { @@ -139,17 +133,11 @@ exports.makeTheTrap = function (suman, gracefulExit) { async.series([ function (cb) { var handleTestContainer = function () { - handleTest(self, test, function (err, result) { + handleTest(self, test, function (err, potentialTestError) { general_1.implementationError(err); - var $result = handleTestResult(result, test); - if (sumanOpts.bail) { - gracefulExit($result, function () { - process.nextTick(cb, null, result); - }); - } - else { - process.nextTick(cb, null, result); - } + handleTestError(potentialTestError, test); + suman.logResult(test); + cb(null); }); }; if (delaySum) { diff --git a/lib/test-suite-helpers/make-the-trap.ts b/lib/test-suite-helpers/make-the-trap.ts index cfef7def..4616167b 100755 --- a/lib/test-suite-helpers/make-the-trap.ts +++ b/lib/test-suite-helpers/make-the-trap.ts @@ -26,231 +26,212 @@ const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); import {makeHandleTest} from './make-handle-test'; import {makeHandleBeforeOrAfterEach} from './make-handle-each'; import {implementationError} from '../helpers/general'; -const rb = _suman.resultBroadcaster = (_suman.resultBroadcaster || new EE()); +const rb = _suman.resultBroadcaster = _suman.resultBroadcaster || new EE(); const testErrors = _suman.testErrors = _suman.testErrors || []; const errors = _suman.sumanRuntimeErrors = _suman.sumanRuntimeErrors || []; //////////////////////////////////////////////////////////////////////////////// const getAllBeforesEaches = function (zuite: ITestSuite) { - + const beforeEaches: Array> = []; beforeEaches.unshift(zuite.getBeforeEaches()); - + if (!zuite.alreadyHandledAfterAllParentHooks) { zuite.alreadyHandledAfterAllParentHooks = true; beforeEaches.unshift(zuite.getAfterAllParentHooks()); } - + const getParentBefores = function (parent: ITestSuite) { beforeEaches.unshift(parent.getBeforeEaches()); if (parent.parent) { getParentBefores(parent.parent); } }; - + if (zuite.parent) { getParentBefores(zuite.parent); } - + return _.flatten(beforeEaches); }; ////////////////////////////////////////////////////////////////////////////////////////// const getAllAfterEaches = function (zuite: ITestSuite) { - + const afterEaches: Array> = []; afterEaches.push(zuite.getAfterEaches()); - + const getParentAfters = function (parent: ITestSuite) { afterEaches.push(parent.getAfterEaches()); if (parent.parent) { getParentAfters(parent.parent); } }; - + if (zuite.parent) { getParentAfters(zuite.parent); } - + return _.flatten(afterEaches); }; - ////////////////////////////////////////////////////////// const stckMapFn = function (item: string, index: number) { - + const fst = _suman.sumanOpts && _suman.sumanOpts.full_stack_traces; - - if(!item){ + + if (!item) { return ''; } - + if (index === 0) { return '\t' + item; } - + if (fst) { return su.padWithXSpaces(4) + item; } - + if ((String(item).match(/\//) || String(item).match('______________')) && !String(item).match(/\/node_modules\//) && !String(item).match(/internal\/process\/next_tick.js/)) { return su.padWithXSpaces(4) + item; } - + }; -///////////////////////////////////////////////////////////////////////////////////// - - const makeHandleTestResults = function (suman: ISuman) { - - return function handleTestError(err: IPseudoError, test: ITestDataObj) { - - if (_suman.uncaughtExceptionTriggered) { - _suman.log.error(`runtime error => "UncaughtException:Triggered" => halting program.\n[${__filename}]`); - return; +const handleTestError = function (err: IPseudoError, test: ITestDataObj) { + + if (_suman.uncaughtExceptionTriggered) { + _suman.log.error(`runtime error => "UncaughtException:Triggered" => halting program.\n[${__filename}]`); + return; + } + + if (err) { + + if (err instanceof Error) { + + test.error = err; + test.errorDisplay = String(err.stack).split('\n') + .concat(`\t${su.repeatCharXTimes('_', 70)}`) + .map(stckMapFn) + .filter(item => item) + .join('\n') + .concat('\n'); + } - - test.error = null; - - if (err) { - - const sumanFatal = err.sumanFatal; - - if (err instanceof Error) { - - test.error = err; - test.errorDisplay = String(err.stack).split('\n') - .concat(`\t${su.repeatCharXTimes('_',70)}`) - .map(stckMapFn) - .filter(item => item) - .join('\n') - .concat('\n'); - - } - else if (typeof err.stack === 'string') { - - test.error = err; - test.errorDisplay = String(err.stack).split('\n') - .concat(`\t${su.repeatCharXTimes('_',70)}`) - .map(stckMapFn) - .filter(item => item) - .join('\n') - .concat('\n'); - } - else { - throw new Error('Suman internal implementation error => invalid error format, please report this.'); - } - - if (su.isSumanDebug()) { - _suman.writeTestError('\n\nTest error: ' + test.desc + '\n\t' + 'stack: ' + test.error.stack + '\n\n'); - } - - testErrors.push(test.error); + else if (typeof err.stack === 'string') { + + test.error = err; + test.errorDisplay = String(err.stack).split('\n') + .concat(`\t${su.repeatCharXTimes('_', 70)}`) + .map(stckMapFn) + .filter(item => item) + .join('\n') + .concat('\n'); } - - if (test.error) { - test.error.isFromTest = true; + else { + throw new Error('Suman internal implementation error => invalid error format, please report this.'); } - - suman.logResult(test); - return test.error; + + if (su.isSumanDebug()) { + _suman.writeTestError('\n\nTest error: ' + test.desc + '\n\t' + 'stack: ' + test.error.stack + '\n\n'); + } + + testErrors.push(test.error); + } + + if (test.error) { + test.error.isFromTest = true; } + + return test.error; }; - //////////////////////////////////////////////////////////////////////////////// export const makeTheTrap = function (suman: ISuman, gracefulExit: Function) { - + const handleTest = makeHandleTest(suman, gracefulExit); - const handleTestResult = makeHandleTestResults(suman); const handleBeforeOrAfterEach = makeHandleBeforeOrAfterEach(suman, gracefulExit); - - return function runTheTrap(self: ITestSuite, test: ITestDataObj, opts: IItOpts, cb: Function) { - + + return function runTheTrap(self: ITestSuite, test: ITestDataObj, opts: Partial, cb: Function) { + if (_suman.uncaughtExceptionTriggered) { _suman.log.error(`runtime error => "uncaughtException" event => halting program.\n[${__filename}]`); return; } - + const sumanOpts = suman.opts, sumanConfig = suman.config; let delaySum = 0; //TODO: is this correct? - + if (test.stubbed) { rb.emit(String(events.TEST_CASE_END), test); rb.emit(String(events.TEST_CASE_STUBBED), test); return process.nextTick(cb, null); } - + if (test.skipped) { rb.emit(String(events.TEST_CASE_END), test); rb.emit(String(events.TEST_CASE_SKIPPED), test); return process.nextTick(cb, null); } - + const parallel = sumanOpts.parallel || (opts.parallel && !_suman.sumanOpts.series); - + async.eachSeries(getAllBeforesEaches(self), function (aBeforeEach: IBeforeEachObj, cb: Function) { handleBeforeOrAfterEach(self, test, aBeforeEach, cb); }, function doneWithBeforeEaches(err: IPseudoError) { - + implementationError(err); - + if (parallel) { delaySum += (test.delay || 0); } else { delaySum = 0; } - + async.series([ function (cb: Function) { - + const handleTestContainer = function () { - handleTest(self, test, function (err: IPseudoError, result: any) { + handleTest(self, test, function (err: null, potentialTestError: Error) { implementationError(err); - let $result = handleTestResult(result, test); - if (sumanOpts.bail) { - gracefulExit($result, function () { - process.nextTick(cb, null, result); - }); - } - else { - process.nextTick(cb, null, result); - } + handleTestError(potentialTestError, test); + suman.logResult(test); + cb(null); }); }; - + if (delaySum) { // if non-zero / non-falsy value setTimeout(handleTestContainer, delaySum); } else { handleTestContainer(); } - }, - + function (cb: Function) { - + async.eachSeries(getAllAfterEaches(self), function (aAfterEach: IAFterEachObj, cb: Function) { - handleBeforeOrAfterEach(self, test, aAfterEach, cb); - }, function done(err: IPseudoError) { - implementationError(err); - process.nextTick(cb); - }); - + handleBeforeOrAfterEach(self, test, aAfterEach, cb); + }, + function done(err: IPseudoError) { + implementationError(err); + process.nextTick(cb); + }); + } ], function doneWithTests(err: IPseudoError, results: Array) { err && console.error('Suman implementation error => the following error should not be present => ', err); cb(null, results); }); - + }); } - + }; 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 d4405abc..d62774a0 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 @@ -34,11 +34,11 @@ exports.makeNotifyParent = function (suman, gracefulExit, handleBeforesAndAfters } parent.afterHooksCallback = function (cb) { parent.alreadyStartedAfterHooks = true; - async.mapSeries(parent.getAfters(), function (aBeforeOrAfter, cb) { + async.eachSeries(parent.getAfters(), function (aBeforeOrAfter, cb) { handleBeforesAndAfters(child, aBeforeOrAfter, cb); - }, function complete(err, results) { + }, function complete(err) { general_1.implementationError(err); - gracefulExit(results, function () { + process.nextTick(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 b3ddfdf8..aa957d7e 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 @@ -62,14 +62,13 @@ export const makeNotifyParent = function (suman: ISuman, gracefulExit: Function, parent.alreadyStartedAfterHooks = true; - async.mapSeries(parent.getAfters(), function (aBeforeOrAfter: IOnceHookObj, cb: Function) { + async.eachSeries(parent.getAfters(), function (aBeforeOrAfter: IOnceHookObj, cb: Function) { handleBeforesAndAfters(child, aBeforeOrAfter, cb); }, - function complete(err: IPseudoError, results: Array) { - + function complete(err: IPseudoError) { implementationError(err); - gracefulExit(results, function () { + process.nextTick(function () { notifyParentThatChildIsComplete(parent, cb); }); }); diff --git a/lib/test-suite-helpers/suman-methods.d.ts b/lib/test-suite-helpers/suman-methods.d.ts index acabe58a..3ec6ac94 100755 --- a/lib/test-suite-helpers/suman-methods.d.ts +++ b/lib/test-suite-helpers/suman-methods.d.ts @@ -1,2 +1,3 @@ import { Suman } from "../suman"; -export declare const makeSumanMethods: (suman: Suman, TestBlock: any, gracefulExit: Function, notifyParent: Function) => any; +import { TestBlockBase } from "./make-test-suite"; +export declare const makeSumanMethods: (suman: Suman, TestBlock: typeof TestBlockBase, gracefulExit: Function, notifyParent: Function) => any; diff --git a/lib/test-suite-helpers/suman-methods.ts b/lib/test-suite-helpers/suman-methods.ts index 71dfe777..fc8f9632 100755 --- a/lib/test-suite-helpers/suman-methods.ts +++ b/lib/test-suite-helpers/suman-methods.ts @@ -44,6 +44,8 @@ import {makeBeforeEach} from '../test-suite-methods/make-before-each'; import {makeBefore} from '../test-suite-methods/make-before'; import {makeInject} from '../test-suite-methods/make-inject'; import {makeDescribe} from '../test-suite-methods/make-describe'; +import {TestBlockBase} from "./make-test-suite"; + ///////////////////////////////////////////////////////////////////// @@ -203,9 +205,10 @@ const addDefine = function (fn: any, Clazz: typeof DefineObject) { }; -export const makeSumanMethods = function (suman: ISuman, TestBlock: TestBlockBase, +export const makeSumanMethods = function (suman: ISuman, TestBlock: typeof TestBlockBase, gracefulExit: Function, notifyParent: Function): any { + /* NOTE: diff --git a/lib/test-suite-helpers/t-proto-hook.d.ts b/lib/test-suite-helpers/t-proto-hook.d.ts deleted file mode 100755 index c13a816d..00000000 --- a/lib/test-suite-helpers/t-proto-hook.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { IAssertObj, IHandleError, IHookObj, IHookParam } from "suman-types/dts/test-suite"; -export declare const makeHookObj: (hook: IHookObj, assertCount: IAssertObj, handleError: IHandleError, fini: Function) => IHookParam; diff --git a/lib/test-suite-helpers/t-proto-hook.js b/lib/test-suite-helpers/t-proto-hook.js deleted file mode 100755 index 533c5b65..00000000 --- a/lib/test-suite-helpers/t-proto-hook.js +++ /dev/null @@ -1,36 +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 chai = require('chai'); -var chaiAssert = chai.assert; -var _suman = global.__suman = (global.__suman || {}); -var t_proto_1 = require("./t-proto"); -var badProps = { - inspect: true, - constructor: true -}; -exports.makeHookObj = function (hook, assertCount, handleError, fini) { - var planCalled = false; - var v = Object.create(t_proto_1.tProto); - v.__hook = hook; - v.__handle = v.__handleErr = handleError; - v.__fini = fini; - v.plan = function (num) { - if (planCalled) { - _suman.writeTestError(new Error('Suman warning => plan() called more than once.').stack); - return; - } - planCalled = true; - if (hook.planCountExpected !== undefined) { - _suman.writeTestError(new Error(' => Suman warning => plan() called, even though plan was already passed as an option.').stack); - } - assert(Number.isInteger(num), 'Suman usage error => value passed to plan() is not an integer.'); - hook.planCountExpected = v.planCountExpected = num; - }; - v.confirm = function () { - assertCount.num++; - }; - return v; -}; diff --git a/lib/test-suite-helpers/t-proto-hook.ts b/lib/test-suite-helpers/t-proto-hook.ts deleted file mode 100755 index b3d8f92d..00000000 --- a/lib/test-suite-helpers/t-proto-hook.ts +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -//dts -import {IAssertObj, IHandleError, IHookObj, IHookParam} from "suman-types/dts/test-suite"; -import {IGlobalSumanObj} from "suman-types/dts/global"; -import AssertStatic = Chai.AssertStatic; - -//polyfills -const process = require('suman-browser-polyfills/modules/process'); -const global = require('suman-browser-polyfills/modules/global'); - -//core -import assert = require('assert'); -const chai = require('chai'); -const chaiAssert = chai.assert; - -//project -const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); -import {tProto} from './t-proto'; - -//////////////////////////////////////////////////////////////////////////////////// - -interface IBadProps { - [key: string]: true -} - -let badProps = { - inspect: true, - constructor: true -}; - -///////////////////////////////////////////////////////////////////////////////// - -export const makeHookObj = function (hook: IHookObj, assertCount: IAssertObj, - handleError: IHandleError, fini: Function): IHookParam { - - let planCalled = false; - const v = Object.create(tProto); - - v.__hook = hook; - v.__handle = v.__handleErr = handleError; - v.__fini = fini; - - - v.plan = function (num: number) { - if (planCalled) { - _suman.writeTestError(new Error('Suman warning => plan() called more than once.').stack); - return; - } - - planCalled = true; - if (hook.planCountExpected !== undefined) { - _suman.writeTestError(new Error(' => Suman warning => plan() called, even though plan was already passed as an option.').stack); - } - - assert(Number.isInteger(num), 'Suman usage error => value passed to plan() is not an integer.'); - hook.planCountExpected = v.planCountExpected = num; - }; - - v.confirm = function () { - assertCount.num++; - }; - - return v; - -}; - diff --git a/lib/test-suite-helpers/t-proto-inject.d.ts b/lib/test-suite-helpers/t-proto-inject.d.ts deleted file mode 100644 index 03fbb4db..00000000 --- a/lib/test-suite-helpers/t-proto-inject.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { IAssertObj, IHandleError, IHookObj, IHookParam } from "suman-types/dts/test-suite"; -import { ITestSuite } from 'suman-types/dts/test-suite'; -export declare const makeInjectObj: (inject: IHookObj, assertCount: IAssertObj, suite: ITestSuite, values: any[], handleError: IHandleError, fini: Function) => IHookParam; diff --git a/lib/test-suite-helpers/t-proto-inject.js b/lib/test-suite-helpers/t-proto-inject.js deleted file mode 100644 index 9b407711..00000000 --- a/lib/test-suite-helpers/t-proto-inject.js +++ /dev/null @@ -1,88 +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 chai = require('chai'); -var chaiAssert = chai.assert; -var su = require("suman-utils"); -var async = require("async"); -var _suman = global.__suman = (global.__suman || {}); -var t_proto_1 = require("./t-proto"); -var badProps = { - inspect: true, - constructor: true -}; -exports.makeInjectObj = function (inject, assertCount, suite, values, handleError, fini) { - var planCalled = false; - var v = Object.create(t_proto_1.tProto); - var valuesMap = {}; - v.__hook = inject; - v.__handle = v.__handleErr = handleError; - v.__fini = fini; - v.registerKey = v.register = function (k, val) { - assert(k && typeof k === 'string', 'key must be a string.'); - if (k in valuesMap) { - throw new Error("Injection key '" + k + "' has already been added."); - } - if (k in suite.injectedValues) { - throw new Error("Injection key '" + k + "' has already been added."); - } - valuesMap[k] = true; - values.push({ k: k, val: val }); - return Promise.resolve(val); - }; - v.registerFnsMap = v.registerFnMap = function (o) { - assert(su.isObject(o), 'value must be a non-array object.'); - return new Promise(function (resolve, reject) { - async.series(o, function (err, results) { - console.log('err => ', err); - console.log('results => ', results); - if (err) { - return reject(err); - } - Object.keys(results).forEach(function (k) { - if (k in valuesMap) { - return reject(new Error("Injection key '" + k + "' has already been added.")); - } - if (k in suite.injectedValues) { - return reject(new Error("Injection key '" + k + "' has already been added.")); - } - valuesMap[k] = true; - values.push({ k: k, val: results[k] }); - }); - resolve(results); - }); - }); - }; - v.registerMap = v.registerPromisesMap = function (o) { - var keys = Object.keys(o); - return Promise.all(keys.map(function (k) { - if (k in valuesMap) { - throw new Error("Injection key '" + k + "' has already been added."); - } - if (k in suite.injectedValues) { - throw new Error("Injection key '" + k + "' has already been added."); - } - valuesMap[k] = true; - values.push({ k: k, val: o[k] }); - return o[k]; - })); - }; - v.plan = function (num) { - if (planCalled) { - _suman.writeTestError(new Error('Suman warning => plan() called more than once.').stack); - return; - } - planCalled = true; - if (inject.planCountExpected !== undefined) { - _suman.writeTestError(new Error(' => Suman warning => plan() called, even though plan was already passed as an option.').stack); - } - assert(Number.isInteger(num), 'Suman usage error => value passed to plan() is not an integer.'); - inject.planCountExpected = v.planCountExpected = num; - }; - v.confirm = function () { - assertCount.num++; - }; - return v; -}; diff --git a/lib/test-suite-helpers/t-proto-inject.ts b/lib/test-suite-helpers/t-proto-inject.ts deleted file mode 100644 index b58560a7..00000000 --- a/lib/test-suite-helpers/t-proto-inject.ts +++ /dev/null @@ -1,140 +0,0 @@ -'use strict'; - -//dts -import {IAssertObj, IHandleError, IHookObj, IHookParam} from "suman-types/dts/test-suite"; -import {IGlobalSumanObj} from "suman-types/dts/global"; -import AssertStatic = Chai.AssertStatic; -import {ITestSuite} from 'suman-types/dts/test-suite'; -import {ErrorCallback, Dictionary} from 'async'; - -//polyfills -const process = require('suman-browser-polyfills/modules/process'); -const global = require('suman-browser-polyfills/modules/global'); - -//core -import assert = require('assert'); -const chai = require('chai'); -const chaiAssert = chai.assert; - -//npm -import su = require('suman-utils'); -import async = require('async'); - -//project -const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); -import {tProto} from './t-proto'; - -//////////////////////////////////////////////////////////////////////////////////// - -interface IBadProps { - [key: string]: true -} - -let badProps = { - inspect: true, - constructor: true -}; - -///////////////////////////////////////////////////////////////////////////////// - -export const makeInjectObj = function (inject: IHookObj, assertCount: IAssertObj, suite: ITestSuite, - values: Array, - handleError: IHandleError, fini: Function): IHookParam { - - let planCalled = false; - const v = Object.create(tProto); - const valuesMap = {} as any; - - v.__hook = inject; - v.__handle = v.__handleErr = handleError; - v.__fini = fini; - - - v.registerKey = v.register = function (k: string, val: any): Promise { - assert(k && typeof k === 'string', 'key must be a string.'); - - if (k in valuesMap) { - throw new Error(`Injection key '${k}' has already been added.`); - } - if (k in suite.injectedValues) { - throw new Error(`Injection key '${k}' has already been added.`); - } - - valuesMap[k] = true; // mark as reserved - values.push({k, val}); - return Promise.resolve(val); - }; - - v.registerFnsMap = v.registerFnMap = function (o: Dictionary): Promise { - - assert(su.isObject(o), 'value must be a non-array object.'); - - return new Promise(function (resolve, reject) { - async.series(o, function (err: Error, results: Dictionary) { - - console.log('err => ', err); - console.log('results => ', results); - - if (err) { - return reject(err); - } - - Object.keys(results).forEach(function (k) { - if (k in valuesMap) { - return reject(new Error(`Injection key '${k}' has already been added.`)); - } - if (k in suite.injectedValues) { - return reject(new Error(`Injection key '${k}' has already been added.`)); - } - - valuesMap[k] = true; // mark as reserved - values.push({k, val: results[k]}); - }); - - resolve(results); - }); - }); - }; - - v.registerMap = v.registerPromisesMap = function (o: Dictionary): Promise> { - - let keys = Object.keys(o); - return Promise.all(keys.map(function (k) { - - if (k in valuesMap) { - throw new Error(`Injection key '${k}' has already been added.`); - } - if (k in suite.injectedValues) { - throw new Error(`Injection key '${k}' has already been added.`); - } - - valuesMap[k] = true; // mark as reserved - values.push({k, val: o[k]}); - return o[k]; - })); - }; - - - v.plan = function (num: number) { - if (planCalled) { - _suman.writeTestError(new Error('Suman warning => plan() called more than once.').stack); - return; - } - - planCalled = true; - if (inject.planCountExpected !== undefined) { - _suman.writeTestError(new Error(' => Suman warning => plan() called, even though plan was already passed as an option.').stack); - } - - assert(Number.isInteger(num), 'Suman usage error => value passed to plan() is not an integer.'); - inject.planCountExpected = v.planCountExpected = num; - }; - - v.confirm = function () { - assertCount.num++; - }; - - return v; - -}; - diff --git a/lib/test-suite-helpers/t-proto-test.d.ts b/lib/test-suite-helpers/t-proto-test.d.ts deleted file mode 100755 index 5a0412df..00000000 --- a/lib/test-suite-helpers/t-proto-test.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ITestDataObj } from "suman-types/dts/it"; -import { IHandleError, ITestCaseParam } from "suman-types/dts/test-suite"; -export interface IAssertCount { - num: number; -} -export declare const makeTestCase: (test: ITestDataObj, assertCount: IAssertCount, handleError: IHandleError, fini: Function) => ITestCaseParam; diff --git a/lib/test-suite-helpers/t-proto-test.js b/lib/test-suite-helpers/t-proto-test.js deleted file mode 100755 index c1bf075f..00000000 --- a/lib/test-suite-helpers/t-proto-test.js +++ /dev/null @@ -1,42 +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 chai = require('chai'); -var chaiAssert = chai.assert; -var _suman = global.__suman = (global.__suman || {}); -var t_proto_1 = require("./t-proto"); -var badProps = { - inspect: true, - constructor: true -}; -exports.makeTestCase = function (test, assertCount, handleError, fini) { - var planCalled = false; - var v = Object.create(t_proto_1.tProto); - v.value = test.value; - v.testId = test.testId; - v.desc = v.title = test.desc; - v.data = test.data; - v.__test = test; - v.__handle = v.__handleError = handleError; - v.__fini = fini; - v.plan = function (num) { - if (planCalled) { - _suman.writeTestError(new Error('Suman warning => t.plan() called more than once for ' + - 'the same test case.').stack); - return; - } - planCalled = true; - if (test.planCountExpected !== undefined) { - _suman.writeTestError(new Error('Suman warning => t.plan() called, even though plan ' + - 'was already passed as an option.').stack); - } - assert(Number.isInteger(num), 'Suman usage error => value passed to t.plan() is not an integer.'); - test.planCountExpected = v.planCountExpected = num; - }; - v.confirm = function () { - assertCount.num++; - }; - return v; -}; diff --git a/lib/test-suite-helpers/t-proto-test.ts b/lib/test-suite-helpers/t-proto-test.ts deleted file mode 100755 index a794aca8..00000000 --- a/lib/test-suite-helpers/t-proto-test.ts +++ /dev/null @@ -1,84 +0,0 @@ -'use strict'; - -//dts -import {IGlobalSumanObj} from "suman-types/dts/global"; -import {ITestDataObj} from "suman-types/dts/it"; -import {IHandleError, ITestCaseParam} from "suman-types/dts/test-suite"; -import AssertStatic = Chai.AssertStatic; - -//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'); - -//npm -const chai = require('chai'); -const chaiAssert = chai.assert; - -//project -const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); -import {tProto} from './t-proto'; - -////////////////////////////////////////////////////////////////////// - -export interface IAssertCount { - num: number -} - -interface IBadProps { - [key: string]: true -} - -/////////////////////////////////////////////////////////////////////// - -let badProps = { - inspect: true, - constructor: true -}; - -/////////////////////////////////////////////////////////////////////// - -export const makeTestCase = function (test: ITestDataObj, assertCount: IAssertCount, - handleError: IHandleError, fini: Function): ITestCaseParam { - - let planCalled = false; - const v = Object.create(tProto); - v.value = test.value; - v.testId = test.testId; - v.desc = v.title = test.desc; - v.data = test.data; - v.__test = test; - v.__handle = v.__handleError = handleError; - v.__fini = fini; - - - v.plan = function (num: number) { - - if (planCalled) { - _suman.writeTestError(new Error('Suman warning => t.plan() called more than once for ' + - 'the same test case.').stack); - return; - } - - planCalled = true; - if (test.planCountExpected !== undefined) { - _suman.writeTestError(new Error('Suman warning => t.plan() called, even though plan ' + - 'was already passed as an option.').stack); - } - - assert(Number.isInteger(num), 'Suman usage error => value passed to t.plan() is not an integer.'); - test.planCountExpected = v.planCountExpected = num; - - }; - - v.confirm = function () { - assertCount.num++; - }; - - return v; - -}; - diff --git a/lib/test-suite-helpers/t-proto.d.ts b/lib/test-suite-helpers/t-proto.d.ts deleted file mode 100755 index fa1305d8..00000000 --- a/lib/test-suite-helpers/t-proto.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const tProto: any; diff --git a/lib/test-suite-helpers/t-proto.js b/lib/test-suite-helpers/t-proto.js deleted file mode 100755 index 1bc34439..00000000 --- a/lib/test-suite-helpers/t-proto.js +++ /dev/null @@ -1,214 +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 EE = require("events"); -var chai = require('chai'); -var _suman = global.__suman = (global.__suman || {}); -var fproto = Object.create(Function.prototype); -var proto = Object.create(Object.assign(fproto, EE.prototype)); -proto.skip = function () { - (this.__hook || this.__test).skipped = true; - (this.__hook || this.__test).dynamicallySkipped = true; -}; -proto.done = proto.pass = proto.ctn = proto.fail = function () { - throw new Error('You have fired a callback for a test case or hook that was not callback oriented.'); -}; -proto.set = function (k, v) { - if (arguments.length < 2) { - throw new Error('Must pass both a key and value to "set" method.'); - } - return this.__shared.set(k, v); -}; -proto.get = function (k) { - if (arguments.length < 1) { - return this.__shared.getAll(); - } - return this.__shared.get(k); -}; -proto.gets = proto.getMany = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var self = this; - return args.map(function (k) { - return self.__shared.get(k); - }); -}; -proto.wrap = function (fn) { - var self = this; - return function () { - try { - return fn.apply(this, arguments); - } - catch (e) { - return self.__handle(e, false); - } - }; -}; -proto.wrapFinal = function (fn) { - var self = this; - return function () { - try { - fn.apply(this, arguments); - self.__fini(null); - } - catch (e) { - self.__handle(e, false); - } - }; -}; -proto.final = function (fn) { - try { - fn.apply(null, arguments); - this.__fini(null); - } - catch (e) { - this.__handle(e, false); - } -}; -var slice = Array.prototype.slice; -proto.wrapFinalErr = proto.wrapFinalErrFirst = proto.wrapFinalErrorFirst = proto.wrapFinalError = function (fn) { - var self = this; - return function (err) { - if (err) - return self.__handle(err, false); - try { - fn.apply(this, slice.call(arguments, 1)); - self.__fini(null); - } - catch (e) { - self.__handle(e, false); - } - }; -}; -proto.wrapErrorFirst = proto.wrapErrFirst = function (fn) { - var self = this; - return function (err) { - if (err) { - return self.__handle(err, false); - } - try { - return fn.apply(this, slice.call(arguments, 1)); - } - catch (e) { - return self.__handle(e, false); - } - }; -}; -proto.handleAssertions = proto.wrapAssertions = function (fn) { - try { - fn.call(null); - } - catch (e) { - this.__handleErr(e); - } -}; -proto.log = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - console.log.apply(console, [" [ '" + (this.desc || 'unknown') + "' ] "].concat(args)); -}; -proto.slow = function () { - this.timeout(30000); -}; -var assertCtx = { - val: null -}; -var expectCtx = { - val: null -}; -var expct = function () { - var ctx = expectCtx.val; - if (!ctx) { - throw new Error('Suman implementation error => expect context is not defined.'); - } - try { - return chai.expect.apply(chai.expect, arguments); - } - catch (e) { - return ctx.__handleError(e); - } -}; -var expectProxy = new Proxy(expct, { - get: function (target, prop) { - if (typeof prop === 'symbol') { - return Reflect.get.apply(Reflect, arguments); - } - var ctx = expectCtx.val; - if (!ctx) { - throw new Error('Suman implementation error => assert context is not defined.'); - } - if (!(prop in chai.expect)) { - try { - return Reflect.get.apply(Reflect, arguments); - } - catch (err) { - return ctx.__handleError(new Error("The assertion library used does not have a '" + prop + "' property or method.")); - } - } - return function () { - try { - return chai.expect[prop].apply(chai.expect, arguments); - } - catch (e) { - return ctx.__handleError(e); - } - }; - } -}); -Object.defineProperty(proto, 'expect', { - get: function () { - expectCtx.val = this; - return expectProxy; - } -}); -var assrt = function () { - var ctx = assertCtx.val; - if (!ctx) { - throw new Error('Suman implementation error => assert context is not defined.'); - } - try { - return chai.assert.apply(chai.assert, arguments); - } - catch (e) { - return ctx.__handleError(e); - } -}; -var p = new Proxy(assrt, { - get: function (target, prop) { - if (typeof prop === 'symbol') { - return Reflect.get.apply(Reflect, arguments); - } - var ctx = assertCtx.val; - if (!ctx) { - throw new Error('Suman implementation error => assert context is not defined.'); - } - if (!(prop in chai.assert)) { - try { - return Reflect.get.apply(Reflect, arguments); - } - catch (err) { - return ctx.__handleError(new Error("The assertion library used does not have a '" + prop + "' property or method.")); - } - } - return function () { - try { - return chai.assert[prop].apply(chai.assert, arguments); - } - catch (e) { - return ctx.__handleError(e); - } - }; - } -}); -Object.defineProperty(proto, 'assert', { - get: function () { - assertCtx.val = this; - return p; - } -}); -exports.tProto = proto; diff --git a/lib/test-suite-helpers/t-proto.ts b/lib/test-suite-helpers/t-proto.ts deleted file mode 100755 index 805d9fa0..00000000 --- a/lib/test-suite-helpers/t-proto.ts +++ /dev/null @@ -1,270 +0,0 @@ -'use strict'; - -//dts -import {IGlobalSumanObj, IPseudoError} from "suman-types/dts/global"; -import AssertStatic = Chai.AssertStatic; - -//polyfills -const process = require('suman-browser-polyfills/modules/process'); -const global = require('suman-browser-polyfills/modules/global'); - -//core -import EE = require('events'); - -//npm -import {freezeExistingProps} from 'freeze-existing-props'; -const chai = require('chai'); - - -//project -const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); - -///////////////////////////////////////////////////////////////////////////////// - -const fproto = Object.create(Function.prototype); -const proto = Object.create(Object.assign(fproto, EE.prototype)); - -proto.skip = function () { - (this.__hook || this.__test).skipped = true; - (this.__hook || this.__test).dynamicallySkipped = true; -}; - -proto.done = proto.pass = proto.ctn = proto.fail = function () { - throw new Error('You have fired a callback for a test case or hook that was not callback oriented.'); -}; - -proto.set = function (k: string, v: any) { - if (arguments.length < 2) { - throw new Error('Must pass both a key and value to "set" method.'); - } - return this.__shared.set(k, v); -}; - -proto.get = function (k?: string) { - if (arguments.length < 1) { - return this.__shared.getAll(); - } - return this.__shared.get(k); -}; - -proto.gets = proto.getMany = function (...args: Array) { - const self = this; - return args.map(function(k){ - return self.__shared.get(k); - }); -}; - -proto.wrap = function (fn: Function) { - const self = this; - return function () { - try { - return fn.apply(this, arguments); - } - catch (e) { - return self.__handle(e, false); - } - } -}; - -proto.wrapFinal = function (fn: Function) { - const self = this; - return function () { - try { - fn.apply(this, arguments); - self.__fini(null); - } - catch (e) { - self.__handle(e, false); - } - } -}; - -proto.final = function (fn: Function) { - try { - fn.apply(null, arguments); - this.__fini(null); - } - catch (e) { - this.__handle(e, false); - } -}; - -const slice = Array.prototype.slice; - -proto.wrapFinalErr = proto.wrapFinalErrFirst = proto.wrapFinalErrorFirst = proto.wrapFinalError = function (fn: Function) { - const self = this; - return function (err: Error) { - if (err) return self.__handle(err, false); - try { - fn.apply(this, slice.call(arguments, 1)); - self.__fini(null); - } - catch (e) { - self.__handle(e, false); - } - } -}; - -proto.wrapErrorFirst = proto.wrapErrFirst = function (fn: Function) { - const self = this; - return function (err: IPseudoError) { - if (err) { - return self.__handle(err, false); - } - try { - // remove the error-first argument - return fn.apply(this, slice.call(arguments, 1)); - } - catch (e) { - return self.__handle(e, false); - } - } -}; - -proto.handleAssertions = proto.wrapAssertions = function (fn: Function) { - try { - fn.call(null); - } - catch (e) { - this.__handleErr(e); - } -}; - -proto.log = function (...args: Array) { - console.log(` [ '${this.desc || 'unknown'}' ] `, ...args); -}; - -proto.slow = function () { - this.timeout(30000); -}; - -const assertCtx: any = { - // this is used to store the context - val: null -}; - -const expectCtx: any = { - // this is used to store the context - val: null -}; - - -const expct = > function () { - - const ctx = expectCtx.val; - - if (!ctx) { - throw new Error('Suman implementation error => expect context is not defined.'); - } - - try { - return chai.expect.apply(chai.expect, arguments); - } - catch (e) { - return ctx.__handleError(e); - } -}; - -const expectProxy = new Proxy(expct, { - get: function (target, prop) { - - if (typeof prop === 'symbol') { - return Reflect.get.apply(Reflect, arguments); - } - - const ctx = expectCtx.val; - - if (!ctx) { - throw new Error('Suman implementation error => assert context is not defined.'); - } - - if (!(prop in chai.expect)) { - try { - return Reflect.get.apply(Reflect, arguments); - } - catch (err) { - return ctx.__handleError( - new Error(`The assertion library used does not have a '${prop}' property or method.`) - ); - } - } - - return function () { - try { - return chai.expect[prop].apply(chai.expect, arguments); - } - catch (e) { - return ctx.__handleError(e); - } - } - } -}); - -Object.defineProperty(proto, 'expect', { - get: function () { - expectCtx.val = this; - return expectProxy; - } -}); - -const assrt = > function () { - - const ctx = assertCtx.val; - - if (!ctx) { - throw new Error('Suman implementation error => assert context is not defined.'); - } - - try { - return chai.assert.apply(chai.assert, arguments); - } - catch (e) { - return ctx.__handleError(e); - } -}; - -const p = new Proxy(assrt, { - get: function (target, prop) { - - if (typeof prop === 'symbol') { - return Reflect.get.apply(Reflect, arguments); - } - - const ctx = assertCtx.val; - - if (!ctx) { - throw new Error('Suman implementation error => assert context is not defined.'); - } - - if (!(prop in chai.assert)) { - try { - return Reflect.get.apply(Reflect, arguments); - } - catch (err) { - return ctx.__handleError( - new Error(`The assertion library used does not have a '${prop}' property or method.`) - ); - } - } - - return function () { - try { - return chai.assert[prop].apply(chai.assert, arguments); - } - catch (e) { - return ctx.__handleError(e); - } - } - } -}); - -Object.defineProperty(proto, 'assert', { - get: function () { - assertCtx.val = this; - return p; - } -}); - -// export const tProto = freezeExistingProps(proto); - -export const tProto = proto; diff --git a/lib/test-suite-methods/make-after.js b/lib/test-suite-methods/make-after.js index c0e4be93..62749038 100755 --- a/lib/test-suite-methods/make-after.js +++ b/lib/test-suite-methods/make-after.js @@ -77,7 +77,7 @@ exports.makeAfter = function (suman) { var obj = { ctx: zuite, timeout: opts.timeout || 11000, - desc: desc || fn.name, + desc: desc || fn.name || '(unknown after-all-hook name)', cb: opts.cb === true, throws: opts.throws, always: opts.always, diff --git a/lib/test-suite-methods/make-after.ts b/lib/test-suite-methods/make-after.ts index f544f446..4a8c9276 100755 --- a/lib/test-suite-methods/make-after.ts +++ b/lib/test-suite-methods/make-after.ts @@ -108,7 +108,7 @@ export const makeAfter = function (suman: ISuman): IAfterFn { let obj: IAfterObj = { ctx: zuite, timeout: opts.timeout || 11000, - desc: desc || fn.name, + desc: desc || fn.name || '(unknown after-all-hook name)', cb: opts.cb === true, // default to false throws: opts.throws, always: opts.always, diff --git a/lib/test-suite-methods/make-before.js b/lib/test-suite-methods/make-before.js index c86b3e72..d0abe72c 100755 --- a/lib/test-suite-methods/make-before.js +++ b/lib/test-suite-methods/make-before.js @@ -72,7 +72,7 @@ exports.makeBefore = function (suman) { else { var obj = { ctx: zuite, - desc: desc || fn.name || '(unknown before-hook name)', + desc: desc || fn.name || '(unknown before-all-hook name)', timeout: opts.timeoutVal || opts.timeout || 11000, cb: opts.cb === true, successEvents: opts.successEvents, diff --git a/lib/test-suite-methods/make-before.ts b/lib/test-suite-methods/make-before.ts index 4f25c7da..d8c15c4e 100755 --- a/lib/test-suite-methods/make-before.ts +++ b/lib/test-suite-methods/make-before.ts @@ -112,7 +112,7 @@ export const makeBefore = function (suman: ISuman): IBeforeFn { let obj = { ctx: zuite, - desc: desc || fn.name || '(unknown before-hook name)', + desc: desc || fn.name || '(unknown before-all-hook name)', timeout: opts.timeoutVal || opts.timeout || 11000, cb: opts.cb === true, // default to false successEvents: opts.successEvents, diff --git a/lib/test-suite-methods/make-describe.d.ts b/lib/test-suite-methods/make-describe.d.ts index f8f97e3e..97dc92e4 100755 --- a/lib/test-suite-methods/make-describe.d.ts +++ b/lib/test-suite-methods/make-describe.d.ts @@ -1,3 +1,4 @@ import { Suman } from "../suman"; import { IDescribeFn } from "suman-types/dts/describe"; -export declare const makeDescribe: (suman: Suman, gracefulExit: Function, TestBlock: any, notifyParentThatChildIsComplete: Function, blockInjector: Function) => IDescribeFn; +import { TestBlockBase } from "../test-suite-helpers/make-test-suite"; +export declare const makeDescribe: (suman: Suman, gracefulExit: Function, TestBlock: TestBlockBase, notifyParentThatChildIsComplete: Function, blockInjector: Function) => IDescribeFn; diff --git a/lib/test-suite-methods/make-describe.js b/lib/test-suite-methods/make-describe.js index 122beab2..a2baff25 100755 --- a/lib/test-suite-methods/make-describe.js +++ b/lib/test-suite-methods/make-describe.js @@ -102,7 +102,6 @@ exports.makeDescribe = function (suman, gracefulExit, TestBlock, notifyParentTha console.log('\n'); } if (!sumanOpts.force && !_suman.inBrowser) { - debugger; if (opts.skip && !sumanOpts.allow_skip && !sumanOpts.$allowSkip) { throw new Error('Test block was declared as "skipped" but "--allow-skip" / "--force" option not specified.'); } diff --git a/lib/test-suite-methods/make-describe.ts b/lib/test-suite-methods/make-describe.ts index c12e4f9c..46e6ea28 100755 --- a/lib/test-suite-methods/make-describe.ts +++ b/lib/test-suite-methods/make-describe.ts @@ -39,6 +39,7 @@ import {handleSetupComplete} from '../helpers/general'; import {handleInjections} from '../test-suite-helpers/handle-injections'; import {parseArgs} from '../helpers/general'; import {evalOptions} from '../helpers/general'; +import {TestBlockBase} from "../test-suite-helpers/make-test-suite"; /////////////////////////////////////////////////////////////////////// @@ -70,7 +71,7 @@ const handleBadOptions = function (opts: IDescribeOpts, typeName: string) { ////////////////////////////////////////////////////////////////////////////////////////////// -export const makeDescribe = function (suman: ISuman, gracefulExit: Function, TestBlock: any, +export const makeDescribe = function (suman: ISuman, gracefulExit: Function, TestBlock: TestBlockBase, notifyParentThatChildIsComplete: Function, blockInjector: Function): IDescribeFn { @@ -149,7 +150,6 @@ export const makeDescribe = function (suman: ISuman, gracefulExit: Function, Tes } if (!sumanOpts.force && !_suman.inBrowser) { - debugger; if (opts.skip && !sumanOpts.allow_skip && !sumanOpts.$allowSkip) { throw new Error('Test block was declared as "skipped" but "--allow-skip" / "--force" option not specified.'); } diff --git a/lib/test-suite-methods/make-it.js b/lib/test-suite-methods/make-it.js index eb9d4286..2be61761 100755 --- a/lib/test-suite-methods/make-it.js +++ b/lib/test-suite-methods/make-it.js @@ -133,6 +133,7 @@ exports.makeIt = function (suman) { parallel: isOverallParallel, mode: opts.mode, delay: opts.delay, + state: 'pending', cb: opts.cb === true, type: typeName, timeout: opts.timeout || 20000, diff --git a/lib/test-suite-methods/make-it.ts b/lib/test-suite-methods/make-it.ts index 6f55a365..9284e8e4 100755 --- a/lib/test-suite-methods/make-it.ts +++ b/lib/test-suite-methods/make-it.ts @@ -183,6 +183,7 @@ export const makeIt = function (suman: ISuman): ItFn { parallel: isOverallParallel, mode: opts.mode, delay: opts.delay, + state: 'pending', cb: opts.cb === true, // default to false type: typeName, timeout: opts.timeout || 20000, diff --git a/lib/test-suite-params/all-hook/all-hook-param.d.ts b/lib/test-suite-params/all-hook/all-hook-param.d.ts new file mode 100644 index 00000000..f94765e9 --- /dev/null +++ b/lib/test-suite-params/all-hook/all-hook-param.d.ts @@ -0,0 +1,11 @@ +import { IAssertObj, IHandleError, IHookObj } from 'suman-types/dts/test-suite'; +import { IAllHookParam } from 'suman-types/dts/params'; +import { ParamBase } from '../base'; +export declare class AllHookParam extends ParamBase implements IAllHookParam { + protected __planCalled: boolean; + protected __assertCount: IAssertObj; + protected planCountExpected: number; + constructor(hook: IHookObj, assertCount: IAssertObj, handleError: IHandleError, fini: Function); + plan(num: number): any; + confirm(): void; +} diff --git a/lib/test-suite-params/all-hook/all-hook-param.js b/lib/test-suite-params/all-hook/all-hook-param.js new file mode 100644 index 00000000..6e1ef885 --- /dev/null +++ b/lib/test-suite-params/all-hook/all-hook-param.js @@ -0,0 +1,59 @@ +'use strict'; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +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 chai = require('chai'); +var chaiAssert = chai.assert; +var _suman = global.__suman = (global.__suman || {}); +var base_1 = require("../base"); +var badProps = { + inspect: true, + constructor: true +}; +var AllHookParam = (function (_super) { + __extends(AllHookParam, _super); + function AllHookParam(hook, assertCount, handleError, fini) { + var _this = _super.call(this) || this; + _this.planCountExpected = null; + _this.__planCalled = false; + _this.__hook = hook; + _this.__handle = handleError; + _this.__fini = fini; + _this.__assertCount = assertCount; + return _this; + } + AllHookParam.prototype.plan = function (num) { + if (this.__planCalled) { + _suman.writeTestError(new Error('Suman warning => plan() called more than once.').stack); + return; + } + var hook = this.__hook; + this.__planCalled = true; + if (hook.planCountExpected !== undefined) { + _suman.writeTestError(new Error('Suman warning => plan() called, even though plan was already passed as an option.').stack); + } + try { + assert(Number.isInteger(num), 'Suman usage error => value passed to plan() is not an integer.'); + } + catch (err) { + return this.__handle(err); + } + hook.planCountExpected = this.planCountExpected = num; + }; + AllHookParam.prototype.confirm = function () { + this.__assertCount.num++; + }; + return AllHookParam; +}(base_1.ParamBase)); +exports.AllHookParam = AllHookParam; diff --git a/lib/test-suite-params/all-hook/all-hook-param.ts b/lib/test-suite-params/all-hook/all-hook-param.ts new file mode 100644 index 00000000..73639ce3 --- /dev/null +++ b/lib/test-suite-params/all-hook/all-hook-param.ts @@ -0,0 +1,84 @@ +'use strict'; + +//dts +import {IAssertObj, IHandleError, IHookObj} from 'suman-types/dts/test-suite'; +import {IGlobalSumanObj} from 'suman-types/dts/global'; +import {IAllHookParam} from 'suman-types/dts/params'; + +//polyfills +const process = require('suman-browser-polyfills/modules/process'); +const global = require('suman-browser-polyfills/modules/global'); + +//core +import assert = require('assert'); +const chai = require('chai'); +const chaiAssert = chai.assert; + +//project +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); +import {ParamBase} from '../base'; + +//////////////////////////////////////////////////////////////////////////////////// + +interface IBadProps { + [key: string]: true +} + +let badProps = { + inspect: true, + constructor: true +}; + +///////////////////////////////////////////////////////////////////////// + + +export class AllHookParam extends ParamBase implements IAllHookParam { + + protected __planCalled: boolean; + protected __assertCount: IAssertObj; + protected planCountExpected: number; + + constructor(hook: IHookObj, assertCount: IAssertObj, handleError: IHandleError, fini: Function) { + + super(); + + this.planCountExpected = null; + this.__planCalled = false; + this.__hook = hook; + this.__handle = handleError; + this.__fini = fini; + this.__assertCount = assertCount; + + } + + plan(num: number) { + + if (this.__planCalled) { + _suman.writeTestError(new Error('Suman warning => plan() called more than once.').stack); + return; + } + + const hook = this.__hook; + this.__planCalled = true; + + if (hook.planCountExpected !== undefined) { + _suman.writeTestError(new Error('Suman warning => plan() called, even though plan was already passed as an option.').stack); + } + + try { + assert(Number.isInteger(num), 'Suman usage error => value passed to plan() is not an integer.'); + } + catch (err) { + return this.__handle(err); + } + + hook.planCountExpected = this.planCountExpected = num; + } + + confirm() { + this.__assertCount.num++; + } + +} + + diff --git a/lib/test-suite-params/base.d.ts b/lib/test-suite-params/base.d.ts new file mode 100644 index 00000000..3b67ec5d --- /dev/null +++ b/lib/test-suite-params/base.d.ts @@ -0,0 +1,45 @@ +/// +import { IPseudoError } from "suman-types/dts/global"; +import { IHookObj } from "suman-types/dts/test-suite"; +import { ITestDataObj } from "suman-types/dts/it"; +import { VamootProxy } from "vamoot"; +import { IHookOrTestCaseParam } from "suman-types/dts/params"; +import EE = require('events'); +import * as chai from 'chai'; +export declare class ParamBase extends EE implements IHookOrTestCaseParam { + protected __hook: IHookObj; + protected __test: ITestDataObj; + protected __handle: Function; + protected __shared: VamootProxy; + protected __fini: Function; + protected callbackMode?: boolean; + assert: typeof chai.assert; + should: typeof chai.should; + expect: typeof chai.expect; + constructor(); + timeout(v: number): void; + done(): void; + skip(): void; + fatal(err: IPseudoError): void; + set(k: string, v: any): boolean; + get(k?: string): any; + getValues(...args: Array): any[]; + getMap(...args: Array): any; + wrap(fn: Function): () => any; + wrapFinal(fn: Function): () => void; + final(fn: Function): void; + log(...args: Array): void; + slow(): void; + wrapFinalErrorFirst(fn: Function): (err: Error) => any; + wrapErrorFirst(fn: Function): (err: IPseudoError) => any; + handleAssertions(fn: Function): any; +} +export interface ParamBase { + pass: typeof ParamBase.prototype.done; + ctn: typeof ParamBase.prototype.done; + fail: typeof ParamBase.prototype.done; + wrapFinalErrFirst: typeof ParamBase.prototype.wrapFinalErrorFirst; + wrapFinalErr: typeof ParamBase.prototype.wrapFinalErrorFirst; + wrapFinalError: typeof ParamBase.prototype.wrapFinalErrorFirst; + wrapErrFirst: typeof ParamBase.prototype.wrapErrorFirst; +} diff --git a/lib/test-suite-params/base.js b/lib/test-suite-params/base.js new file mode 100644 index 00000000..a84ae0c7 --- /dev/null +++ b/lib/test-suite-params/base.js @@ -0,0 +1,267 @@ +'use strict'; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var process = require('suman-browser-polyfills/modules/process'); +var global = require('suman-browser-polyfills/modules/global'); +var EE = require("events"); +var util = require("util"); +var su = require("suman-utils"); +var chai = require("chai"); +var _suman = global.__suman = (global.__suman || {}); +var badProps = { + inspect: true, + constructor: true +}; +var slice = Array.prototype.slice; +var ParamBase = (function (_super) { + __extends(ParamBase, _super); + function ParamBase() { + return _super.call(this) || this; + } + ParamBase.prototype.timeout = function (v) { + }; + ParamBase.prototype.done = function () { + this.__handle(new Error('You have fired a callback for a test case or hook that was not callback oriented.')); + }; + ParamBase.prototype.skip = function () { + (this.__hook || this.__test).skipped = true; + (this.__hook || this.__test).dynamicallySkipped = true; + }; + ParamBase.prototype.fatal = function (err) { + if (!err) { + err = new Error('t.fatal() was called by the developer, with a falsy first argument.'); + } + else if (!su.isObject(err)) { + var msg = 't.fatal() was called by the developer: '; + err = new Error(msg + util.inspect(err)); + } + err.sumanFatal = true; + this.__handle(err); + }; + ParamBase.prototype.set = function (k, v) { + if (arguments.length < 2) { + throw new Error('Must pass both a key and value to "set" method.'); + } + return this.__shared.set(k, v); + }; + ParamBase.prototype.get = function (k) { + if (arguments.length < 1) { + return this.__shared.getAll(); + } + return this.__shared.get(k); + }; + ParamBase.prototype.getValues = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var self = this; + return args.map(function (k) { + return self.__shared.get(k); + }); + }; + ParamBase.prototype.getMap = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var self = this; + var ret = {}; + args.forEach(function (a) { + ret[a] = self.__shared.get(a); + }); + return ret; + }; + ParamBase.prototype.wrap = function (fn) { + var self = this; + return function () { + try { + return fn.apply(this, arguments); + } + catch (e) { + return self.__handle(e, false); + } + }; + }; + ; + ParamBase.prototype.wrapFinal = function (fn) { + var self = this; + return function () { + try { + fn.apply(this, arguments); + self.__fini(null); + } + catch (e) { + self.__handle(e, false); + } + }; + }; + ParamBase.prototype.final = function (fn) { + try { + fn.apply(null, arguments); + this.__fini(null); + } + catch (e) { + this.__handle(e, false); + } + }; + ParamBase.prototype.log = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + console.log.apply(console, [" [ '" + (this.desc || 'unknown') + "' ] "].concat(args)); + }; + ParamBase.prototype.slow = function () { + this.timeout(30000); + }; + ParamBase.prototype.wrapFinalErrorFirst = function (fn) { + var self = this; + return function (err) { + if (err) { + return self.__handle(err, false); + } + try { + fn.apply(this, slice.call(arguments, 1)); + self.__fini(null); + } + catch (e) { + self.__handle(e, false); + } + }; + }; + ParamBase.prototype.wrapErrorFirst = function (fn) { + var self = this; + return function (err) { + if (err) { + return self.__handle(err, false); + } + try { + return fn.apply(this, slice.call(arguments, 1)); + } + catch (e) { + return self.__handle(e, false); + } + }; + }; + ParamBase.prototype.handleAssertions = function (fn) { + try { + return fn.call(null); + } + catch (e) { + return this.__handle(e); + } + }; + return ParamBase; +}(EE)); +exports.ParamBase = ParamBase; +var b = Object.setPrototypeOf(ParamBase.prototype, Function.prototype); +var proto = Object.assign(ParamBase.prototype, EE.prototype); +proto.pass = proto.ctn = proto.fail = proto.done; +proto.wrapFinalErrFirst = proto.wrapFinalErr = proto.wrapFinalError = proto.wrapFinalErrorFirst; +proto.wrapErrFirst = proto.wrapErrorFirst; +var assertCtx = { + val: null +}; +var expectCtx = { + val: null +}; +var expct = function () { + var ctx = expectCtx.val; + if (!ctx) { + throw new Error('Suman implementation error => expect context is not defined.'); + } + try { + return chai.expect.apply(chai.expect, arguments); + } + catch (e) { + return ctx.__handle(e); + } +}; +var expectProxy = new Proxy(expct, { + get: function (target, prop) { + if (typeof prop === 'symbol') { + return Reflect.get.apply(Reflect, arguments); + } + var ctx = expectCtx.val; + if (!ctx) { + throw new Error('Suman implementation error => assert context is not defined.'); + } + if (!(prop in chai.expect)) { + try { + return Reflect.get.apply(Reflect, arguments); + } + catch (err) { + return ctx.__handle(new Error("The assertion library used does not have a '" + prop + "' property or method.")); + } + } + return function () { + try { + return chai.expect[prop].apply(chai.expect, arguments); + } + catch (e) { + return ctx.__handle(e); + } + }; + } +}); +Object.defineProperty(proto, 'expect', { + get: function () { + expectCtx.val = this; + return expectProxy; + } +}); +var assrt = function () { + var ctx = assertCtx.val; + if (!ctx) { + throw new Error('Suman implementation error => assert context is not defined.'); + } + try { + return chai.assert.apply(chai.assert, arguments); + } + catch (e) { + return ctx.__handle(e); + } +}; +var assertProxy = new Proxy(assrt, { + get: function (target, prop) { + if (typeof prop === 'symbol') { + return Reflect.get.apply(Reflect, arguments); + } + var ctx = assertCtx.val; + if (!ctx) { + throw new Error('Suman implementation error => assert context is not defined.'); + } + if (!(prop in chai.assert)) { + try { + return Reflect.get.apply(Reflect, arguments); + } + catch (err) { + return ctx.__handle(new Error("The assertion library used does not have a '" + prop + "' property or method.")); + } + } + return function () { + try { + return chai.assert[prop].apply(chai.assert, arguments); + } + catch (e) { + return ctx.__handle(e); + } + }; + } +}); +Object.defineProperty(proto, 'assert', { + get: function () { + assertCtx.val = this; + return assertProxy; + } +}); diff --git a/lib/test-suite-params/base.ts b/lib/test-suite-params/base.ts new file mode 100644 index 00000000..8581ac6a --- /dev/null +++ b/lib/test-suite-params/base.ts @@ -0,0 +1,349 @@ +'use strict'; + +//dts +import {IGlobalSumanObj, IPseudoError} from "suman-types/dts/global"; +import AssertStatic = Chai.AssertStatic; +import {IHookObj} from "suman-types/dts/test-suite"; +import {ITestDataObj} from "suman-types/dts/it"; +import {VamootProxy} from "vamoot"; +import {IHookOrTestCaseParam} from "suman-types/dts/params"; + +//polyfills +const process = require('suman-browser-polyfills/modules/process'); +const global = require('suman-browser-polyfills/modules/global'); + +//core +import EE = require('events'); +import util = require('util'); + +//npm +import su = require('suman-utils'); +import {freezeExistingProps} from 'freeze-existing-props'; +import * as chai from 'chai'; + +//project +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); + +///////////////////////////////////////////////////////////////////////////////// + +// const fproto = Object.create(Function.prototype); +// export const proto = Object.create(Object.assign(fproto, EE.prototype)); + +interface IBadProps { + [key: string]: true +} + +let badProps = { + inspect: true, + constructor: true +}; + + +const slice = Array.prototype.slice; + +export class ParamBase extends EE implements IHookOrTestCaseParam{ + + protected __hook: IHookObj; + protected __test: ITestDataObj; + protected __handle: Function; + protected __shared: VamootProxy; + protected __fini: Function; + protected callbackMode?: boolean; + assert: typeof chai.assert; + should: typeof chai.should; + expect: typeof chai.expect; + + constructor() { + super(); + } + + timeout(v:number){ + + } + + + done() { + this.__handle(new Error('You have fired a callback for a test case or hook that was not callback oriented.')); + } + + skip() { + (this.__hook || this.__test).skipped = true; + (this.__hook || this.__test).dynamicallySkipped = true; + } + + fatal(err: IPseudoError) { + if (!err) { + err = new Error('t.fatal() was called by the developer, with a falsy first argument.'); + } + else if (!su.isObject(err)) { + let msg = 't.fatal() was called by the developer: '; + err = new Error(msg + util.inspect(err)); + } + err.sumanFatal = true; + this.__handle(err); + } + + set(k: string, v: any) { + if (arguments.length < 2) { + throw new Error('Must pass both a key and value to "set" method.'); + } + return this.__shared.set(k, v); + } + + get(k?: string) { + if (arguments.length < 1) { + return this.__shared.getAll(); + } + return this.__shared.get(k); + } + + getValues(...args: Array) { + const self = this; + return args.map(function (k) { + return self.__shared.get(k); + }); + } + + getMap(...args: Array) { + const self = this; + const ret = {} as any; + args.forEach(function (a) { + ret[a] = self.__shared.get(a); + }); + return ret; + } + + wrap(fn: Function) { + const self = this; + return function () { + try { + return fn.apply(this, arguments); + } + catch (e) { + return self.__handle(e, false); + } + } + }; + + wrapFinal(fn: Function) { + const self = this; + return function () { + try { + fn.apply(this, arguments); + self.__fini(null); + } + catch (e) { + self.__handle(e, false); + } + } + } + + final(fn: Function) { + try { + fn.apply(null, arguments); + this.__fini(null); + } + catch (e) { + this.__handle(e, false); + } + } + + log(...args: Array) { + console.log(` [ '${this.desc || 'unknown'}' ] `, ...args); + } + + slow() { + this.timeout(30000); + } + + wrapFinalErrorFirst(fn: Function) { + const self = this; + return function (err: Error) { + if (err) { + return self.__handle(err, false); + } + try { + fn.apply(this, slice.call(arguments, 1)); + self.__fini(null); + } + catch (e) { + self.__handle(e, false); + } + } + } + + wrapErrorFirst(fn: Function) { + const self = this; + return function (err: IPseudoError) { + if (err) { + return self.__handle(err, false); + } + try { + // remove the error-first argument + return fn.apply(this, slice.call(arguments, 1)); + } + catch (e) { + return self.__handle(e, false); + } + } + } + + handleAssertions(fn: Function) { + try { + return fn.call(null); + } + catch (e) { + return this.__handle(e); + } + } + +} + +export interface ParamBase { + pass: typeof ParamBase.prototype.done; + ctn: typeof ParamBase.prototype.done; + fail: typeof ParamBase.prototype.done; + wrapFinalErrFirst: typeof ParamBase.prototype.wrapFinalErrorFirst; + wrapFinalErr: typeof ParamBase.prototype.wrapFinalErrorFirst; + wrapFinalError: typeof ParamBase.prototype.wrapFinalErrorFirst; + wrapErrFirst: typeof ParamBase.prototype.wrapErrorFirst; +} + +// Alternative: +const b = Object.setPrototypeOf(ParamBase.prototype, Function.prototype); +const proto = Object.assign(ParamBase.prototype, EE.prototype); + +// const proto = Object.assign(ParamBase.prototype, Function.prototype, EE.prototype); +proto.pass = proto.ctn = proto.fail = proto.done; +proto.wrapFinalErrFirst = proto.wrapFinalErr = proto.wrapFinalError = proto.wrapFinalErrorFirst; +proto.wrapErrFirst = proto.wrapErrorFirst; + + +const assertCtx: any = { + // this is used to store the context + val: null +}; + +const expectCtx: any = { + // this is used to store the context + val: null +}; + +const expct = > function () { + + const ctx = expectCtx.val; + + if (!ctx) { + throw new Error('Suman implementation error => expect context is not defined.'); + } + + try { + return chai.expect.apply(chai.expect, arguments); + } + catch (e) { + return ctx.__handle(e); + } +}; + +const expectProxy = new Proxy(expct, { + get: function (target, prop) { + + if (typeof prop === 'symbol') { + return Reflect.get.apply(Reflect, arguments); + } + + const ctx = expectCtx.val; + + if (!ctx) { + throw new Error('Suman implementation error => assert context is not defined.'); + } + + if (!(prop in chai.expect)) { + try { + return Reflect.get.apply(Reflect, arguments); + } + catch (err) { + return ctx.__handle( + new Error(`The assertion library used does not have a '${prop}' property or method.`) + ); + } + } + + return function () { + try { + return (chai.expect as any)[prop].apply(chai.expect, arguments); + } + catch (e) { + return ctx.__handle(e); + } + } + } +}); + +Object.defineProperty(proto, 'expect', { + get: function () { + expectCtx.val = this; + return expectProxy; + } +}); + +const assrt = > function () { + + const ctx = assertCtx.val; + + if (!ctx) { + throw new Error('Suman implementation error => assert context is not defined.'); + } + + try { + return chai.assert.apply(chai.assert, arguments); + } + catch (e) { + return ctx.__handle(e); + } +}; + +const assertProxy = new Proxy(assrt, { + get: function (target, prop) { + + if (typeof prop === 'symbol') { + return Reflect.get.apply(Reflect, arguments); + } + + const ctx = assertCtx.val; + + if (!ctx) { + throw new Error('Suman implementation error => assert context is not defined.'); + } + + if (!(prop in chai.assert)) { + try { + return Reflect.get.apply(Reflect, arguments); + } + catch (err) { + return ctx.__handle( + new Error(`The assertion library used does not have a '${prop}' property or method.`) + ); + } + } + + return function () { + try { + return (chai.assert as any)[prop].apply(chai.assert, arguments); + } + catch (e) { + return ctx.__handle(e); + } + } + } +}); + +Object.defineProperty(proto, 'assert', { + get: function () { + assertCtx.val = this; + return assertProxy; + } +}); + +// export const tProto = freezeExistingProps(proto); +// export const tProto = proto; diff --git a/lib/test-suite-params/each-hook/each-hook-param.d.ts b/lib/test-suite-params/each-hook/each-hook-param.d.ts new file mode 100644 index 00000000..049d4405 --- /dev/null +++ b/lib/test-suite-params/each-hook/each-hook-param.d.ts @@ -0,0 +1,11 @@ +import { IAssertObj, IHandleError, IHookObj } from 'suman-types/dts/test-suite'; +import { IEachHookParam } from 'suman-types/dts/params'; +import { ParamBase } from '../base'; +export declare class EachHookParam extends ParamBase implements IEachHookParam { + protected __planCalled: boolean; + protected __assertCount: IAssertObj; + protected planCountExpected: number; + constructor(hook: IHookObj, assertCount: IAssertObj, handleError: IHandleError, fini: Function); + plan(num: number): any; + confirm(): void; +} diff --git a/lib/test-suite-params/each-hook/each-hook-param.js b/lib/test-suite-params/each-hook/each-hook-param.js new file mode 100644 index 00000000..128dd789 --- /dev/null +++ b/lib/test-suite-params/each-hook/each-hook-param.js @@ -0,0 +1,58 @@ +'use strict'; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +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 chai = require('chai'); +var chaiAssert = chai.assert; +var _suman = global.__suman = (global.__suman || {}); +var base_1 = require("../base"); +var badProps = { + inspect: true, + constructor: true +}; +var EachHookParam = (function (_super) { + __extends(EachHookParam, _super); + function EachHookParam(hook, assertCount, handleError, fini) { + var _this = _super.call(this) || this; + _this.__planCalled = false; + _this.__hook = hook; + _this.__handle = handleError; + _this.__fini = fini; + _this.__assertCount = assertCount; + return _this; + } + EachHookParam.prototype.plan = function (num) { + if (this.__planCalled) { + _suman.writeTestError(new Error('Suman warning => plan() called more than once.').stack); + return; + } + var hook = this.__hook; + this.__planCalled = true; + if (hook.planCountExpected !== undefined) { + _suman.writeTestError(new Error(' => Suman warning => plan() called, even though plan was already passed as an option.').stack); + } + try { + assert(Number.isInteger(num), 'Suman usage error => value passed to plan() is not an integer.'); + } + catch (err) { + return this.__handle(err); + } + hook.planCountExpected = this.planCountExpected = num; + }; + EachHookParam.prototype.confirm = function () { + this.__assertCount.num++; + }; + return EachHookParam; +}(base_1.ParamBase)); +exports.EachHookParam = EachHookParam; diff --git a/lib/test-suite-params/each-hook/each-hook-param.ts b/lib/test-suite-params/each-hook/each-hook-param.ts new file mode 100644 index 00000000..e7c04fd2 --- /dev/null +++ b/lib/test-suite-params/each-hook/each-hook-param.ts @@ -0,0 +1,84 @@ +'use strict'; + +//dts +import {IAssertObj, IHandleError, IHookObj} from 'suman-types/dts/test-suite'; +import {IGlobalSumanObj} from 'suman-types/dts/global'; +import {IEachHookParam} from 'suman-types/dts/params'; +import AssertStatic = Chai.AssertStatic; + +//polyfills +const process = require('suman-browser-polyfills/modules/process'); +const global = require('suman-browser-polyfills/modules/global'); + +//core +import assert = require('assert'); +const chai = require('chai'); +const chaiAssert = chai.assert; + +//project +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); +import {ParamBase} from '../base'; + +//////////////////////////////////////////////////////////////////////////////////// + +interface IBadProps { + [key: string]: true +} + +let badProps = { + inspect: true, + constructor: true +}; + +///////////////////////////////////////////////////////////////////////// + +export class EachHookParam extends ParamBase implements IEachHookParam { + + protected __planCalled: boolean; + protected __assertCount: IAssertObj; + protected planCountExpected: number; + + constructor(hook: IHookObj, assertCount: IAssertObj, + handleError: IHandleError, fini: Function) { + + super(); + + this.__planCalled = false; + this.__hook = hook; + this.__handle = handleError; + this.__fini = fini; + this.__assertCount = assertCount; + + } + + plan(num: number) { + + if (this.__planCalled) { + _suman.writeTestError(new Error('Suman warning => plan() called more than once.').stack); + return; + } + + const hook = this.__hook; + this.__planCalled = true; + + if (hook.planCountExpected !== undefined) { + _suman.writeTestError(new Error(' => Suman warning => plan() called, even though plan was already passed as an option.').stack); + } + + try { + assert(Number.isInteger(num), 'Suman usage error => value passed to plan() is not an integer.'); + } + catch (err) { + return this.__handle(err); + } + + hook.planCountExpected = this.planCountExpected = num; + } + + confirm() { + this.__assertCount.num++; + } + +} + + diff --git a/lib/test-suite-params/inject/inject-param.d.ts b/lib/test-suite-params/inject/inject-param.d.ts new file mode 100644 index 00000000..d60830c0 --- /dev/null +++ b/lib/test-suite-params/inject/inject-param.d.ts @@ -0,0 +1,23 @@ +import { IAssertObj, IHandleError, IHookObj } from 'suman-types/dts/test-suite'; +import { IInjectHookParam } from 'suman-types/dts/params'; +import { ITestSuite } from 'suman-types/dts/test-suite'; +import { Dictionary } from 'async'; +import { ParamBase } from '../base'; +export interface IValuesMap { + [key: string]: true; +} +export declare class InjectParam extends ParamBase implements IInjectHookParam { + protected __planCalled: boolean; + protected __valuesMap: IValuesMap; + protected __suite: ITestSuite; + protected __values: Array; + protected __inject: IHookObj; + protected __assertCount: IAssertObj; + planCountExpected: number; + constructor(inject: IHookObj, assertCount: IAssertObj, suite: ITestSuite, values: Array, handleError: IHandleError, fini: Function); + registerKey(k: string, val: any): Promise; + registerFnMap(o: Dictionary): Promise; + registerMap(o: Dictionary): Promise>; + plan(num: number): any; + confirm(): void; +} diff --git a/lib/test-suite-params/inject/inject-param.js b/lib/test-suite-params/inject/inject-param.js new file mode 100644 index 00000000..a3e928e4 --- /dev/null +++ b/lib/test-suite-params/inject/inject-param.js @@ -0,0 +1,143 @@ +'use strict'; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +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 su = require("suman-utils"); +var _suman = global.__suman = (global.__suman || {}); +var base_1 = require("../base"); +var badProps = { + inspect: true, + constructor: true +}; +var InjectParam = (function (_super) { + __extends(InjectParam, _super); + function InjectParam(inject, assertCount, suite, values, handleError, fini) { + var _this = _super.call(this) || this; + _this.__planCalled = false; + _this.__valuesMap = {}; + _this.__suite = suite; + _this.__hook = inject; + _this.__handle = handleError; + _this.__fini = fini; + _this.__values = values; + _this.__assertCount = assertCount; + _this.__inject = inject; + _this.planCountExpected = null; + return _this; + } + InjectParam.prototype.registerKey = function (k, val) { + var suite = this.__suite; + var valuesMap = this.__valuesMap; + var values = this.__values; + try { + assert(k && typeof k === 'string', 'key must be a string.'); + } + catch (err) { + return this.__handle(err); + } + if (k in valuesMap) { + return this.__handle(new Error("Injection key '" + k + "' has already been added.")); + } + if (k in suite.injectedValues) { + return this.__handle(new Error("Injection key '" + k + "' has already been added.")); + } + valuesMap[k] = true; + values.push({ k: k, val: val }); + return Promise.resolve(val); + }; + InjectParam.prototype.registerFnMap = function (o) { + var suite = this.__suite; + var valuesMap = this.__valuesMap; + var values = this.__values; + var self = this; + return new Promise(function (resolve, reject) { + assert(su.isObject(o), 'value must be a non-array object.'); + async.series(o, function (err, results) { + if (err) { + return reject(err); + } + try { + Object.keys(results).forEach(function (k) { + if (k in valuesMap) { + throw new Error("Injection key '" + k + "' has already been added."); + } + if (k in suite.injectedValues) { + throw new Error("Injection key '" + k + "' has already been added."); + } + valuesMap[k] = true; + values.push({ k: k, val: results[k] }); + }); + } + catch (err) { + return reject(err); + } + resolve(results); + }); + }) + .catch(function (err) { + return self.__handle(err); + }); + }; + InjectParam.prototype.registerMap = function (o) { + var suite = this.__suite; + var valuesMap = this.__valuesMap; + var values = this.__values; + var keys = Object.keys(o); + var self = this; + var registry; + try { + registry = keys.map(function (k) { + if (k in valuesMap) { + throw new Error("Injection key '" + k + "' has already been added."); + } + if (k in suite.injectedValues) { + throw new Error("Injection key '" + k + "' has already been added."); + } + valuesMap[k] = true; + values.push({ k: k, val: o[k] }); + return o[k]; + }); + } + catch (err) { + return self.__handle(err); + } + return Promise.all(registry) + .catch(function (err) { + return self.__handle(err); + }); + }; + InjectParam.prototype.plan = function (num) { + if (this.__planCalled) { + _suman.writeTestError(new Error('Suman warning => plan() called more than once.').stack); + return; + } + this.__planCalled = true; + if (this.__inject.planCountExpected !== undefined) { + _suman.writeTestError(new Error(' => Suman warning => plan() called, even though plan was already passed as an option.').stack); + } + try { + assert(Number.isInteger(num), 'Suman usage error => value passed to plan() is not an integer.'); + } + catch (err) { + return this.__handle(err); + } + this.__inject.planCountExpected = this.planCountExpected = num; + }; + InjectParam.prototype.confirm = function () { + this.__assertCount.num++; + }; + return InjectParam; +}(base_1.ParamBase)); +exports.InjectParam = InjectParam; diff --git a/lib/test-suite-params/inject/inject-param.ts b/lib/test-suite-params/inject/inject-param.ts new file mode 100644 index 00000000..627c71e8 --- /dev/null +++ b/lib/test-suite-params/inject/inject-param.ts @@ -0,0 +1,201 @@ +'use strict'; + +//dts +import {IAssertObj, IHandleError, IHookObj} from 'suman-types/dts/test-suite'; +import {IInjectHookParam} from 'suman-types/dts/params'; +import {IGlobalSumanObj} from 'suman-types/dts/global'; +import AssertStatic = Chai.AssertStatic; +import {ITestSuite} from 'suman-types/dts/test-suite'; +import {ErrorCallback, Dictionary} from 'async'; + +//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'); +import su = require('suman-utils'); + +//project +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); +import {ParamBase} from '../base'; + +//////////////////////////////////////////////////////////////////////////////////// + +interface IBadProps { + [key: string]: true +} + +export interface IValuesMap { + [key: string]: true +} + +let badProps = { + inspect: true, + constructor: true +}; + + +export class InjectParam extends ParamBase implements IInjectHookParam{ + + protected __planCalled: boolean; + protected __valuesMap: IValuesMap; + protected __suite: ITestSuite; + protected __values: Array; + protected __inject: IHookObj; + protected __assertCount: IAssertObj; + public planCountExpected: number; + + constructor(inject: IHookObj, assertCount: IAssertObj, suite: ITestSuite, + values: Array, handleError: IHandleError, fini: Function){ + + super(); + this.__planCalled = false; + this.__valuesMap = {} as any; + this.__suite = suite; + this.__hook = inject; + this.__handle = handleError; + this.__fini = fini; + this.__values = values; + this.__assertCount = assertCount; + this.__inject = inject; + this.planCountExpected = null; + } + + + registerKey (k: string, val: any): Promise { // 'register' should be an alias? + + const suite = this.__suite; + const valuesMap = this.__valuesMap; + const values = this.__values; + + try { + assert(k && typeof k === 'string', 'key must be a string.'); + } + catch (err) { + return this.__handle(err); + } + + if (k in valuesMap) { + return this.__handle(new Error(`Injection key '${k}' has already been added.`)); + } + if (k in suite.injectedValues) { + return this.__handle(new Error(`Injection key '${k}' has already been added.`)); + } + + valuesMap[k] = true; // mark as reserved + values.push({k, val}); + return Promise.resolve(val); + } + + registerFnMap (o: Dictionary): Promise { // 'registerFnsMap' shoule be an alias + + const suite = this.__suite; + const valuesMap = this.__valuesMap; + const values = this.__values; + const self = this; + + return new Promise(function (resolve, reject) { + + assert(su.isObject(o), 'value must be a non-array object.'); + + async.series(o, function (err: Error, results: Dictionary) { + + if (err) { + return reject(err); + } + + try { + Object.keys(results).forEach(function (k) { + if (k in valuesMap) { + throw new Error(`Injection key '${k}' has already been added.`); + } + if (k in suite.injectedValues) { + throw new Error(`Injection key '${k}' has already been added.`); + } + valuesMap[k] = true; // mark as reserved + values.push({k, val: results[k]}); + }); + } + catch (err) { + return reject(err); + } + + resolve(results); + }); + }) + .catch(function (err) { + return self.__handle(err); + }); + } + + registerMap (o: Dictionary): Promise> { // 'registerPromisesMap' should be an alias + + const suite = this.__suite; + const valuesMap = this.__valuesMap; + const values = this.__values; + const keys = Object.keys(o); + const self = this; + let registry; + + try { + registry = keys.map(function (k) { + + if (k in valuesMap) { + throw new Error(`Injection key '${k}' has already been added.`); + } + if (k in suite.injectedValues) { + throw new Error(`Injection key '${k}' has already been added.`); + } + + valuesMap[k] = true; // mark as reserved + values.push({k, val: o[k]}); + return o[k]; + }); + } + catch (err) { + return self.__handle(err); + } + + return Promise.all(registry) + .catch(function (err) { + return self.__handle(err); + }); + } + + plan (num: number) { + + if (this.__planCalled) { + _suman.writeTestError(new Error('Suman warning => plan() called more than once.').stack); + return; + } + + this.__planCalled = true; + if (this.__inject.planCountExpected !== undefined) { + _suman.writeTestError( + new Error(' => Suman warning => plan() called, even though plan was already passed as an option.').stack + ); + } + + try { + assert(Number.isInteger(num), 'Suman usage error => value passed to plan() is not an integer.'); + } + catch (err) { + return this.__handle(err); + } + + this.__inject.planCountExpected = this.planCountExpected = num; + } + + confirm () { + this.__assertCount.num++; + } + +} + + + + diff --git a/lib/test-suite-params/test-case/test-case-param.d.ts b/lib/test-suite-params/test-case/test-case-param.d.ts new file mode 100644 index 00000000..fe40327c --- /dev/null +++ b/lib/test-suite-params/test-case/test-case-param.d.ts @@ -0,0 +1,20 @@ +import { ITestDataObj } from 'suman-types/dts/it'; +import { IHandleError } from 'suman-types/dts/test-suite'; +import { ITestCaseParam } from 'suman-types/dts/params'; +import { ParamBase } from '../base'; +export interface IAssertCount { + num: number; +} +export declare class TestCaseParam extends ParamBase implements ITestCaseParam { + protected __planCalled: boolean; + protected __assertCount: IAssertCount; + protected planCountExpected: number; + protected value: Object; + protected data: Object; + protected testId: number; + protected desc: string; + protected title: string; + constructor(test: ITestDataObj, assertCount: IAssertCount, handleError: IHandleError, fini: Function); + plan(num: number): void; + confirm(): void; +} diff --git a/lib/test-suite-params/test-case/test-case-param.js b/lib/test-suite-params/test-case/test-case-param.js new file mode 100644 index 00000000..e0b9cc80 --- /dev/null +++ b/lib/test-suite-params/test-case/test-case-param.js @@ -0,0 +1,53 @@ +'use strict'; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +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 = global.__suman = (global.__suman || {}); +var base_1 = require("../base"); +var TestCaseParam = (function (_super) { + __extends(TestCaseParam, _super); + function TestCaseParam(test, assertCount, handleError, fini) { + var _this = _super.call(this) || this; + _this.__assertCount = assertCount; + _this.__planCalled = false; + _this.value = test.value; + _this.testId = test.testId; + _this.desc = _this.title = test.desc; + _this.data = test.data; + _this.__test = test; + _this.__handle = handleError; + _this.__fini = fini; + return _this; + } + TestCaseParam.prototype.plan = function (num) { + var test = this.__test; + if (this.__planCalled) { + _suman.writeTestError(new Error('Suman warning => t.plan() called more than once for ' + + 'the same test case.').stack); + return; + } + this.__planCalled = true; + if (test.planCountExpected !== undefined) { + _suman.writeTestError(new Error('Suman warning => t.plan() called, even though plan ' + + 'was already passed as an option.').stack); + } + assert(Number.isInteger(num), 'Suman usage error => value passed to t.plan() is not an integer.'); + test.planCountExpected = this.planCountExpected = num; + }; + TestCaseParam.prototype.confirm = function () { + this.__assertCount.num++; + }; + return TestCaseParam; +}(base_1.ParamBase)); +exports.TestCaseParam = TestCaseParam; diff --git a/lib/test-suite-params/test-case/test-case-param.ts b/lib/test-suite-params/test-case/test-case-param.ts new file mode 100644 index 00000000..e870da6d --- /dev/null +++ b/lib/test-suite-params/test-case/test-case-param.ts @@ -0,0 +1,86 @@ +'use strict'; + +//dts +import {IGlobalSumanObj} from 'suman-types/dts/global'; +import {ITestDataObj} from 'suman-types/dts/it'; +import {IHandleError} from 'suman-types/dts/test-suite'; +import {ITestCaseParam} from 'suman-types/dts/params'; +import AssertStatic = Chai.AssertStatic; + +//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'); + +//npm +import * as chai from 'chai'; + +//project +const _suman: IGlobalSumanObj = global.__suman = (global.__suman || {}); +import {ParamBase} from '../base'; + +////////////////////////////////////////////////////////////////////////////// + +export interface IAssertCount { + num: number +} + +/////////////////////////////////////////////////////////////////////////////// + +export class TestCaseParam extends ParamBase implements ITestCaseParam { + + protected __planCalled: boolean; + protected __assertCount: IAssertCount; + protected planCountExpected: number; + protected value: Object; + protected data: Object; + protected testId: number; + protected desc: string; + protected title: string; + + constructor(test: ITestDataObj, assertCount: IAssertCount, + handleError: IHandleError, fini: Function) { + super(); + + this.__assertCount = assertCount; + this.__planCalled = false; + this.value = test.value; + this.testId = test.testId; + this.desc = this.title = test.desc; + this.data = test.data; + this.__test = test; + this.__handle = handleError; + this.__fini = fini; + } + + plan(num: number) { + + const test = this.__test; + + if (this.__planCalled) { + _suman.writeTestError(new Error('Suman warning => t.plan() called more than once for ' + + 'the same test case.').stack); + return; + } + + this.__planCalled = true; + if (test.planCountExpected !== undefined) { + _suman.writeTestError(new Error('Suman warning => t.plan() called, even though plan ' + + 'was already passed as an option.').stack); + } + + assert(Number.isInteger(num), 'Suman usage error => value passed to t.plan() is not an integer.'); + test.planCountExpected = this.planCountExpected = num; + } + + confirm() { + this.__assertCount.num++; + } + +} + + + diff --git a/suman-todos.txt b/suman-todos.txt index 65de6903..e79ba475 100755 --- a/suman-todos.txt +++ b/suman-todos.txt @@ -8,6 +8,14 @@ three SO profiles: //TODO: t.state = 'passed'/'failed' etc. +/// + + use procure instead of source, or load, or locate, gather + +//// + + add env vars to @config.json + //// spawn all child processes in shell, launch processes via bash instead of directly @@ -181,6 +189,11 @@ exit with command to the right that exits with non-zero } }, +//// + + suman watch, suman-refine, suman-shell + need to pass env vars so that we get the right reporter at top level and child levels + //// suman tests should work without having to run suman --init @@ -195,6 +208,8 @@ exit with command to the right that exits with non-zero use puppeteer to launch chrome instead of chrome-launcher https://developers.google.com/web/updates/2017/04/headless-chrome + https://github.com/mochajs/mocha/pull/3152 + //// https://unix.stackexchange.com/questions/407222/find-location-of-shell-bash-function-on-disk @@ -268,10 +283,6 @@ shopt -u extdebug skip and only do not work creates - Test.create(['bat', 'suit', {only: true}, -//// - - if beforeEach hook fails -> we do not exit, but we should mark the test as failed. - //// if function parameter name is in $ioc, but is listed explicity, then we should throw to let the user know. diff --git a/test/.suman/.meta/gantt.html b/test/.suman/.meta/gantt.html index dc1248a0..1a38b737 100644 --- a/test/.suman/.meta/gantt.html +++ b/test/.suman/.meta/gantt.html @@ -90,7 +90,7 @@ } ]; - let tasksRaw = JSON.parse('[{"startDate":1513489996939,"endDate":1513489997508,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/1.test.js","status":"SUCCEEDED"},{"startDate":1513489996892,"endDate":1513489997377,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/3.test.js","status":"SUCCEEDED"},{"startDate":1513489996189,"endDate":1513489998436,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/2.test.js","status":"SUCCEEDED"},{"startDate":1513489996186,"endDate":1513489996940,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/4.test.js","status":"SUCCEEDED"},{"startDate":1513489996182,"endDate":1513489996875,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/5.test.js","status":"FAILED"},{"startDate":1513489996179,"endDate":1513489996996,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/6.test.js","status":"SUCCEEDED"},{"startDate":1513489996176,"endDate":1513489997902,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/events.test.js","status":"SUCCEEDED"},{"startDate":1513489996173,"endDate":1513489996990,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/injection.test.js","status":"SUCCEEDED"},{"startDate":1513489996170,"endDate":1513489996974,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/injection2.test.js","status":"FAILED"},{"startDate":1513489996166,"endDate":1513489996935,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/simple.js","status":"SUCCEEDED"}]'); + let tasksRaw = JSON.parse('[{"startDate":1513923585242,"endDate":1513923585833,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/1.test.js","status":"SUCCEEDED"},{"startDate":1513923584464,"endDate":1513923585580,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/2.test.js","status":"SUCCEEDED"},{"startDate":1513923584295,"endDate":1513923585237,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/3.test.js","status":"FAILED"},{"startDate":1513923584311,"endDate":1513923585286,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/4.test.js","status":"SUCCEEDED"},{"startDate":1513923584261,"endDate":1513923585309,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/5.test.js","status":"SUCCEEDED"},{"startDate":1513923584250,"endDate":1513923585299,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/6.test.js","status":"SUCCEEDED"},{"startDate":1513923584279,"endDate":1513923585286,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/events.test.js","status":"SUCCEEDED"},{"startDate":1513923584225,"endDate":1513923585449,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/injection.test.js","status":"SUCCEEDED"},{"startDate":1513923584230,"endDate":1513923584439,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/injection2.test.ts","status":"FAILED"},{"startDate":1513923584233,"endDate":1513923585286,"transformStartDate":null,"transformEndDate":null,"taskName":"/Users/alexamil/WebstormProjects/oresoftware/sumanjs/suman/test/src/dev/node/simple.js","status":"SUCCEEDED"}]'); let tasks = []; diff --git a/test/.suman/.meta/timeline.html b/test/.suman/.meta/timeline.html index 0de0d3a8..11a4e993 100644 --- a/test/.suman/.meta/timeline.html +++ b/test/.suman/.meta/timeline.html @@ -25,7 +25,7 @@ dataTable.addColumn({type: 'date', id: 'Start'}); dataTable.addColumn({type: 'date', id: 'End'}); - let tasksRaw = JSON.parse('[{"startDate":1513489996166,"endDate":1513489996935,"transformStartDate":null,"transformEndDate":null,"taskName":"simple.js","status":"SUCCEEDED"},{"startDate":1513489996170,"endDate":1513489996974,"transformStartDate":null,"transformEndDate":null,"taskName":"injection2.test.js","status":"FAILED"},{"startDate":1513489996173,"endDate":1513489996990,"transformStartDate":null,"transformEndDate":null,"taskName":"injection.test.js","status":"SUCCEEDED"},{"startDate":1513489996176,"endDate":1513489997902,"transformStartDate":null,"transformEndDate":null,"taskName":"events.test.js","status":"SUCCEEDED"},{"startDate":1513489996179,"endDate":1513489996996,"transformStartDate":null,"transformEndDate":null,"taskName":"6.test.js","status":"SUCCEEDED"},{"startDate":1513489996182,"endDate":1513489996875,"transformStartDate":null,"transformEndDate":null,"taskName":"5.test.js","status":"FAILED"},{"startDate":1513489996186,"endDate":1513489996940,"transformStartDate":null,"transformEndDate":null,"taskName":"4.test.js","status":"SUCCEEDED"},{"startDate":1513489996189,"endDate":1513489998436,"transformStartDate":null,"transformEndDate":null,"taskName":"2.test.js","status":"SUCCEEDED"},{"startDate":1513489996892,"endDate":1513489997377,"transformStartDate":null,"transformEndDate":null,"taskName":"3.test.js","status":"SUCCEEDED"},{"startDate":1513489996939,"endDate":1513489997508,"transformStartDate":null,"transformEndDate":null,"taskName":"1.test.js","status":"SUCCEEDED"}]'); + let tasksRaw = JSON.parse('[{"startDate":1513923584225,"endDate":1513923585449,"transformStartDate":null,"transformEndDate":null,"taskName":"injection.test.js","status":"SUCCEEDED"},{"startDate":1513923584230,"endDate":1513923584439,"transformStartDate":null,"transformEndDate":null,"taskName":"injection2.test.ts","status":"FAILED"},{"startDate":1513923584233,"endDate":1513923585286,"transformStartDate":null,"transformEndDate":null,"taskName":"simple.js","status":"SUCCEEDED"},{"startDate":1513923584250,"endDate":1513923585299,"transformStartDate":null,"transformEndDate":null,"taskName":"6.test.js","status":"SUCCEEDED"},{"startDate":1513923584261,"endDate":1513923585309,"transformStartDate":null,"transformEndDate":null,"taskName":"5.test.js","status":"SUCCEEDED"},{"startDate":1513923584279,"endDate":1513923585286,"transformStartDate":null,"transformEndDate":null,"taskName":"events.test.js","status":"SUCCEEDED"},{"startDate":1513923584295,"endDate":1513923585237,"transformStartDate":null,"transformEndDate":null,"taskName":"3.test.js","status":"FAILED"},{"startDate":1513923584311,"endDate":1513923585286,"transformStartDate":null,"transformEndDate":null,"taskName":"4.test.js","status":"SUCCEEDED"},{"startDate":1513923584464,"endDate":1513923585580,"transformStartDate":null,"transformEndDate":null,"taskName":"2.test.js","status":"SUCCEEDED"},{"startDate":1513923585242,"endDate":1513923585833,"transformStartDate":null,"transformEndDate":null,"taskName":"1.test.js","status":"SUCCEEDED"}]'); let tasks = []; let colors = []; diff --git a/test/src/dev/node/1.test.js b/test/src/dev/node/1.test.js index 86e766b6..07da4b60 100755 --- a/test/src/dev/node/1.test.js +++ b/test/src/dev/node/1.test.js @@ -23,6 +23,9 @@ Test.define(v => { .run((b, before, after, afterEach, it) => { it('is cool', t => { + + // console.log(t); + debugger; }); @@ -105,6 +108,7 @@ Test.create(opts, ['rudolph', function (assert, describe, before, beforeEach, af it('xxx ', t => { assert(true); + // t.fatal(); }); it.skip['retries:5, name:hi']('zoom', t => { diff --git a/test/src/dev/node/2.test.js b/test/src/dev/node/2.test.js index eebed7e4..10482ad0 100755 --- a/test/src/dev/node/2.test.js +++ b/test/src/dev/node/2.test.js @@ -46,9 +46,9 @@ Test.create('X', { before(async function (h) { h.assert.equal(++count, 2); - return Promise.delay(399).then(function () { + return Promise.delay(39).then(function () { console.log('delaying more.'); - return Promise.delay(1000); + return Promise.delay(100); }); }); diff --git a/test/src/dev/node/3.test.js b/test/src/dev/node/3.test.js index 02c221a2..3afacc15 100755 --- a/test/src/dev/node/3.test.js +++ b/test/src/dev/node/3.test.js @@ -2,29 +2,31 @@ 'use strict'; const suman = require('suman'); -const { Test } = suman.init(module, { - pre: ['dog'] -}, +const {Test} = suman.init(module, { + pre: ['dog'] + }, { allowSkip: true }); +let count = 0; + /////////////////////////////////////////////////////////////////////// -Test.create({ delay: true }, b => { - b.resume(); -}); +// Test.create({delay: true}, b => { +// b.resume(); +// }); Test.create(function (b, assert, describe, test, before, beforeEach, after, afterEach, it, $core) { - const { child_process, http } = $core; + const {child_process, http} = $core; beforeEach.define('early').run(h => { return Promise.resolve('foobar'); }); b.set('a', 'bingo'); - const [a, z] = b.gets('a', 'b'); + const [a, z] = b.getValues('a', 'b'); assert.equal(a, 'bingo'); assert.equal(z, undefined); @@ -32,7 +34,7 @@ Test.create(function (b, assert, describe, test, before, beforeEach, after, afte describe('here we go', function (b) { - const [a, z] = b.gets('a', 'b'); + const [a, z] = b.getValues('a', 'b'); assert.equal(a, 'bingo'); assert.equal(z, undefined); @@ -40,11 +42,19 @@ Test.create(function (b, assert, describe, test, before, beforeEach, after, afte h.assert(true); }); - it('sync test', t => { - t.assert(true); - }); + // it('sync test', t => { + // t.assert(true); + // t.plan(3); + // t.confirm(); + // t.confirm(); + // }); + - after(h => { + after.fatal(h => { + h.plan(3); + h.confirm(); + h.confirm(); + h.confirm(); assert(true); }); diff --git a/test/src/dev/node/5.test.js b/test/src/dev/node/5.test.js index ecbceb37..b6378cf6 100755 --- a/test/src/dev/node/5.test.js +++ b/test/src/dev/node/5.test.js @@ -3,9 +3,12 @@ const suman = require('suman'); const {Test} = suman.init(module, { - forceParallel: true, // parallel, not parallel-max - __expectedExitCode: 56 -}); + forceParallel: true, // parallel, not parallel-max + __expectedExitCode: 56 + }, + { + allowSkip: true + }); /////////////////////////////////////////////////////////////////////// @@ -17,35 +20,26 @@ Test.create(function (assert, describe, before, beforeEach, after, afterEach, it console.log('before all hook'); }); - // before.cb(['fatal:false', h => { - // - // const d = domain.create(); - // d.xxx = 'foo'; - // - // const d2 = process.domain; - // d2.yyy = 'bar'; - // - // debugger; - // - // // throw 'samsam'; - // // process.on('uncaughtException', function (e) { - // // console.log('ue => ', e); - // // }); - // - // d.run(function () { - // - // throw new Error('barf'); - // - // }); - // - // }]); + before.cb(['fatal:false', h => { + + const d = domain.create(); + d.xxx = 'foo'; + + const d2 = process.domain; + d2.yyy = 'bar'; + + d.run(function () { + throw new Error('barf'); + }); + + }]); it.cb('passing', t => { t.done(); }); it.cb('failing', t => { - t.done('this test failed'); + t.done(null,'this test failed'); }); afterEach.cb(h => { @@ -67,7 +61,7 @@ Test.create(function (assert, describe, before, beforeEach, after, afterEach, it }); it.cb('failing', t => { - t.done('buggers') + t.done(null,'buggers') }); afterEach.cb(h => { @@ -106,7 +100,7 @@ Test.create(function (assert, describe, before, beforeEach, after, afterEach, it }); it('failing', t => { - return Promise.reject('zoomba'); + return Promise.resolve('zoomba'); }); after.cb(h => { diff --git a/test/src/dev/node/6.test.js b/test/src/dev/node/6.test.js index bb002dbd..4515d824 100755 --- a/test/src/dev/node/6.test.js +++ b/test/src/dev/node/6.test.js @@ -14,7 +14,7 @@ Test.create(function (b, test, setup, setupTest, setuptest, teardown, teardownTe test('here we go'); - b.shared.set('users', 888); + b.set('users', 888); setup({}, h => { console.log('this is a setup..'); diff --git a/test/src/dev/node/dep-injection/one.test.js b/test/src/dev/node/dep-injection/one.test.js index 57803ef5..43388f2f 100644 --- a/test/src/dev/node/dep-injection/one.test.js +++ b/test/src/dev/node/dep-injection/one.test.js @@ -55,3 +55,16 @@ Test.create(['aaa', 'bbb', 'ccc', (b, describe, before, after, afterEach) => { // }); }]); + +Test.define('roo') +.source('bat', 'suit') +.run(b => { + + console.log('B dot i.o.c.', b.ioc); + console.log('B dot i.o.c.', b.getSourcedValues('bat')); + +}) +.run(b => { + + console.log('B dot i.o.c.', b.ioc); +}); diff --git a/test/src/dev/node/events.test.js b/test/src/dev/node/events.test.js index f547a218..808bf6f8 100755 --- a/test/src/dev/node/events.test.js +++ b/test/src/dev/node/events.test.js @@ -20,7 +20,7 @@ Test.create(function (b, assert, describe, before, beforeEach, after, afterEach, setTimeout(function () { ee.emit('done'); - }, 300); + }, 30); return ee; @@ -32,7 +32,7 @@ Test.create(function (b, assert, describe, before, beforeEach, after, afterEach, setTimeout(function () { ee.emit('bubba', new Error('zoom')); - }, 300); + }, 30); return ee; @@ -44,7 +44,7 @@ Test.create(function (b, assert, describe, before, beforeEach, after, afterEach, setTimeout(function () { ee.emit('bubba', new Error('zoom')); - }, 300); + }, 30); return ee; diff --git a/test/src/dev/node/injection2.test.js b/test/src/dev/node/injection2.test.ts old mode 100644 new mode 100755 similarity index 81% rename from test/src/dev/node/injection2.test.js rename to test/src/dev/node/injection2.test.ts index 3695aded..6e151b80 --- a/test/src/dev/node/injection2.test.js +++ b/test/src/dev/node/injection2.test.ts @@ -1,9 +1,17 @@ #!/usr/bin/env node 'use strict'; -const suman = require('suman'); -const Test = suman.init(module, {}, { - // series: false +import suman, { s } from 'suman'; + +const { Test } = suman.init(module, { + override: { + opts: { + allowSkip: true, + }, + config: { + + } + } }); /////////////////////////////////////////////////////////////////////// @@ -15,101 +23,103 @@ const opts = { fixed: true }; -const Promise = require('bluebird'); +global.Promise = require('bluebird'); Test.create(opts, ['rudolph', function (b, assert, describe, before, beforeEach, after, afterEach, it, inject) { - + inject('eage', t => { return t.registerFnMap({ - a: async function () { - console.log('arguments => ', arguments); - Promise.delay(300); + a: function (cb) { + // await Promise.delay(300); + return process.nextTick(cb, null, 'dogs'); + }, + b: async function () { return 'dogs'; } }); }); - + it('sync test hagieao agoeajgoea jo joeajgoea aegjeag oa iag j aogeg ', t => { assert(false); }); - + it.skip['retries:5, name:hi']('zoom', t => { - + }); - + before('hi', [h => { h.assert.equal(++count, 1); }]); - + describe('zoom', b => { - + describe('nested1', {}, (b) => { - + const a = b.getInjectedValue('a'); console.log('a is => ', a); - + b.set('a', true); - + // console.log('before => ', before); assert.equal(count, 0); - + before(h => { h.assert(h.get('a')); h.assert.equal(++count, 2); }); - + it('sync test', t => { assert(true); }); - + after(h => { h.assert.equal(++count, 5); }); - + describe('nested2', {}, b => { - + assert(b.get('a')); - + assert.equal(count, 0); - + it('sync test', t => { assert(true); }); - + before(h => { h.assert.equal(++count, 3); }); - + after(h => { h.assert.equal(++count, 4); }); - + }); - + }); - + }); - + describe('nested3', b => { - + assert.equal(count, 0); - + before('zoomy', h => { h.assert.equal(++count, 6); }); - + it('sync test', t => { assert(true); }); - + }); - + after.last('roomy', h => { h.assert.equal(++count, 8); }); - + after.always('roomy', h => { h.assert.equal(++count, 7); }); - + }]); diff --git a/test/src/dev/node/supply/one.js b/test/src/dev/node/supply/one.js new file mode 100644 index 00000000..bcb3c1b5 --- /dev/null +++ b/test/src/dev/node/supply/one.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node +'use strict'; + +const suman = require('suman'); +const {Test} = suman.init(module); + +Test.create(function(before, beforeEach, afterEach, it, after){ + + before(h => { + h.supply.three = 3; + h.assert.equal(h.supply.three,3); + }); + + beforeEach(h => { + h.assert.equal(h.supply.three,3); + }); + + it('testo',t => { + t.assert.equal(t.supply.three,3); + }); + + afterEach(h => { + h.assert.equal(h.supply.three,3); + }); + + after(h => { + h.assert.equal(h.supply.three,3); + }); + + +}); + diff --git a/test/src/exp/before-each.js b/test/src/exp/before-each.js index fcc89be3..093024f0 100755 --- a/test/src/exp/before-each.js +++ b/test/src/exp/before-each.js @@ -41,7 +41,7 @@ Test.create('hotels1', function (it, before, beforeEach, describe, context, util }); }); - context('inner block A', function(){ + context('inner block A', function(b){ it.cb('third', t => { setTimeout(t, 10); @@ -51,7 +51,7 @@ Test.create('hotels1', function (it, before, beforeEach, describe, context, util setTimeout(t, 10); }); - context('inner block B', function(){ + context('inner block B', function(b){ it.cb('fifth', t => { setTimeout(t, 10); @@ -63,7 +63,7 @@ Test.create('hotels1', function (it, before, beforeEach, describe, context, util }); }); - context('inner block C', function(){ + context('inner block C', function(b){ it.cb('seventh', t => { setTimeout(t, 10); @@ -73,7 +73,7 @@ Test.create('hotels1', function (it, before, beforeEach, describe, context, util setTimeout(t, 10); }); - context('inner block D', function(){ + context('inner block D', function(b){ it.cb('ninth', t => { setTimeout(t, 10); @@ -86,7 +86,7 @@ Test.create('hotels1', function (it, before, beforeEach, describe, context, util }); - context('inner block E', function(){ + context('inner block E', function(b){ it.cb('eleventh', t => { setTimeout(t, 10); @@ -96,7 +96,7 @@ Test.create('hotels1', function (it, before, beforeEach, describe, context, util setTimeout(t, 10); }); - context('inner block F', function(){ + context('inner block F', function(b){ it.cb('thirteenth', t => { setTimeout(t, 10); diff --git a/test/src/exp/es5-es6/other-tests/test6.js b/test/src/exp/es5-es6/other-tests/test6.js index 1f8e354e..7d3ed599 100755 --- a/test/src/exp/es5-es6/other-tests/test6.js +++ b/test/src/exp/es5-es6/other-tests/test6.js @@ -1,99 +1,84 @@ -/** - * Created by denman on 12/2/2015. - */ - var suman = require('suman'); const Test = suman.init(module); - const should = require('should'); Test.describe('suite tres', {}, function (assert) { - this.before.cb(t => { - - t.done(); - t.log('barf'); - }); - + this.before.cb(t => { - this.it.cb('my test99999', t => { + t.done(); + t.log('barf'); + }); - setTimeout(function(){ - t.pass(); - },200); - - }); + this.it.cb('my test99999', t => { + setTimeout(function () { + t.pass(); + }, 200); - this.afterEach.cb({fatal: false}, t => { + }); - setTimeout(function () { + this.afterEach.cb({fatal: false}, t => { - var user = { - name: 'tj', - pets: ['tobi', 'loki', 'jane', 'bandit'] - }; + setTimeout(function () { - // assert(false); + var user = { + name: 'tj', + pets: ['tobi', 'loki', 'jane', 'bandit'] + }; - t.done(); - }); + // assert(false); + t.done(); }); + }); - this.afterEach.cb({fatal: false}, t => { + this.afterEach.cb({fatal: false}, t => { - setTimeout(t.wrap(function () { + setTimeout(t.wrap(function () { - // assert(false); - t.done(); - })); - - }); + // assert(false); + t.done(); + })); + }); - this.describe('tarzan', function () { + this.describe('tarzan', function () { - this.before(t => { + this.before(t => { + }); + this.it('my tarzan test', t => { - }); + }); - this.it('my tarzan test', t => { + this.describe('uuuuu test', function () { + this.describe('uuuuu3333 test', function () { + this.before.skip(t => { }); - this.describe('uuuuu test', function () { - - this.describe('uuuuu3333 test', function () { - - this.before.skip(t => { + // this.it.red('my 3333 test', function () { + // + // }); - }); + }); - // this.it.red('my 3333 test', function () { - // - // }); + this.before(function () { - }); + }); + this.it('my boooz test', function () { - this.before(function () { - - }); - - this.it('my boooz test', function () { - - }); - - }); + }); }); + }); -}); \ No newline at end of file +});