0
# Tape Promise
1
2
Tape Promise provides Promise and ES2016 (ES7) async/await support for the Tape testing framework. It acts as a decorator that enhances tape with the ability to handle Promise-based and async/await test functions without requiring tape as a direct dependency.
3
4
## Package Information
5
6
- **Package Name**: tape-promise
7
- **Package Type**: npm
8
- **Language**: JavaScript (with Babel transpilation)
9
- **Installation**: `npm install --save-dev tape-promise`
10
- **Prerequisites**: `npm install --save-dev tape`
11
12
## Core Imports
13
14
ES6 (ES2015):
15
16
```javascript
17
import tape from 'tape';
18
import tapePromise from 'tape-promise';
19
const test = tapePromise(tape); // decorate tape
20
```
21
22
ES5 (CommonJS):
23
24
```javascript
25
var tape = require('tape');
26
var tapePromise = require('tape-promise').default; // notice 'default'
27
var test = tapePromise(tape); // decorate tape
28
```
29
30
Convenience import (pre-configured):
31
32
```javascript
33
// ES6
34
import test from 'tape-promise/tape';
35
36
// ES5
37
var test = require('tape-promise/tape');
38
```
39
40
## Basic Usage
41
42
```javascript
43
import test from 'tape-promise/tape';
44
45
// Promise-based test
46
test('promise test', function (t) {
47
return delay(100).then(function () {
48
t.true(true);
49
});
50
});
51
52
// Async/await test
53
test('async test', async function (t) {
54
await delay(100);
55
t.true(true);
56
// t.end() is optional for async functions
57
});
58
59
// Regular tape test still works
60
test('regular test', function (t) {
61
t.true(true);
62
t.end();
63
});
64
65
// Example helper function
66
function delay(time) {
67
return new Promise(function (resolve) {
68
setTimeout(function () {
69
resolve();
70
}, time);
71
});
72
}
73
```
74
75
## Architecture
76
77
Tape Promise uses a decorator pattern to enhance tape's functionality without requiring tape as a direct dependency:
78
79
- **Factory Function**: `tapePromiseFactory()` accepts any tape-compatible test function and returns an enhanced version
80
- **Promise Detection**: Uses `is-promise` library to identify when test functions return promises
81
- **Automatic Resolution**: Hooks into promise resolution to automatically call `t.end()` when promises resolve
82
- **Error Handling**: Captures both synchronous exceptions and unhandled promise rejections
83
- **Method Preservation**: Copies all original tape methods (skip, only, etc.) to the enhanced function
84
- **Assertion Enhancement**: Adds new promise-specific assertion methods (`rejects`, `doesNotReject`) to the Test prototype
85
- **Execution Safety**: Uses `onetime` to ensure `t.end()` is only called once per test
86
- **Multiple Entry Points**: Provides both factory function and pre-configured convenience module
87
88
This design allows tape-promise to work with any tape-compatible library while adding comprehensive promise and async/await support.
89
90
## Capabilities
91
92
### Tape Promise Factory
93
94
Creates a decorated version of tape that supports Promise and async/await test functions.
95
96
```javascript { .api }
97
/**
98
* Factory function that decorates a tape test function with promise support
99
* @param {Function} tapeTest - The tape test function to be decorated
100
* @returns {Function} Enhanced test function with promise support
101
*/
102
function tapePromiseFactory(tapeTest);
103
```
104
105
The returned test function supports:
106
- All original tape methods and properties (skip, only, etc.)
107
- Automatic promise resolution handling
108
- Async/await test functions
109
- Enhanced assertion methods
110
111
### Enhanced Test Function
112
113
The decorated test function accepts the same arguments as tape but with promise support.
114
115
```javascript { .api }
116
/**
117
* Enhanced test function that supports promises and async/await
118
* @param {string} [name] - Test name
119
* @param {Object} [opts] - Test options
120
* @param {Function} callback - Test function that can return promises or be async
121
*/
122
function test(name, opts, callback);
123
```
124
125
**Usage patterns:**
126
127
```javascript
128
// Named test with promise return
129
test('my test', function (t) {
130
return someAsyncOperation().then(() => {
131
t.pass('async operation completed');
132
});
133
});
134
135
// Async/await test
136
test('async test', async function (t) {
137
const result = await someAsyncOperation();
138
t.equal(result, 'expected');
139
});
140
141
// Test with options
142
test('test with options', { timeout: 5000 }, async function (t) {
143
await longRunningOperation();
144
t.pass('completed');
145
});
146
```
147
148
### Promise Rejection Assertions
149
150
Enhanced assertion methods for testing promise rejection scenarios.
151
152
#### t.rejects()
153
154
Asserts that a promise will reject.
155
156
```javascript { .api }
157
/**
158
* Assert that the promise will reject
159
* @param {Promise|Function} promise - Promise to test or function that returns a promise
160
* @param {RegExp|Function} [expected] - Expected error pattern (RegExp) or constructor (Function)
161
* @param {string} [message='should reject'] - Assertion message
162
* @param {Object} [extra] - Extra assertion data
163
* @returns {Promise} Promise that resolves when assertion completes
164
*/
165
t.rejects(promise, expected, message, extra);
166
```
167
168
**Usage examples:**
169
170
```javascript
171
test('rejection tests', async (t) => {
172
// Test promise rejection
173
await t.rejects(Promise.reject(new Error('failed')));
174
175
// Test with error pattern
176
await t.rejects(
177
Promise.reject(new Error('connection failed')),
178
/connection failed/
179
);
180
181
// Test with error constructor
182
await t.rejects(
183
Promise.reject(new TypeError('invalid type')),
184
TypeError
185
);
186
187
// Test function that returns rejecting promise
188
await t.rejects(function () {
189
return Promise.reject(new Error('async error'));
190
});
191
192
// With custom message
193
await t.rejects(
194
failingAsync(),
195
/network/,
196
'should fail with network error'
197
);
198
});
199
```
200
201
#### t.doesNotReject()
202
203
Asserts that a promise will resolve (not reject).
204
205
```javascript { .api }
206
/**
207
* Assert that the promise will resolve
208
* @param {Promise|Function} promise - Promise to test or function that returns a promise
209
* @param {RegExp|Function} [expected] - Error pattern that should NOT be thrown
210
* @param {string} [message='should resolve'] - Assertion message
211
* @param {Object} [extra] - Extra assertion data
212
* @returns {Promise} Promise that resolves when assertion completes
213
*/
214
t.doesNotReject(promise, expected, message, extra);
215
```
216
217
**Usage examples:**
218
219
```javascript
220
test('resolution tests', async (t) => {
221
// Test promise resolution
222
await t.doesNotReject(Promise.resolve('success'));
223
224
// Test that specific error is NOT thrown
225
await t.doesNotReject(
226
someAsyncOperation(),
227
TypeError,
228
'should not throw TypeError'
229
);
230
231
// Test function that returns resolving promise
232
await t.doesNotReject(function () {
233
return Promise.resolve('data');
234
});
235
});
236
```
237
238
## Enhanced Methods
239
240
### test.only()
241
242
The `only` method is also enhanced with promise support for focused testing.
243
244
```javascript { .api }
245
/**
246
* Enhanced only method with promise support
247
* @param {string} [name] - Test name
248
* @param {Object} [opts] - Test options
249
* @param {Function} callback - Test function that can return promises or be async
250
*/
251
test.only(name, opts, callback);
252
```
253
254
**Usage:**
255
256
```javascript
257
test.only('focused async test', async function (t) {
258
const result = await criticalAsyncOperation();
259
t.ok(result, 'critical operation succeeded');
260
});
261
```
262
263
## Error Handling
264
265
Tape Promise automatically handles:
266
267
- **Unhandled Promise Rejections**: Caught and passed to `t.end()`
268
- **Synchronous Exceptions**: Caught in try/catch and passed to `t.end()`
269
- **Promise Resolution**: Automatically calls `t.end()` when promise resolves (unless `t.plan()` was called)
270
271
## Types
272
273
```javascript { .api }
274
// Main factory function signature
275
/**
276
* @typedef {Function} tapePromiseFactory
277
* @param {TapeTest} tapeTest - Original tape test function
278
* @returns {EnhancedTest} Enhanced test function with promise support
279
*/
280
281
// Enhanced test function interface
282
/**
283
* @typedef {Function} EnhancedTest
284
* @param {string} [name] - Test name
285
* @param {TestOptions} [opts] - Test options
286
* @param {TestCallback} callback - Test function
287
* @property {EnhancedTest} skip - Skip this test
288
* @property {EnhancedTest} only - Run only this test (with promise support)
289
*/
290
291
// Test callback types
292
/**
293
* @typedef {Function} TestCallback
294
* @param {EnhancedAssert} t - Test assertion object
295
* @returns {void|Promise} Can return void or a Promise
296
*/
297
298
// Enhanced assertion interface (extends tape's assertions)
299
/**
300
* @typedef {Object} EnhancedAssert
301
* @property {Function} rejects - Assert promise rejection
302
* @property {Function} doesNotReject - Assert promise resolution
303
* @property {Function} end - End the test (automatically called for promises)
304
* @property {Function} plan - Plan number of assertions
305
* // ... all standard tape assertions (ok, equal, deepEqual, etc.)
306
*/
307
308
// Test options
309
/**
310
* @typedef {Object} TestOptions
311
* @property {number} [timeout] - Test timeout in milliseconds
312
* @property {boolean} [skip] - Skip this test
313
* @property {Object} [objectPrintDepth] - Object print depth for assertions
314
* // ... other tape options
315
*/
316
317
// Internal helper types
318
/**
319
* @typedef {Object} TestArgs
320
* @property {string} name - Resolved test name
321
* @property {TestOptions} opts - Resolved test options
322
* @property {TestCallback} cb - Test callback function
323
*/
324
```
325
326
## Dependencies
327
328
- `is-promise`: Utility for checking if a value is a promise
329
- `onetime`: Ensures `t.end()` is only called once per test