Skip to content

Commit 2ad380e

Browse files
committed
add types
1 parent eafacf6 commit 2ad380e

14 files changed

+643
-37
lines changed

.github/workflows/node-aught.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ jobs:
99
range: '< 10'
1010
type: minors
1111
command: npm run tests-only
12+
skip-ls-check: true

bin/import-or-require.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const { extname: extnamePath } = require('path');
44
const { pathToFileURL } = require('url');
55
const getPackageType = require('get-package-type');
66

7+
/** @type {(file: string) => undefined | Promise<unknown>} */
78
// eslint-disable-next-line consistent-return
89
module.exports = function importOrRequire(file) {
910
const ext = extnamePath(file);

bin/tape

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ var hasImport = require('has-dynamic-import');
9595

9696
var tape = require('../');
9797

98+
/** @type {(hasSupport: boolean) => Promise<void> | void} */
9899
function importFiles(hasSupport) {
99100
if (!hasSupport) {
100101
return files.forEach(function (x) { require(x); });
@@ -104,6 +105,7 @@ function importFiles(hasSupport) {
104105

105106
tape.wait();
106107

108+
/** @type {null | undefined | Promise<unknown>} */
107109
var filesPromise = files.reduce(function (promise, file) {
108110
return promise ? promise.then(function () {
109111
return importOrRequire(file);

index.d.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import through = require('@ljharb/through');
2+
3+
import Test = require('./lib/test');
4+
5+
namespace tape {
6+
export type TestOptions = {
7+
objectPrintDepth?: number | undefined;
8+
skip?: boolean | undefined;
9+
timeout?: number | undefined;
10+
todo?: boolean | undefined;
11+
};
12+
13+
export interface AssertOptions {
14+
skip?: boolean | string | undefined;
15+
todo?: boolean | string | undefined;
16+
message?: string | undefined;
17+
actual?: unknown;
18+
expected?: unknown;
19+
exiting?: boolean;
20+
};
21+
22+
export interface TestCase {
23+
(test: Test): void | Promise<void>;
24+
};
25+
26+
export interface StreamOptions {
27+
objectMode?: boolean | undefined;
28+
};
29+
30+
declare function createStream(opts?: StreamOptions): ReturnType<through>;
31+
32+
export type CreateStream = typeof createStream;
33+
34+
export type HarnessEventHandler = (cb: Test.SyncCallback, ...rest: unknown[]) => void;
35+
36+
function only(name: string, cb: tape.TestCase): void;
37+
function only(name: string, opts: tape.TestOptions, cb: tape.TestCase): void;
38+
function only(cb: tape.TestCase): void;
39+
function only(opts: tape.TestOptions, cb: tape.TestCase): void;
40+
41+
export type Harness = {
42+
(this: ThisType<Test>, ...args: Parameters<Test>): Test;
43+
run?: () => void;
44+
only: typeof only;
45+
_exitCode: number;
46+
_results: Results;
47+
_tests: Test[];
48+
close: () => void;
49+
createStream: CreateStream;
50+
onFailure: HarnessEventHandler;
51+
onFinish: HarnessEventHandler;
52+
};
53+
54+
export type HarnessConfig = {
55+
autoclose?: boolean;
56+
noOnly?: boolean;
57+
stream?: NodeJS.WritableStream;
58+
exit?: boolean;
59+
} & StreamOptions;
60+
61+
declare function createHarness(conf_?: HarnessConfig): Harness;
62+
Test = Test;
63+
test = typeof tape;
64+
skip = Test['skip'];
65+
}
66+
67+
declare function tape(this: tape.Harness, name: string, cb: Test.Callback): Test;
68+
declare function tape(this: tape.Harness, name: string, opts: tape.TestOptions, cb: Test.Callback): Test;
69+
declare function tape(this: tape.Harness, opts?: tape.TestOptions): Test;
70+
declare function tape(this: tape.Harness, opts?: tape.TestOptions, cb: Test.Callback): Test;
71+
72+
export = tape;

index.js

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
'use strict';
22

33
var defined = require('defined');
4+
var through = require('@ljharb/through');
5+
46
var createDefaultStream = require('./lib/default_stream');
57
var Test = require('./lib/test');
68
var Results = require('./lib/results');
7-
var through = require('@ljharb/through');
89

910
var canEmitExit = typeof process !== 'undefined' && process
11+
// @ts-expect-error i think old browserify uses `process.browser`
1012
&& typeof process.on === 'function' && process.browser !== true;
1113
var canExit = typeof process !== 'undefined' && process
1214
&& typeof process.exit === 'function';
1315

16+
/** @typedef {import('.')} Tape */
17+
/** @typedef {ThisParameterType<Tape>} Harness */
18+
/** @typedef {import('.').HarnessConfig} HarnessConfig */
19+
1420
module.exports = (function () {
1521
var wait = false;
22+
/** @type {undefined | Harness} */
1623
var harness;
1724

25+
/** @type {(opts?: HarnessConfig) => Harness} */
1826
function getHarness(opts) {
1927
// this override is here since tests fail via nyc if createHarness is moved upwards
2028
if (!harness) {
@@ -24,6 +32,7 @@ module.exports = (function () {
2432
return harness;
2533
}
2634

35+
/** @type {(this: Harness, ...args: Parameters<Tape>) => ReturnType<Tape>} */
2736
function lazyLoad() {
2837
// eslint-disable-next-line no-invalid-this
2938
return getHarness().apply(this, arguments);
@@ -43,11 +52,13 @@ module.exports = (function () {
4352
return getHarness().only.apply(this, arguments);
4453
};
4554

55+
/** @type {import('.').CreateStream} */
4656
lazyLoad.createStream = function (opts) {
4757
var options = opts || {};
4858
if (!harness) {
4959
var output = through();
50-
getHarness({ stream: output, objectMode: options.objectMode });
60+
// eslint-disable-next-line no-extra-parens
61+
getHarness({ stream: /** @type {import('stream').Writable} */ (output), objectMode: options.objectMode });
5162
return output;
5263
}
5364
return harness.createStream(options);
@@ -66,21 +77,23 @@ module.exports = (function () {
6677
return lazyLoad;
6778
}());
6879

80+
/** @type {Tape['createHarness']} */
6981
function createHarness(conf_) {
7082
var results = new Results({ todoIsOK: !!(process.env.TODO_IS_OK === '1') });
7183
if (!conf_ || conf_.autoclose !== false) {
7284
results.once('done', function () { results.close(); });
7385
}
7486

87+
/** @type {(name: string, conf: import('.').TestOptions, cb: Test.Callback) => Test} */
7588
function test(name, conf, cb) {
7689
var t = new Test(name, conf, cb);
7790
test._tests.push(t);
7891

7992
(function inspectCode(st) {
80-
st.on('test', function sub(st_) {
93+
st.on('test', /** @type {(st: Test) => void} */ function sub(st_) {
8194
inspectCode(st_);
8295
});
83-
st.on('result', function (r) {
96+
st.on('result', /** @type {(r: import('./lib/results').Result) => void} */ function (r) {
8497
if (!r.todo && !r.ok && typeof r !== 'string') { test._exitCode = 1; }
8598
});
8699
}(t));
@@ -90,21 +103,25 @@ function createHarness(conf_) {
90103
}
91104
test._results = results;
92105

93-
test._tests = [];
106+
/** @type {Test[]} */ test._tests = [];
94107

108+
/** @type {import('.').CreateStream} */
95109
test.createStream = function (opts) {
96110
return results.createStream(opts);
97111
};
98112

113+
/** @type {import('.').HarnessEventHandler} */
99114
test.onFinish = function (cb) {
100115
results.on('done', cb);
101116
};
102117

118+
/** @type {import('.').HarnessEventHandler} */
103119
test.onFailure = function (cb) {
104120
results.on('fail', cb);
105121
};
106122

107123
var only = false;
124+
/** @type {() => ReturnType<typeof test>} */
108125
test.only = function () {
109126
if (only) { throw new Error('there can only be one only test'); }
110127
if (conf_ && conf_.noOnly) { throw new Error('`only` tests are prohibited'); }
@@ -117,9 +134,12 @@ function createHarness(conf_) {
117134

118135
test.close = function () { results.close(); };
119136

137+
test.run = function () {};
138+
120139
return test;
121140
}
122141

142+
/** @type {(conf: Omit<HarnessConfig, 'autoclose'>, wait?: boolean) => Harness} */
123143
function createExitHarness(config, wait) {
124144
var noOnly = config.noOnly;
125145
var objectMode = config.objectMode;
@@ -140,6 +160,7 @@ function createExitHarness(config, wait) {
140160
var es = stream.pipe(cStream || createDefaultStream());
141161
if (canEmitExit && es) { // in node v0.4, `es` is `undefined`
142162
// TODO: use `err` arg?
163+
// @ts-expect-error
143164
// eslint-disable-next-line no-unused-vars
144165
es.on('error', function (err) { harness._exitCode = 1; });
145166
}
@@ -180,6 +201,7 @@ function createExitHarness(config, wait) {
180201
}
181202

182203
module.exports.createHarness = createHarness;
183-
module.exports.Test = Test;
184-
module.exports.test = module.exports; // tap compat
185-
module.exports.test.skip = Test.skip;
204+
var moduleExports = module.exports; // this hack is needed because TS has a bug with seemingly circular exports
205+
moduleExports.Test = Test;
206+
moduleExports.test = module.exports; // tap compat
207+
moduleExports.skip = Test.skip;

lib/default_stream.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import type { ThroughStream } from "@ljharb/through";
2+
3+
declare function defaultStream(): ThroughStream;
4+
5+
export = defaultStream;

lib/default_stream.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
var through = require('@ljharb/through');
44
var fs = require('fs');
55

6+
/** @type {import('./default_stream')} */
67
module.exports = function () {
78
var line = '';
89
var stream = through(write, flush);
910
return stream;
1011

12+
/** @type {(buf: unknown) => void} */
1113
function write(buf) {
1214
if (
1315
buf == null // eslint-disable-line eqeqeq
@@ -16,10 +18,11 @@ module.exports = function () {
1618
flush();
1719
return;
1820
}
19-
for (var i = 0; i < buf.length; i++) {
20-
var c = typeof buf === 'string'
21-
? buf.charAt(i)
22-
: String.fromCharCode(buf[i]);
21+
var b = /** @type {string | ArrayLike<number>} */ (buf); // eslint-disable-line no-extra-parens
22+
for (var i = 0; i < b.length; i++) {
23+
var c = typeof b === 'string'
24+
? b.charAt(i)
25+
: String.fromCharCode(b[i]);
2326
if (c === '\n') {
2427
flush();
2528
} else {

lib/results.d.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import through = require('@ljharb/through');
2+
import type { EventEmitter } from 'events';
3+
4+
import type { StreamOptions } from '../';
5+
import Test = require('./test');
6+
7+
type Stream = ReturnType<through>;
8+
9+
declare class Results extends EventEmitter {
10+
constructor(options?: { todoIsOK?: boolean });
11+
12+
count: number;
13+
fail: number;
14+
pass: number;
15+
tests: Test[];
16+
todo: number;
17+
todoIsOK: boolean;
18+
closed?: boolean;
19+
20+
_isRunning: boolean;
21+
_only: Test | null;
22+
_stream: Stream;
23+
24+
close(this: Results): void;
25+
createStream(this: Results, opts?: StreamOptions): Stream;
26+
only(this: Results, t: Test): void;
27+
push(this: Results, t: Test): void;
28+
29+
_watch(this: Results, t: Test): void;
30+
}
31+
32+
namespace Results {
33+
export type Operator = string;
34+
35+
export type Result = {
36+
id: number;
37+
ok: boolean;
38+
skip: unknown;
39+
todo: unknown;
40+
name?: string;
41+
operator: undefined | Operator;
42+
objectPrintDepth?: number;
43+
actual?: unknown;
44+
expected?: unknown;
45+
error?: unknown;
46+
functionName?: string;
47+
file?: string;
48+
line?: number;
49+
column?: number;
50+
at?: string;
51+
};
52+
}
53+
54+
export = Results;

0 commit comments

Comments
 (0)