Skip to content

Commit 74db73b

Browse files
committed
add types
1 parent aa7de58 commit 74db73b

File tree

14 files changed

+588
-37
lines changed

14 files changed

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

index.js

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,34 @@
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 {import('.').Harness} Harness */
18+
/** @typedef {import('.').HarnessConfig} HarnessConfig */
19+
/** @typedef {import('.').TestOptions} TestOptions */
20+
/** @typedef {import('.').HarnessEventHandler} HarnessEventHandler */
21+
/** @typedef {import('.').CreateStream} CreateStream */
22+
/** @typedef {import('.').createHarness} CreateHarness */
23+
/** @typedef {import('./lib/results').Result} Result */
24+
/** @typedef {import('stream').Writable} WritableStream */
25+
1426
module.exports = (function () {
1527
var wait = false;
28+
/** @type {undefined | Harness} */
1629
var harness;
1730

31+
/** @type {(opts?: HarnessConfig) => Harness} */
1832
function getHarness(opts) {
1933
// this override is here since tests fail via nyc if createHarness is moved upwards
2034
if (!harness) {
@@ -24,6 +38,7 @@ module.exports = (function () {
2438
return harness;
2539
}
2640

41+
/** @type {(this: Harness, ...args: Parameters<Tape>) => ReturnType<Tape>} */
2742
function lazyLoad() {
2843
// eslint-disable-next-line no-invalid-this
2944
return getHarness().apply(this, arguments);
@@ -43,6 +58,7 @@ module.exports = (function () {
4358
return getHarness().only.apply(this, arguments);
4459
};
4560

61+
/** @type {CreateStream} */
4662
lazyLoad.createStream = function (opts) {
4763
var options = opts || {};
4864
if (!harness) {
@@ -66,21 +82,23 @@ module.exports = (function () {
6682
return lazyLoad;
6783
}());
6884

85+
/** @type {CreateHarness} */
6986
function createHarness(conf_) {
7087
var results = new Results({ todoIsOK: !!(process.env.TODO_IS_OK === '1') });
7188
if (!conf_ || conf_.autoclose !== false) {
7289
results.once('done', function () { results.close(); });
7390
}
7491

92+
/** @type {Harness} */
7593
function test(name, conf, cb) {
7694
var t = new Test(name, conf, cb);
7795
test._tests.push(t);
7896

7997
(function inspectCode(st) {
80-
st.on('test', function sub(st_) {
98+
st.on('test', /** @type {(st: Test) => void} */ function sub(st_) {
8199
inspectCode(st_);
82100
});
83-
st.on('result', function (r) {
101+
st.on('result', /** @type {(r: Result) => void} */ function (r) {
84102
if (!r.todo && !r.ok && typeof r !== 'string') { test._exitCode = 1; }
85103
});
86104
}(t));
@@ -90,21 +108,25 @@ function createHarness(conf_) {
90108
}
91109
test._results = results;
92110

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

113+
/** @type {CreateStream} */
95114
test.createStream = function (opts) {
96115
return results.createStream(opts);
97116
};
98117

118+
/** @type {HarnessEventHandler} */
99119
test.onFinish = function (cb) {
100120
results.on('done', cb);
101121
};
102122

123+
/** @type {HarnessEventHandler} */
103124
test.onFailure = function (cb) {
104125
results.on('fail', cb);
105126
};
106127

107128
var only = false;
129+
/** @type {() => Test} */
108130
test.only = function () {
109131
if (only) { throw new Error('there can only be one only test'); }
110132
if (conf_ && conf_.noOnly) { throw new Error('`only` tests are prohibited'); }
@@ -120,6 +142,7 @@ function createHarness(conf_) {
120142
return test;
121143
}
122144

145+
/** @type {(conf: Omit<HarnessConfig, 'autoclose'>, wait?: boolean) => Harness} */
123146
function createExitHarness(config, wait) {
124147
var noOnly = config.noOnly;
125148
var objectMode = config.objectMode;
@@ -137,9 +160,11 @@ function createExitHarness(config, wait) {
137160
if (running) { return; }
138161
running = true;
139162
var stream = harness.createStream({ objectMode: objectMode });
140-
var es = stream.pipe(cStream || createDefaultStream());
163+
// eslint-disable-next-line no-extra-parens
164+
var es = stream.pipe(/** @type {WritableStream} */ (cStream || createDefaultStream()));
141165
if (canEmitExit && es) { // in node v0.4, `es` is `undefined`
142166
// TODO: use `err` arg?
167+
// @ts-expect-error
143168
// eslint-disable-next-line no-unused-vars
144169
es.on('error', function (err) { harness._exitCode = 1; });
145170
}
@@ -180,6 +205,7 @@ function createExitHarness(config, wait) {
180205
}
181206

182207
module.exports.createHarness = createHarness;
183-
module.exports.Test = Test;
184-
module.exports.test = module.exports; // tap compat
185-
module.exports.test.skip = Test.skip;
208+
var moduleExports = module.exports; // this hack is needed because TS has a bug with seemingly circular exports
209+
moduleExports.Test = Test;
210+
moduleExports.test = module.exports; // tap compat
211+
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: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import through from '@ljharb/through';
2+
import type { EventEmitter } from 'events';
3+
4+
import type { StreamOptions } from '../';
5+
import Test = require('./test');
6+
7+
declare class Results extends EventEmitter {
8+
constructor(options?: { todoIsOK?: boolean });
9+
10+
count: number;
11+
fail: number;
12+
pass: number;
13+
tests: Test[];
14+
todo: number;
15+
todoIsOK: boolean;
16+
closed?: boolean;
17+
18+
_isRunning: boolean;
19+
_only: Test | null;
20+
_stream: through.ThroughStream;
21+
22+
close(this: Results): void;
23+
createStream(this: Results, opts?: StreamOptions): through.ThroughStream;
24+
only(this: Results, t: Test): void;
25+
push(this: Results, t: Test): void;
26+
27+
_watch(this: Results, t: Test): void;
28+
}
29+
30+
declare namespace Results {
31+
export type Operator = string;
32+
33+
export type Result = {
34+
id: number;
35+
ok: boolean;
36+
skip: unknown;
37+
todo: unknown;
38+
name?: string;
39+
operator: undefined | Operator;
40+
objectPrintDepth?: number;
41+
actual?: unknown;
42+
expected?: unknown;
43+
error?: unknown;
44+
functionName?: string;
45+
file?: string;
46+
line?: number;
47+
column?: number;
48+
at?: string;
49+
};
50+
}
51+
52+
export = Results;

0 commit comments

Comments
 (0)