├── .gitignore ├── .npmignore ├── bin └── blue-tape.js ├── .github └── ISSUE_TEMPLATE │ └── project-not-maintained.md ├── package.json ├── blue-tape.js ├── README.md └── test └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | .gitignore 3 | -------------------------------------------------------------------------------- /bin/blue-tape.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('tape/bin/tape') 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/project-not-maintained.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Project not maintained 3 | about: This project is no longer maintained 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | The best option is to switch to a library that supports promises - either https://github.com/jprichardson/tape-promise or https://www.node-tap.org/ - or perhaps its time to revisit substack/tape/issues/262 and add promise support to tape. 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blue-tape", 3 | "version": "1.0.0", 4 | "description": "Tape test runner with promise support", 5 | "main": "blue-tape.js", 6 | "bin": { 7 | "blue-tape": "./bin/blue-tape.js" 8 | }, 9 | "scripts": { 10 | "test": "standard && node test/index.js" 11 | }, 12 | "keywords": [ 13 | "tape", 14 | "bluebird", 15 | "promises" 16 | ], 17 | "author": "spion", 18 | "license": "MIT", 19 | "dependencies": { 20 | "tape": ">=2.0.0 <5.0.0" 21 | }, 22 | "directories": { 23 | "test": "test" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/spion/blue-tape.git" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/spion/blue-tape/issues" 31 | }, 32 | "devDependencies": { 33 | "bl": "^4.0.3", 34 | "bluebird": "^2.1.2", 35 | "standard": "*" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /blue-tape.js: -------------------------------------------------------------------------------- 1 | var Test = require('tape/lib/test') 2 | 3 | function checkPromise (p) { 4 | return p && p.then && typeof p.then === 'function' 5 | } 6 | 7 | Test.prototype.run = function () { 8 | if (this._skip) { 9 | return this.end() 10 | } 11 | this.emit('prerun') 12 | try { 13 | var p = this._cb && this._cb(this) 14 | var isPromise = checkPromise(p) 15 | var self = this 16 | if (isPromise) { 17 | p.then(function () { 18 | self.end() 19 | }, function (err) { 20 | err ? self.error(err) : self.fail(err) 21 | self.end() 22 | }) 23 | } 24 | } catch (err) { 25 | if (err) { 26 | this.error(err) 27 | } else { 28 | this.fail(err) 29 | } 30 | this.end() 31 | return 32 | } 33 | this.emit('run') 34 | } 35 | 36 | function noop() {} 37 | 38 | Test.prototype.shouldFail = 39 | Test.prototype.shouldReject = 40 | function (promise, expected, message, extra) { 41 | var self = this 42 | return promise.then(function () { 43 | self.throws(noop, expected, message, extra) 44 | }, function (err) { 45 | function f() {throw err} 46 | self.throws(f, expected, message, extra) 47 | }) 48 | } 49 | 50 | 51 | module.exports = require('tape') 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### This project is no longer maintained. 2 | 3 | The best option is to switch to a library that supports promises - either https://github.com/jprichardson/tape-promise or https://github.com/tapjs/node-tap - or perhaps its time to revisit https://github.com/substack/tape/issues/262 and add promise support to tape. 4 | 5 | -------------- 6 | 7 | # blue-tape 8 | 9 | Tape with promise support. 10 | 11 | ### Usage 12 | 13 | Same as [tape](https://github.com/substack/tape), except if you return a promise from a test, 14 | it will be checked for errors. If there are no errors, the test will end. Otherwise the test 15 | will fail. This means there is no need to use `t.plan()` or `t.end()`. 16 | 17 | Also provides `t.shouldFail(promise P, optional class|regex expected, optional message)` (as 18 | well as the alias `shouldReject`) which returns a new promise that resolves successfully if `P` 19 | rejects. If you provide the optional class, or regex then it additionally ensures that `err` is 20 | an instance of that class or that the message matches the regular expression. The behaviour is 21 | identical to tape's `throws` assertion. 22 | 23 | ### Examples 24 | 25 | Assuming `delay()` returns a promise: 26 | 27 | ```js 28 | const test = require('blue-tape'); 29 | 30 | test("simple delay", function(t) { 31 | return delay(1); 32 | }); 33 | 34 | test("should fail", function(t) { 35 | return delay(1).then(function() { 36 | throw new Error("Failed!"); 37 | }); 38 | }); 39 | ``` 40 | 41 | Assuming `failDelay()` returns a promise that rejects with a DerpError: 42 | 43 | ```js 44 | test("promise fails but test succeeds", function(t) { 45 | return t.shouldFail(failDelay(), DerpError); 46 | }); 47 | ``` 48 | 49 | ### License 50 | 51 | MIT 52 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var tape = require('../blue-tape') 2 | var bl = require('bl') 3 | var P = require('bluebird') 4 | P.longStackTraces() 5 | 6 | function test (name, test, checkErrors) { 7 | tape.test(name, function (t) { 8 | var htest = tape.createHarness() 9 | htest.createStream().pipe(bl(function (_, data) { 10 | checkErrors && checkErrors(data.toString().split('\n'), t) 11 | })) 12 | htest(function (t) { 13 | return test(t, htest) 14 | }) 15 | }) 16 | } 17 | 18 | function verifyAsserts (counts) { 19 | return function (lines, t) { 20 | t.equal(count(lines, /^ok/), counts.ok, 'should have ' + counts.ok + ' ok asserts') 21 | t.equal(count(lines, /^not ok/), counts.fail, 'should have ' + counts.fail + ' failed asserts') 22 | t.end() 23 | } 24 | } 25 | 26 | function count (lines, regex) { 27 | var c = 0 28 | for (var k = 0; k < lines.length; ++k) { 29 | if (regex.test(lines[k])) { 30 | ++c 31 | } 32 | } 33 | return c 34 | } 35 | 36 | test('non-promise test', function (t) { 37 | t.ok(true) 38 | t.end() 39 | }, 40 | verifyAsserts({ok: 1, fail: 0})) 41 | 42 | test('simple delay', function (t) { 43 | return P.delay(1) 44 | }, 45 | verifyAsserts({ok: 0, fail: 0})) 46 | 47 | test('should not affect plan', function (t) { 48 | t.plan(2) 49 | t.ok(true) 50 | t.ok(true) 51 | return P.delay(1) 52 | }, 53 | verifyAsserts({ok: 2, fail: 0})) 54 | 55 | test('nested tests with promises', function (t) { 56 | t.test('delay1', function (t) { 57 | return P.delay(1) 58 | }) 59 | t.test('delay2', function () { 60 | return P.delay(1) 61 | }) 62 | }, 63 | verifyAsserts({ok: 0, fail: 0})) 64 | 65 | test('should error', function (t) { 66 | return P.delay(1).then(function () { 67 | throw new Error('Failed!') 68 | }) 69 | }, 70 | verifyAsserts({ok: 0, fail: 1})) 71 | 72 | test('should fail', function (t) { 73 | return P.delay(1).then(function () { 74 | return P.reject() 75 | }) 76 | }, 77 | verifyAsserts({ok: 0, fail: 1})) 78 | 79 | test('run test with only', function (t, htest) { 80 | var count = 0 81 | htest('first', function (t) { 82 | t.equal(++count, 1) 83 | t.end() 84 | }) 85 | htest.only('second', function (t) { 86 | t.equal(++count, 1) 87 | t.end() 88 | }) 89 | t.end() 90 | }, 91 | verifyAsserts({ok: 1, fail: 0})) 92 | 93 | test('test that expects promise to fail', function (t) { 94 | return t.shouldFail(P.delay(1).then(function () { 95 | return P.reject(new Error("Test")) 96 | })) 97 | }, 98 | verifyAsserts({ok: 1, fail: 0})) 99 | 100 | test('test that expects promise to fail, but it succeeds', function (t) { 101 | return t.shouldFail(P.delay(1).then(function () { 102 | return P.resolve() 103 | })) 104 | }, 105 | verifyAsserts({ok: 0, fail: 1})) 106 | 107 | test('test that expects specific exception', function (t) { 108 | return t.shouldFail(P.delay(1).then(function () { 109 | var f = 5 110 | f.toFixed(100) // RangeError 111 | }), RangeError) 112 | }, 113 | verifyAsserts({ok: 1, fail: 0})) 114 | 115 | test('test that expects wrong exception', function (t) { 116 | return t.shouldFail(P.delay(1).then(function () { 117 | var f = 5 118 | f.toFixed(100) // RangeError 119 | }), SyntaxError) 120 | }, 121 | verifyAsserts({ok: 0, fail: 1})) 122 | --------------------------------------------------------------------------------