Skip to content

Commit 7809a84

Browse files
authored
test: initial set of tests (#6)
Adds the initial set of tests for our utils.
1 parent ce57d86 commit 7809a84

File tree

6 files changed

+158
-5
lines changed

6 files changed

+158
-5
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
/node_modules
33
/lib
44
/dist
5+
/coverage
56
*.swp

eslint.config.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,14 @@ export default [
1515
rules: {
1616
'@typescript-eslint/no-unused-vars': 'off'
1717
}
18+
},
19+
{
20+
files: [
21+
'src/test/**/*.ts'
22+
],
23+
rules: {
24+
'@typescript-eslint/no-dynamic-delete': 'off',
25+
'@typescript-eslint/no-non-null-assertion': 'off'
26+
}
1827
}
1928
];

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"!dist/esm/test"
1212
],
1313
"scripts": {
14-
"build": "tsc --noEmit",
15-
"test": "npm run prepare && echo \"no tests yet\"",
14+
"build": "tsc",
15+
"test": "npm run build && c8 node --test",
1616
"lint": "eslint src",
1717
"format": "prettier --write src",
1818
"format:check": "prettier --check src",

src/env.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import {type SpawnOptions} from 'node:child_process';
21
import {
32
delimiter as pathDelimiter,
43
resolve as resolvePath,
54
dirname
65
} from 'node:path';
76

8-
export type EnvLike = SpawnOptions['env'];
7+
export type EnvLike = (typeof process)['env'];
98

109
export interface EnvPathInfo {
1110
key: string;
@@ -50,7 +49,7 @@ function addNodeBinToPath(cwd: string, path: EnvPathInfo): EnvPathInfo {
5049
return {key: path.key, value: parts.join(pathDelimiter)};
5150
}
5251

53-
export function computeEnv(cwd: string, env: EnvLike): EnvLike {
52+
export function computeEnv(cwd: string, env?: EnvLike): EnvLike {
5453
const envWithDefault = {
5554
...process.env,
5655
...env

src/test/env_test.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import {computeEnv} from '../env.js';
2+
import * as assert from 'node:assert/strict';
3+
import {test} from 'node:test';
4+
import process from 'node:process';
5+
6+
test('computeEnv', async (t) => {
7+
await t.test('adds node binaries to path', () => {
8+
const env = computeEnv(process.cwd());
9+
const path = env['PATH']!;
10+
11+
assert.ok(path.includes('node_modules/.bin'));
12+
});
13+
14+
await t.test('extends process env', () => {
15+
const env = computeEnv(process.cwd(), {
16+
foo: 'bar'
17+
});
18+
19+
for (const key in process.env) {
20+
if (key !== 'PATH') {
21+
assert.equal(env[key], process.env[key]);
22+
}
23+
}
24+
25+
assert.equal(env.foo, 'bar');
26+
});
27+
28+
await t.test('supports case-insensitive path keys', () => {
29+
const originalPath = process.env['PATH'];
30+
try {
31+
delete process.env['PATH'];
32+
const env = computeEnv(process.cwd(), {
33+
Path: '/'
34+
});
35+
const keys = [...Object.keys(env)];
36+
37+
assert.ok(keys.includes('Path'));
38+
assert.ok(!keys.includes('PATH'));
39+
} finally {
40+
process.env['PATH'] = originalPath;
41+
}
42+
});
43+
44+
await t.test('uses default key if empty path found', () => {
45+
const originalPath = process.env['PATH'];
46+
try {
47+
delete process.env['PATH'];
48+
const env = computeEnv(process.cwd(), {
49+
Path: undefined
50+
});
51+
52+
assert.ok(typeof env['PATH'] === 'string');
53+
assert.equal(env['Path'], undefined);
54+
} finally {
55+
process.env['PATH'] = originalPath;
56+
}
57+
});
58+
59+
await t.test('uses default key if no path found', () => {
60+
const originalPath = process.env['PATH'];
61+
try {
62+
delete process.env['PATH'];
63+
const env = computeEnv(process.cwd());
64+
65+
assert.ok(typeof env['PATH'] === 'string');
66+
} finally {
67+
process.env['PATH'] = originalPath;
68+
}
69+
});
70+
});

src/test/stream_test.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import {combineStreams, waitForEvent, readStreamAsString} from '../stream.js';
2+
import * as assert from 'node:assert/strict';
3+
import {test} from 'node:test';
4+
import {EventEmitter} from 'node:events';
5+
import {Readable} from 'node:stream';
6+
7+
test('waitForEvent', async (t) => {
8+
await t.test('waits for event to fire', async () => {
9+
const emitter = new EventEmitter();
10+
const waiter = waitForEvent(emitter, 'foo');
11+
emitter.emit('foo');
12+
await waiter;
13+
});
14+
});
15+
16+
test('readStreamAsString', async (t) => {
17+
await t.test('rejects on error', async () => {
18+
const streamError = new Error('fudge');
19+
const stream = new Readable({
20+
read() {
21+
this.destroy(streamError);
22+
}
23+
});
24+
try {
25+
await readStreamAsString(stream);
26+
assert.fail('expected to throw');
27+
} catch (err) {
28+
assert.equal(err, streamError);
29+
}
30+
});
31+
32+
await t.test('resolves to concatenated data', async () => {
33+
const stream = Readable.from(['foo', 'bar']);
34+
const result = await readStreamAsString(stream);
35+
assert.equal(result, 'foobar');
36+
});
37+
38+
await t.test('handles buffer data', async () => {
39+
const stream = new Readable({
40+
read() {
41+
this.push(Buffer.from('foo'));
42+
this.push(Buffer.from('bar'));
43+
this.push(null);
44+
}
45+
});
46+
const result = await readStreamAsString(stream);
47+
assert.equal(result, 'foobar');
48+
});
49+
});
50+
51+
test('combineStreams', async (t) => {
52+
await t.test('works with a single stream', async () => {
53+
const stream = Readable.from(['foo', 'bar']);
54+
const combined = combineStreams([stream]);
55+
const chunks: string[] = [];
56+
combined.on('data', (chunk: Buffer) => {
57+
chunks.push(chunk.toString());
58+
});
59+
await waitForEvent(combined, 'end');
60+
assert.deepEqual(chunks, ['foo', 'bar']);
61+
});
62+
63+
await t.test('works with multiple streams', async () => {
64+
const stream0 = Readable.from(['foo']);
65+
const stream1 = Readable.from(['bar', 'baz']);
66+
const combined = combineStreams([stream0, stream1]);
67+
const chunks: string[] = [];
68+
combined.on('data', (chunk: Buffer) => {
69+
chunks.push(chunk.toString());
70+
});
71+
await waitForEvent(combined, 'end');
72+
assert.deepEqual(chunks, ['foo', 'bar', 'baz']);
73+
});
74+
});

0 commit comments

Comments
 (0)