From e30f200b84ff7f862f61fe5c69185aaa816c5b25 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Fri, 9 Feb 2024 12:29:22 +0100 Subject: [PATCH 01/23] test: replace t.pass with t.ok (#2721) --- test/client-keep-alive.js | 20 ++++++++--------- test/client-pipeline.js | 12 +++++----- test/client-pipelining.js | 24 ++++++++++---------- test/client-post.js | 4 ++-- test/client-reconnect.js | 4 ++-- test/client-request.js | 30 ++++++++++++------------- test/client-stream.js | 4 ++-- test/client-timeout.js | 2 +- test/client-upgrade.js | 2 +- test/client-write-max-listeners.js | 2 +- test/client.js | 36 +++++++++++++++--------------- test/close-and-destroy.js | 2 +- test/connect-errconnect.js | 2 +- test/content-length.js | 12 +++++----- test/get-head-body.js | 6 ++--- test/http-100.js | 6 ++--- test/http2.js | 2 +- test/inflight-and-close.js | 6 ++--- test/issue-810.js | 8 +++---- test/max-headers.js | 2 +- test/node-test/client-dispatch.js | 8 +++---- test/parser-issues.js | 2 +- test/pipeline-pipelining.js | 4 ++-- test/pool.js | 20 ++++++++--------- test/proxy-agent.js | 32 +++++++++++++------------- test/redirect-request.js | 2 +- test/retry-handler.js | 36 +++++++++++++++--------------- test/socket-back-pressure.js | 2 +- test/socket-timeout.js | 2 +- test/tls-session-reuse.js | 4 ++-- test/tls.js | 16 ++++++------- 31 files changed, 157 insertions(+), 157 deletions(-) diff --git a/test/client-keep-alive.js b/test/client-keep-alive.js index 961a44f1a8b..15e432c7b2c 100644 --- a/test/client-keep-alive.js +++ b/test/client-keep-alive.js @@ -34,7 +34,7 @@ test('keep-alive header', (t) => { t.fail() }, 4e3) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') clearTimeout(timeout) }) }).resume() @@ -76,7 +76,7 @@ test('keep-alive header 0', (t) => { t.error(err) body.on('end', () => { client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') }) clock.tick(600) }).resume() @@ -110,7 +110,7 @@ test('keep-alive header 1', (t) => { t.fail() }, 0) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') clearTimeout(timeout) }) }).resume() @@ -144,7 +144,7 @@ test('keep-alive header no postfix', (t) => { t.fail() }, 4e3) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') clearTimeout(timeout) }) }).resume() @@ -180,7 +180,7 @@ test('keep-alive not timeout', (t) => { t.fail() }, 3e3) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') clearTimeout(timeout) }) }).resume() @@ -217,7 +217,7 @@ test('keep-alive threshold', (t) => { t.fail() }, 5e3) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') clearTimeout(timeout) }) }).resume() @@ -254,7 +254,7 @@ test('keep-alive max keepalive', (t) => { t.fail() }, 3e3) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') clearTimeout(timeout) }) }).resume() @@ -296,7 +296,7 @@ test('connection close', (t) => { }, 3e3) client.once('disconnect', () => { close = false - t.pass() + t.ok(true, 'pass') clearTimeout(timeout) }) }).resume() @@ -312,7 +312,7 @@ test('connection close', (t) => { t.fail() }, 3e3) client.once('disconnect', () => { - t.pass() + t.ok(true, 'pass') clearTimeout(timeout) }) }).resume() @@ -350,7 +350,7 @@ test('Disable keep alive', (t) => { }, (err, { body }) => { t.error(err) body.on('end', () => { - t.pass() + t.ok(true, 'pass') }).resume() }) }).resume() diff --git a/test/client-pipeline.js b/test/client-pipeline.js index 300e42c7eb2..e37657456ff 100644 --- a/test/client-pipeline.js +++ b/test/client-pipeline.js @@ -201,7 +201,7 @@ test('pipeline invalid handler return after destroy should not error', (t) => { t.equal(err.message, 'asd') }) .on('close', () => { - t.pass() + t.ok(true, 'pass') }) .end() }) @@ -315,7 +315,7 @@ test('pipeline backpressure', (t) => { duplex.resume() }) }).on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -412,7 +412,7 @@ test('pipeline destroy and throw handler', (t) => { t.type(err, errors.RequestAbortedError) }) .on('close', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -443,7 +443,7 @@ test('pipeline abort res', (t) => { }, 100) client.on('disconnect', () => { clearTimeout(timeout) - t.pass() + t.ok(true, 'pass') }) }) return body @@ -789,7 +789,7 @@ test('pipeline legacy stream', (t) => { }) .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) .end() }) @@ -896,7 +896,7 @@ test('pipeline body without destroy', (t) => { }) .end() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) .resume() }) diff --git a/test/client-pipelining.js b/test/client-pipelining.js index 38a99f54c5b..25441407f43 100644 --- a/test/client-pipelining.js +++ b/test/client-pipelining.js @@ -355,7 +355,7 @@ function errordInflightPost (bodyType) { serverRes.end() }) .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -391,7 +391,7 @@ test('pipelining non-idempotent', (t) => { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') ended = true }) }) @@ -449,7 +449,7 @@ function pipeliningNonIdempotentWithBody (bodyType) { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) @@ -504,7 +504,7 @@ function pipeliningHeadBusy (bodyType) { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) body.push(null) @@ -525,7 +525,7 @@ function pipeliningHeadBusy (bodyType) { .resume() .on('end', () => { ended = true - t.pass() + t.ok(true, 'pass') }) }) body.push(null) @@ -575,7 +575,7 @@ test('pipelining empty pipeline before reset', (t) => { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) t.equal(client[kBusy], false) @@ -590,7 +590,7 @@ test('pipelining empty pipeline before reset', (t) => { .resume() .on('end', () => { ended = true - t.pass() + t.ok(true, 'pass') }) }) t.equal(client[kBusy], true) @@ -628,7 +628,7 @@ function pipeliningIdempotentBusy (bodyType) { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) body.push(null) @@ -649,7 +649,7 @@ function pipeliningIdempotentBusy (bodyType) { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) body.push(null) @@ -688,7 +688,7 @@ function pipeliningIdempotentBusy (bodyType) { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) body.push(null) @@ -734,7 +734,7 @@ test('pipelining blocked', (t) => { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) client.request({ @@ -745,7 +745,7 @@ test('pipelining blocked', (t) => { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) diff --git a/test/client-post.js b/test/client-post.js index fc696c951a5..82203ad36c7 100644 --- a/test/client-post.js +++ b/test/client-post.js @@ -32,7 +32,7 @@ test('request post blob', { skip: !Blob }, (t) => { }, (err, data) => { t.error(err) data.body.resume().on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -66,7 +66,7 @@ test('request post arrayBuffer', { skip: !Blob }, (t) => { }, (err, data) => { t.error(err) data.body.resume().on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) diff --git a/test/client-reconnect.js b/test/client-reconnect.js index 85f76ef5f62..d8ed2ce4ddd 100644 --- a/test/client-reconnect.js +++ b/test/client-reconnect.js @@ -38,13 +38,13 @@ test('multiple reconnect', (t) => { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) client.on('disconnect', () => { if (++n === 1) { - t.pass() + t.ok(true, 'pass') } process.nextTick(() => { clock.tick(1000) diff --git a/test/client-request.js b/test/client-request.js index ebcc0c2e96f..aa9405b2fcc 100644 --- a/test/client-request.js +++ b/test/client-request.js @@ -36,7 +36,7 @@ test('request dump', (t) => { t.error(err) body.dump().then(() => { dumped = true - t.pass() + t.ok(true, 'pass') }) }) }) @@ -270,7 +270,7 @@ test('destroy socket abruptly with keep-alive', { skip: true }, async (t) => { /* eslint-enable */ t.fail('no error') } catch (err) { - t.pass('error happened') + t.ok(true, 'error happened') } }) @@ -490,7 +490,7 @@ test('request post body no missing data', (t) => { maxRedirections: 2 }) await body.text() - t.pass() + t.ok(true, 'pass') }) }) @@ -527,7 +527,7 @@ test('request post body no extra data handler', (t) => { maxRedirections: 0 }) await body.text() - t.pass() + t.ok(true, 'pass') }) }) @@ -552,7 +552,7 @@ test('request with onInfo callback', (t) => { }) t.equal(infos.length, 1) t.equal(infos[0].statusCode, 102) - t.pass() + t.ok(true, 'pass') }) }) @@ -585,7 +585,7 @@ test('request with onInfo callback but socket is destroyed before end of respons } t.equal(infos.length, 1) t.equal(infos[0].statusCode, 102) - t.pass() + t.ok(true, 'pass') }) }) @@ -622,7 +622,7 @@ test('request onInfo callback headers parsing', async (t) => { t.equal(infos.length, 1) t.equal(infos[0].statusCode, 103) t.same(infos[0].headers, { link: '; rel=preload; as=style' }) - t.pass() + t.ok(true, 'pass') }) test('request raw responseHeaders', async (t) => { @@ -659,7 +659,7 @@ test('request raw responseHeaders', async (t) => { t.equal(infos.length, 1) t.same(infos[0].headers, ['Link', '; rel=preload; as=style']) t.same(headers, ['Date', 'Sat, 09 Oct 2010 14:28:02 GMT', 'Connection', 'close']) - t.pass() + t.ok(true, 'pass') }) test('request formData', (t) => { @@ -793,7 +793,7 @@ test('request post body Buffer from string', (t) => { maxRedirections: 2 }) await body.text() - t.pass() + t.ok(true, 'pass') }) }) @@ -823,7 +823,7 @@ test('request post body Buffer from buffer', (t) => { maxRedirections: 2 }) await body.text() - t.pass() + t.ok(true, 'pass') }) }) @@ -853,7 +853,7 @@ test('request post body Uint8Array', (t) => { maxRedirections: 2 }) await body.text() - t.pass() + t.ok(true, 'pass') }) }) @@ -883,7 +883,7 @@ test('request post body Uint32Array', (t) => { maxRedirections: 2 }) await body.text() - t.pass() + t.ok(true, 'pass') }) }) @@ -913,7 +913,7 @@ test('request post body Float64Array', (t) => { maxRedirections: 2 }) await body.text() - t.pass() + t.ok(true, 'pass') }) }) @@ -943,7 +943,7 @@ test('request post body BigUint64Array', (t) => { maxRedirections: 2 }) await body.text() - t.pass() + t.ok(true, 'pass') }) }) @@ -973,6 +973,6 @@ test('request post body DataView', (t) => { maxRedirections: 2 }) await body.text() - t.pass() + t.ok(true, 'pass') }) }) diff --git a/test/client-stream.js b/test/client-stream.js index 7732187f159..a77804ace51 100644 --- a/test/client-stream.js +++ b/test/client-stream.js @@ -729,7 +729,7 @@ test('stream needDrain', (t) => { }) p.then(() => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -782,7 +782,7 @@ test('stream legacy needDrain', (t) => { }) p.then(() => { - t.pass() + t.ok(true, 'pass') }) }) diff --git a/test/client-timeout.js b/test/client-timeout.js index e02c46ceff3..38895c600c6 100644 --- a/test/client-timeout.js +++ b/test/client-timeout.js @@ -187,7 +187,7 @@ test('parser resume with no body timeout', (t) => { }, onComplete () { - t.pass() + t.ok(true, 'pass') }, onError (err) { t.error(err) diff --git a/test/client-upgrade.js b/test/client-upgrade.js index 80aa7314b30..84b84424e97 100644 --- a/test/client-upgrade.js +++ b/test/client-upgrade.js @@ -316,7 +316,7 @@ test('upgrade aborted', (t) => { signal.emit('abort') client.close(() => { - t.pass() + t.ok(true, 'pass') }) }) }) diff --git a/test/client-write-max-listeners.js b/test/client-write-max-listeners.js index c511fb4fb68..237bb527f10 100644 --- a/test/client-write-max-listeners.js +++ b/test/client-write-max-listeners.js @@ -27,7 +27,7 @@ test('socket close listener does not leak', (t) => { const onRequest = (err, data) => { t.error(err) - data.body.on('end', () => t.pass()).resume() + data.body.on('end', () => t.ok(true, 'pass')).resume() } function onWarning (warning) { diff --git a/test/client.js b/test/client.js index 5aa031f6907..7f23ecd034d 100644 --- a/test/client.js +++ b/test/client.js @@ -469,7 +469,7 @@ test('basic head', (t) => { body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) @@ -480,7 +480,7 @@ test('basic head', (t) => { body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -509,7 +509,7 @@ test('basic head (IPv6)', { skip: !hasIPv6 }, (t) => { body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) @@ -520,7 +520,7 @@ test('basic head (IPv6)', { skip: !hasIPv6 }, (t) => { body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -611,7 +611,7 @@ test('head with host header', (t) => { body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -1061,7 +1061,7 @@ test('basic POST with empty stream', (t) => { t.fail() }) .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -1124,7 +1124,7 @@ test('10 times HEAD', (t) => { body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) } @@ -1256,7 +1256,7 @@ test('multiple destroy callback', (t) => { data.body .resume() .on('error', () => { - t.pass() + t.ok(true, 'pass') }) client.destroy(new Error(), (err) => { t.error(err) @@ -1316,7 +1316,7 @@ test('only one streaming req at a time', (t) => { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) t.equal(client[kBusy], true) @@ -1370,7 +1370,7 @@ test('only one async iterating req at a time', (t) => { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) t.equal(client[kBusy], true) @@ -1399,7 +1399,7 @@ test('300 requests succeed', (t) => { data.body.on('data', (chunk) => { t.equal(chunk.toString(), 'asd') }).on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) } @@ -1650,7 +1650,7 @@ test('emit disconnect after destroy', t => { let disconnected = false client.on('disconnect', () => { disconnected = true - t.pass() + t.ok(true, 'pass') }) client.destroy(() => { t.equal(disconnected, true) @@ -1684,7 +1684,7 @@ test('end response before request', t => { t.fail() }) .on('end', () => { - t.pass() + t.ok(true, 'pass') }) .resume() client.on('disconnect', (url, targets, err) => { @@ -1808,7 +1808,7 @@ test('async iterator error from server destroys early', (t) => { yield 'inner-value' t.fail('should not get here, iterator should be destroyed') } finally { - t.ok(true) + t.ok(true, 'pass') } })() client.request({ path: '/', method: 'POST', body }, (err, { statusCode, body }) => { @@ -1848,7 +1848,7 @@ test('regular iterator error from server closes early', (t) => { t.fail('should not get here, iterator should be destroyed') yield 'zzz' } finally { - t.ok(true) + t.ok(true, 'pass') } })() client.request({ path: '/', method: 'POST', body }, (err, { statusCode, body }) => { @@ -1885,7 +1885,7 @@ test('async iterator early return closes early', (t) => { yield 'inner-value' t.fail('should not get here, iterator should be destroyed') } finally { - t.ok(true) + t.ok(true, 'pass') } })() client.request({ path: '/', method: 'POST', body }, (err, { statusCode, body }) => { @@ -1916,7 +1916,7 @@ test('async iterator yield unsupported TypedArray', (t) => { yield new Int32Array([1]) t.fail('should not get here, iterator should be destroyed') } finally { - t.ok(true) + t.ok(true, 'pass') } })() client.request({ path: '/', method: 'POST', body }, (err) => { @@ -1946,7 +1946,7 @@ test('async iterator yield object error', (t) => { yield {} t.fail('should not get here, iterator should be destroyed') } finally { - t.ok(true) + t.ok(true, 'pass') } })() client.request({ path: '/', method: 'POST', body }, (err) => { diff --git a/test/close-and-destroy.js b/test/close-and-destroy.js index 6675e1d2cd0..3a949502494 100644 --- a/test/close-and-destroy.js +++ b/test/close-and-destroy.js @@ -11,7 +11,7 @@ test('close waits for queued requests to finish', (t) => { const server = createServer() server.on('request', (req, res) => { - t.pass('request received') + t.ok(true, 'request received') res.end('hello') }) t.teardown(server.close.bind(server)) diff --git a/test/connect-errconnect.js b/test/connect-errconnect.js index 885d6ddb19c..85b11f83847 100644 --- a/test/connect-errconnect.js +++ b/test/connect-errconnect.js @@ -11,7 +11,7 @@ test('connect-connectionError', t => { t.teardown(client.close.bind(client)) client.once('connectionError', () => { - t.pass() + t.ok(true, 'pass') }) const _err = new Error('kaboom') diff --git a/test/content-length.js b/test/content-length.js index 0257e4d62a4..aa5efb84167 100644 --- a/test/content-length.js +++ b/test/content-length.js @@ -109,9 +109,9 @@ function invalidContentLength (bodyType) { t.teardown(client.destroy.bind(client)) client.once('disconnect', () => { - t.pass() + t.ok(true, 'pass') client.once('disconnect', () => { - t.pass() + t.ok(true, 'pass') }) }) @@ -217,7 +217,7 @@ test('request streaming no body data when content-length=0', (t) => { t.fail() }) .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -282,7 +282,7 @@ test('request streaming with Readable.from(buf)', (t) => { }) .on('end', () => { t.equal(Buffer.concat(chunks).toString(), 'hello') - t.pass() + t.ok(true, 'pass') t.end() }) }) @@ -330,7 +330,7 @@ test('request DELETE, content-length=0, with body', (t) => { }) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -439,7 +439,7 @@ test('content-length shouldSendContentLength=false', (t) => { }) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') }) }) }) diff --git a/test/get-head-body.js b/test/get-head-body.js index 9b587980224..74420a174cd 100644 --- a/test/get-head-body.js +++ b/test/get-head-body.js @@ -21,7 +21,7 @@ test('GET and HEAD with body should reset connection', (t) => { t.teardown(client.destroy.bind(client)) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') }) client.request({ @@ -145,7 +145,7 @@ test('HEAD should reset connection', (t) => { t.teardown(client.destroy.bind(client)) client.once('disconnect', () => { - t.pass() + t.ok(true, 'pass') }) client.request({ @@ -172,7 +172,7 @@ test('HEAD should reset connection', (t) => { t.error(err) data.body.resume() data.body.on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) t.equal(client[kBusy], true) diff --git a/test/http-100.js b/test/http-100.js index add1273d9c0..434b53a5c2f 100644 --- a/test/http-100.js +++ b/test/http-100.js @@ -55,7 +55,7 @@ test('error 103 body', (t) => { t.equal(err.code, 'HPE_INVALID_CONSTANT') }) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -79,7 +79,7 @@ test('error 100 body', (t) => { t.equal(err.message, 'bad response') }) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') }) }) }) @@ -103,7 +103,7 @@ test('error 101 upgrade', (t) => { t.equal(err.message, 'bad upgrade') }) client.on('disconnect', () => { - t.pass() + t.ok(true, 'pass') }) }) }) diff --git a/test/http2.js b/test/http2.js index 2daef09bd2c..33c2b72aa91 100644 --- a/test/http2.js +++ b/test/http2.js @@ -829,7 +829,7 @@ test('Should handle h2 request with body (string or buffer) - dispatch', t => { }, { onConnect () { - t.ok(true) + t.ok(true, 'pass') }, onError (err) { t.error(err) diff --git a/test/inflight-and-close.js b/test/inflight-and-close.js index d1930ff1bed..576a8c568ff 100644 --- a/test/inflight-and-close.js +++ b/test/inflight-and-close.js @@ -12,14 +12,14 @@ const server = http.createServer((req, res) => { const url = `http://127.0.0.1:${this.address().port}` request(url) .then(({ statusCode, headers, body }) => { - t.pass('first response') + t.ok(true, 'first response') body.resume() body.on('close', function () { - t.pass('first body closed') + t.ok(true, 'first body closed') }) return request(url) .then(({ statusCode, headers, body }) => { - t.pass('second response') + t.ok(true, 'second response') body.resume() body.on('close', function () { server.close() diff --git a/test/issue-810.js b/test/issue-810.js index ba4a35234e7..2640fd8d5c3 100644 --- a/test/issue-810.js +++ b/test/issue-810.js @@ -32,7 +32,7 @@ test('https://github.com/mcollina/undici/issues/810', (t) => { t.error(err) data.body.resume().on('end', () => { // t.fail() FIX: Should fail. - t.pass() + t.ok(true, 'pass') }).on('error', err => ( t.type(err, errors.HTTPParserError) )) @@ -66,7 +66,7 @@ test('https://github.com/mcollina/undici/issues/810 no pipelining', (t) => { t.error(err) data.body.resume().on('end', () => { // t.fail() FIX: Should fail. - t.pass() + t.ok(true, 'pass') }) }) }) @@ -93,7 +93,7 @@ test('https://github.com/mcollina/undici/issues/810 pipelining', (t) => { t.error(err) data.body.resume().on('end', () => { // t.fail() FIX: Should fail. - t.pass() + t.ok(true, 'pass') }) }) }) @@ -120,7 +120,7 @@ test('https://github.com/mcollina/undici/issues/810 pipelining 2', (t) => { t.error(err) data.body.resume().on('end', () => { // t.fail() FIX: Should fail. - t.pass() + t.ok(true, 'pass') }) }) diff --git a/test/max-headers.js b/test/max-headers.js index 9e7396ae76f..a7946e81098 100644 --- a/test/max-headers.js +++ b/test/max-headers.js @@ -34,7 +34,7 @@ test('handle a lot of headers', (t) => { data.body .resume() .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) diff --git a/test/node-test/client-dispatch.js b/test/node-test/client-dispatch.js index b89bad7278b..d780da3b7b9 100644 --- a/test/node-test/client-dispatch.js +++ b/test/node-test/client-dispatch.js @@ -387,7 +387,7 @@ test('connect call onUpgrade once', async (t) => { onConnect () { }, onHeaders (statusCode, headers) { - t.pass('should not throw') + t.ok(true, 'should not throw') }, onUpgrade (statusCode, headers, socket) { p.strictEqual(count++, 0) @@ -435,13 +435,13 @@ test('dispatch onConnect missing', async (t) => { method: 'GET' }, { onHeaders (statusCode, headers) { - t.pass('should not throw') + t.ok(true, 'should not throw') }, onData (buf) { - t.pass('should not throw') + t.ok(true, 'should not throw') }, onComplete (trailers) { - t.pass('should not throw') + t.ok(true, 'should not throw') }, onError (err) { p.strictEqual(err.code, 'UND_ERR_INVALID_ARG') diff --git a/test/parser-issues.js b/test/parser-issues.js index c94e8cf04bc..aef7c42664e 100644 --- a/test/parser-issues.js +++ b/test/parser-issues.js @@ -32,7 +32,7 @@ test('https://github.com/mcollina/undici/issues/268', (t) => { data.body .resume() setTimeout(() => { - t.pass() + t.ok(true, 'pass') data.body.on('error', () => {}) }, 2e3) }) diff --git a/test/pipeline-pipelining.js b/test/pipeline-pipelining.js index 4a94e38375f..d3f7143cba4 100644 --- a/test/pipeline-pipelining.js +++ b/test/pipeline-pipelining.js @@ -65,7 +65,7 @@ test('pipeline pipelining retry', (t) => { t.teardown(client.destroy.bind(client)) client.once('disconnect', () => { - t.pass() + t.ok(true, 'pass') }) client[kConnect](() => { @@ -101,7 +101,7 @@ test('pipeline pipelining retry', (t) => { }) client.close(() => { - t.pass() + t.ok(true, 'pass') }) }) }) diff --git a/test/pool.js b/test/pool.js index 0d586655b9f..b1c8722913e 100644 --- a/test/pool.js +++ b/test/pool.js @@ -423,10 +423,10 @@ test('busy', (t) => { pipelining: 2 }) client.on('drain', () => { - t.pass() + t.ok(true, 'pass') }) client.on('connect', () => { - t.pass() + t.ok(true, 'pass') }) t.teardown(client.destroy.bind(client)) @@ -623,7 +623,7 @@ test('300 requests succeed', (t) => { data.body.on('data', (chunk) => { t.equal(chunk.toString(), 'asd') }).on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) } @@ -716,7 +716,7 @@ test('pool dispatch error', (t) => { onData (chunk) { }, onComplete () { - t.pass() + t.ok(true, 'pass') }, onError () { } @@ -772,7 +772,7 @@ test('pool request abort in queue', (t) => { onData (chunk) { }, onComplete () { - t.pass() + t.ok(true, 'pass') }, onError () { } @@ -817,7 +817,7 @@ test('pool stream abort in queue', (t) => { onData (chunk) { }, onComplete () { - t.pass() + t.ok(true, 'pass') }, onError () { } @@ -862,7 +862,7 @@ test('pool pipeline abort in queue', (t) => { onData (chunk) { }, onComplete () { - t.pass() + t.ok(true, 'pass') }, onError () { } @@ -1014,11 +1014,11 @@ test('pool close waits for all requests', (t) => { }) client.close(() => { - t.pass() + t.ok(true, 'pass') }) client.close(() => { - t.pass() + t.ok(true, 'pass') }) client.request({ @@ -1087,7 +1087,7 @@ test('pool destroy fails queued requests', (t) => { t.equal(client.destroyed, false) client.destroy(_err, () => { - t.pass() + t.ok(true, 'pass') }) t.equal(client.destroyed, true) diff --git a/test/proxy-agent.js b/test/proxy-agent.js index 806f02a2d55..70e76756a54 100644 --- a/test/proxy-agent.js +++ b/test/proxy-agent.js @@ -46,7 +46,7 @@ test('use proxy-agent to connect through proxy', async (t) => { const parsedOrigin = new URL(serverUrl) proxy.on('connect', () => { - t.pass('should connect to proxy') + t.ok(true, 'should connect to proxy') }) server.on('request', (req, res) => { @@ -81,7 +81,7 @@ test('use proxy agent to connect through proxy using Pool', async (t) => { proxy.authenticate = async function (req, fn) { if (++connectCount === 2) { - t.pass('second connect should arrive while first is still inflight') + t.ok(true, 'second connect should arrive while first is still inflight') resolveFirstConnect() fn(null, true) } else { @@ -122,7 +122,7 @@ test('use proxy-agent to connect through proxy using path with params', async (t const parsedOrigin = new URL(serverUrl) proxy.on('connect', () => { - t.pass('should call proxy') + t.ok(true, 'should call proxy') }) server.on('request', (req, res) => { t.equal(req.url, '/hello?foo=bar') @@ -161,11 +161,11 @@ test('use proxy-agent with auth', async (t) => { const parsedOrigin = new URL(serverUrl) proxy.authenticate = function (req, fn) { - t.pass('authentication should be called') + t.ok(true, 'authentication should be called') fn(null, req.headers['proxy-authorization'] === `Basic ${Buffer.from('user:pass').toString('base64')}`) } proxy.on('connect', () => { - t.pass('proxy should be called') + t.ok(true, 'proxy should be called') }) server.on('request', (req, res) => { @@ -205,11 +205,11 @@ test('use proxy-agent with token', async (t) => { const parsedOrigin = new URL(serverUrl) proxy.authenticate = function (req, fn) { - t.pass('authentication should be called') + t.ok(true, 'authentication should be called') fn(null, req.headers['proxy-authorization'] === `Bearer ${Buffer.from('user:pass').toString('base64')}`) } proxy.on('connect', () => { - t.pass('proxy should be called') + t.ok(true, 'proxy should be called') }) server.on('request', (req, res) => { @@ -341,7 +341,7 @@ test('use proxy-agent with setGlobalDispatcher', async (t) => { t.teardown(() => setGlobalDispatcher(defaultDispatcher)) proxy.on('connect', () => { - t.pass('should call proxy') + t.ok(true, 'should call proxy') }) server.on('request', (req, res) => { t.equal(req.url, '/hello?foo=bar') @@ -432,7 +432,7 @@ test('should throw when proxy does not return 200', async (t) => { await request(serverUrl, { dispatcher: proxyAgent }) t.fail() } catch (e) { - t.pass() + t.ok(true, 'pass') t.ok(e) } @@ -492,7 +492,7 @@ test('Proxy via HTTP to HTTPS endpoint', async (t) => { }) server.on('secureConnection', () => { - t.pass('server should be connected secured') + t.ok(true, 'server should be connected secured') }) proxy.on('secureConnection', () => { @@ -500,7 +500,7 @@ test('Proxy via HTTP to HTTPS endpoint', async (t) => { }) proxy.on('connect', function () { - t.pass('proxy should be connected') + t.ok(true, 'proxy should be connected') }) proxy.on('request', function () { @@ -553,15 +553,15 @@ test('Proxy via HTTPS to HTTPS endpoint', async (t) => { }) server.on('secureConnection', () => { - t.pass('server should be connected secured') + t.ok(true, 'server should be connected secured') }) proxy.on('secureConnection', () => { - t.pass('proxy over http should call secureConnection') + t.ok(true, 'proxy over http should call secureConnection') }) proxy.on('connect', function () { - t.pass('proxy should be connected') + t.ok(true, 'proxy should be connected') }) proxy.on('request', function () { @@ -610,7 +610,7 @@ test('Proxy via HTTPS to HTTP endpoint', async (t) => { }) proxy.on('secureConnection', () => { - t.pass('proxy over http should call secureConnection') + t.ok(true, 'proxy over http should call secureConnection') }) proxy.on('request', function () { @@ -652,7 +652,7 @@ test('Proxy via HTTP to HTTP endpoint', async (t) => { }) proxy.on('connect', () => { - t.pass('connect to proxy') + t.ok(true, 'connect to proxy') }) proxy.on('request', function () { diff --git a/test/redirect-request.js b/test/redirect-request.js index da77aa78502..d200ec17aa8 100644 --- a/test/redirect-request.js +++ b/test/redirect-request.js @@ -284,7 +284,7 @@ for (const factory of [ t.equal(body.length, 0) } catch (error) { if (error.message.startsWith('max redirects')) { - t.pass('Max redirects handled correctly') + t.ok(true, 'Max redirects handled correctly') } else { t.fail(`Unexpected error: ${error.message}`) } diff --git a/test/retry-handler.js b/test/retry-handler.js index d90ff5ebc45..b4000606f62 100644 --- a/test/retry-handler.js +++ b/test/retry-handler.js @@ -60,10 +60,10 @@ tap.test('Should retry status code', t => { dispatch: client.dispatch.bind(client), handler: { onConnect () { - t.pass() + t.ok(true, 'pass') }, onBodySent () { - t.pass() + t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { t.equal(status, 200) @@ -145,10 +145,10 @@ tap.test('Should use retry-after header for retries', t => { dispatch: client.dispatch.bind(client), handler: { onConnect () { - t.pass() + t.ok(true, 'pass') }, onBodySent () { - t.pass() + t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { t.equal(status, 200) @@ -231,10 +231,10 @@ tap.test('Should use retry-after header for retries (date)', t => { dispatch: client.dispatch.bind(client), handler: { onConnect () { - t.pass() + t.ok(true, 'pass') }, onBodySent () { - t.pass() + t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { t.equal(status, 200) @@ -314,10 +314,10 @@ tap.test('Should retry with defaults', t => { dispatch: client.dispatch.bind(client), handler: { onConnect () { - t.pass() + t.ok(true, 'pass') }, onBodySent () { - t.pass() + t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { t.equal(status, 200) @@ -364,7 +364,7 @@ tap.test('Should handle 206 partial content', t => { let x = 0 const server = createServer((req, res) => { if (x === 0) { - t.pass() + t.ok(true, 'pass') res.setHeader('etag', 'asd') res.write('abc') setTimeout(() => { @@ -411,13 +411,13 @@ tap.test('Should handle 206 partial content', t => { }, handler: { onRequestSent () { - t.pass() + t.ok(true, 'pass') }, onConnect () { - t.pass() + t.ok(true, 'pass') }, onBodySent () { - t.pass() + t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { t.equal(status, 200) @@ -464,7 +464,7 @@ tap.test('Should handle 206 partial content - bad-etag', t => { let x = 0 const server = createServer((req, res) => { if (x === 0) { - t.pass() + t.ok(true, 'pass') res.setHeader('etag', 'asd') res.write('abc') setTimeout(() => { @@ -500,13 +500,13 @@ tap.test('Should handle 206 partial content - bad-etag', t => { }, handler: { onConnect () { - t.pass() + t.ok(true, 'pass') }, onBodySent () { - t.pass() + t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { - t.pass() + t.ok(true, 'pass') return true }, onData (chunk) { @@ -647,10 +647,10 @@ tap.test('should not error if request is not meant to be retried', t => { dispatch: client.dispatch.bind(client), handler: { onConnect () { - t.pass() + t.ok(true, 'pass') }, onBodySent () { - t.pass() + t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { t.equal(status, 400) diff --git a/test/socket-back-pressure.js b/test/socket-back-pressure.js index 325ac993933..bdc2c74346f 100644 --- a/test/socket-back-pressure.js +++ b/test/socket-back-pressure.js @@ -47,7 +47,7 @@ test('socket back-pressure', (t) => { }, 1e3) }) .on('end', () => { - t.pass() + t.ok(true, 'pass') }) }) }) diff --git a/test/socket-timeout.js b/test/socket-timeout.js index eb9670c6020..f2ad9faa34a 100644 --- a/test/socket-timeout.js +++ b/test/socket-timeout.js @@ -12,7 +12,7 @@ test('timeout with pipelining 1', (t) => { const server = createServer() server.once('request', (req, res) => { - t.pass('first request received, we are letting this timeout on the client') + t.ok(true, 'first request received, we are letting this timeout on the client') server.once('request', (req, res) => { t.equal('/', req.url) diff --git a/test/tls-session-reuse.js b/test/tls-session-reuse.js index ae65571bfa2..0c784456798 100644 --- a/test/tls-session-reuse.js +++ b/test/tls-session-reuse.js @@ -70,7 +70,7 @@ test('A client should disable session caching', t => { if (queue.length !== 0) { return request() } - t.pass() + t.ok(true, 'pass') }) }) } @@ -170,7 +170,7 @@ test('A pool should be able to reuse TLS sessions between clients', t => { t.equal(numSessions, 2) t.equal(serverRequests, 2 + REQ_COUNT * 2) - t.pass() + t.ok(true, 'pass') }) }) diff --git a/test/tls.js b/test/tls.js index cd4660fa319..8c2b4cc8afb 100644 --- a/test/tls.js +++ b/test/tls.js @@ -22,7 +22,7 @@ // data.body // .resume() // .on('end', () => { -// t.pass() +// t.ok(true, 'pass') // }) // }) // }) @@ -45,7 +45,7 @@ // data.body // .resume() // .on('end', () => { -// t.pass() +// t.ok(true, 'pass') // }) // }) // }) @@ -71,10 +71,10 @@ // data.body // .resume() // .on('end', () => { -// t.pass() +// t.ok(true, 'pass') // }) // client.once('disconnect', () => { -// t.pass() +// t.ok(true, 'pass') // didDisconnect = true // }) // }) @@ -133,14 +133,14 @@ // data.body // .resume() // .on('end', () => { -// t.pass() +// t.ok(true, 'pass') // }) // }) // data.body // .resume() // .on('end', () => { -// t.pass() +// t.ok(true, 'pass') // }) // }) // }) @@ -166,10 +166,10 @@ // data.body // .resume() // .on('end', () => { -// t.pass() +// t.ok(true, 'pass') // }) // client.once('disconnect', () => { -// t.pass() +// t.ok(true, 'pass') // didDisconnect = true // }) // }) From c4adfddf09a2c2118fdc1c2bf8b25298056314a8 Mon Sep 17 00:00:00 2001 From: tsctx <91457664+tsctx@users.noreply.github.com> Date: Sat, 10 Feb 2024 01:49:54 +0900 Subject: [PATCH 02/23] perf: remove redundant operation in FormData (#2726) --- lib/core/util.js | 8 +------- lib/fetch/formdata.js | 11 ++++------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/lib/core/util.js b/lib/core/util.js index 55bf9f49822..7b863067870 100644 --- a/lib/core/util.js +++ b/lib/core/util.js @@ -438,13 +438,7 @@ const hasToWellFormed = !!String.prototype.toWellFormed * @param {string} val */ function toUSVString (val) { - if (hasToWellFormed) { - return `${val}`.toWellFormed() - } else if (nodeUtil.toUSVString) { - return nodeUtil.toUSVString(val) - } - - return `${val}` + return hasToWellFormed ? `${val}`.toWellFormed() : nodeUtil.toUSVString(val) } /** diff --git a/lib/fetch/formdata.js b/lib/fetch/formdata.js index b519f890b18..add64aa9226 100644 --- a/lib/fetch/formdata.js +++ b/lib/fetch/formdata.js @@ -1,6 +1,6 @@ 'use strict' -const { isBlobLike, toUSVString, makeIterator } = require('./util') +const { isBlobLike, makeIterator } = require('./util') const { kState } = require('./symbols') const { kEnumerableProperty } = require('../core/util') const { File: UndiciFile, FileLike, isFileLike } = require('./file') @@ -133,7 +133,7 @@ class FormData { ? webidl.converters.Blob(value, { strict: false }) : webidl.converters.USVString(value) filename = arguments.length === 3 - ? toUSVString(filename) + ? webidl.converters.USVString(filename) : undefined // 2. Let entry be the result of creating an entry with name, value, and @@ -238,15 +238,12 @@ Object.defineProperties(FormData.prototype, { */ function makeEntry (name, value, filename) { // 1. Set name to the result of converting name into a scalar value string. - // "To convert a string into a scalar value string, replace any surrogates - // with U+FFFD." - // see: https://nodejs.org/dist/latest-v20.x/docs/api/buffer.html#buftostringencoding-start-end - name = Buffer.from(name).toString('utf8') + // Note: This operation was done by the webidl converter USVString. // 2. If value is a string, then set value to the result of converting // value into a scalar value string. if (typeof value === 'string') { - value = Buffer.from(value).toString('utf8') + // Note: This operation was done by the webidl converter USVString. } else { // 3. Otherwise: From c2f006894c53609032ccbf82a98e1b0221da4d66 Mon Sep 17 00:00:00 2001 From: Maksym Shenderuk Date: Fri, 9 Feb 2024 20:40:56 +0300 Subject: [PATCH 03/23] Add support for passing iterable objects as headers (#2708) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update tests with iterable object cases * Add support for iterable object headers * Update tests with cases of malformed headers * Add check for malformed headers * Update lib/core/request.js Co-authored-by: Mert Can Altın * Update lib/core/request.js Co-authored-by: Mert Can Altın * Fix code after unverified improvement broke functionality --------- Co-authored-by: Mert Can Altın --- lib/core/request.js | 17 ++++-- test/request.js | 135 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 5 deletions(-) diff --git a/lib/core/request.js b/lib/core/request.js index 74e0ca16eaa..bee7a47af92 100644 --- a/lib/core/request.js +++ b/lib/core/request.js @@ -164,10 +164,19 @@ class Request { processHeader(this, headers[i], headers[i + 1]) } } else if (headers && typeof headers === 'object') { - const keys = Object.keys(headers) - for (let i = 0; i < keys.length; i++) { - const key = keys[i] - processHeader(this, key, headers[key]) + if (headers[Symbol.iterator]) { + for (const header of headers) { + if (!Array.isArray(header) || header.length !== 2) { + throw new InvalidArgumentError('headers must be in key-value pair format') + } + const [key, value] = header + processHeader(this, key, value) + } + } else { + const keys = Object.keys(headers) + for (const key of keys) { + processHeader(this, key, headers[key]) + } } } else if (headers != null) { throw new InvalidArgumentError('headers must be an object or an array') diff --git a/test/request.js b/test/request.js index 30bf745c3f1..bbfab5b3f5c 100644 --- a/test/request.js +++ b/test/request.js @@ -2,7 +2,7 @@ const { createServer } = require('node:http') const { test } = require('tap') -const { request } = require('..') +const { request, errors } = require('..') test('no-slash/one-slash pathname should be included in req.path', async (t) => { const pathServer = createServer((req, res) => { @@ -246,3 +246,136 @@ test('DispatchOptions#reset', scope => { }) }) }) + +test('Should include headers from iterable objects', scope => { + scope.plan(4) + + scope.test('Should include headers built with Headers global object', async t => { + const server = createServer((req, res) => { + t.equal('GET', req.method) + t.equal(`localhost:${server.address().port}`, req.headers.host) + t.equal(req.headers.hello, 'world') + res.statusCode = 200 + res.end('hello') + }) + + const headers = new Headers() + headers.set('hello', 'world') + + t.plan(3) + + t.teardown(server.close.bind(server)) + + await new Promise((resolve, reject) => { + server.listen(0, (err) => { + if (err != null) reject(err) + else resolve() + }) + }) + + await request({ + method: 'GET', + origin: `http://localhost:${server.address().port}`, + reset: true, + headers + }) + }) + + scope.test('Should include headers built with Map', async t => { + const server = createServer((req, res) => { + t.equal('GET', req.method) + t.equal(`localhost:${server.address().port}`, req.headers.host) + t.equal(req.headers.hello, 'world') + res.statusCode = 200 + res.end('hello') + }) + + const headers = new Map() + headers.set('hello', 'world') + + t.plan(3) + + t.teardown(server.close.bind(server)) + + await new Promise((resolve, reject) => { + server.listen(0, (err) => { + if (err != null) reject(err) + else resolve() + }) + }) + + await request({ + method: 'GET', + origin: `http://localhost:${server.address().port}`, + reset: true, + headers + }) + }) + + scope.test('Should include headers built with custom iterable object', async t => { + const server = createServer((req, res) => { + t.equal('GET', req.method) + t.equal(`localhost:${server.address().port}`, req.headers.host) + t.equal(req.headers.hello, 'world') + res.statusCode = 200 + res.end('hello') + }) + + const headers = { + * [Symbol.iterator] () { + yield ['hello', 'world'] + } + } + + t.plan(3) + + t.teardown(server.close.bind(server)) + + await new Promise((resolve, reject) => { + server.listen(0, (err) => { + if (err != null) reject(err) + else resolve() + }) + }) + + await request({ + method: 'GET', + origin: `http://localhost:${server.address().port}`, + reset: true, + headers + }) + }) + + scope.test('Should throw error if headers iterable object does not yield key-value pairs', async t => { + const server = createServer((req, res) => { + res.end('hello') + }) + + const headers = { + * [Symbol.iterator] () { + yield 'Bad formatted header' + } + } + + t.plan(2) + + t.teardown(server.close.bind(server)) + + await new Promise((resolve, reject) => { + server.listen(0, (err) => { + if (err != null) reject(err) + else resolve() + }) + }) + + await request({ + method: 'GET', + origin: `http://localhost:${server.address().port}`, + reset: true, + headers + }).catch((err) => { + t.type(err, errors.InvalidArgumentError) + t.equal(err.message, 'headers must be in key-value pair format') + }) + }) +}) From 08607353423e04b94da135398a1cc485c550a906 Mon Sep 17 00:00:00 2001 From: Zephyr Lykos Date: Sat, 10 Feb 2024 01:41:56 +0800 Subject: [PATCH 04/23] chore: refine esbuild & node detection (#2677) When using the loader for external builtins, `esbuildDetection` is undefined. This commit defines `__UNDICI_IS_NODE__` on `globalThis` in the loader and deletes it after loading Undici. `esbuildDetection` has also been extracted as a variable at the top level of the module, to support deleting `__UNDICI_IS_NODE__` on `globalThis` to avoid polluting the global namespace. --- build/wasm.js | 2 ++ lib/fetch/index.js | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/build/wasm.js b/build/wasm.js index 3fb8f103117..ca89ec7d4cf 100644 --- a/build/wasm.js +++ b/build/wasm.js @@ -101,6 +101,8 @@ if (EXTERNAL_PATH) { writeFileSync(join(ROOT, 'loader.js'), ` 'use strict' +globalThis.__UNDICI_IS_NODE__ = true module.exports = require('node:module').createRequire('${EXTERNAL_PATH}/loader.js')('./index-fetch.js') +delete globalThis.__UNDICI_IS_NODE__ `) } diff --git a/lib/fetch/index.js b/lib/fetch/index.js index 4b89b4a48e3..a11f0a8d506 100644 --- a/lib/fetch/index.js +++ b/lib/fetch/index.js @@ -66,6 +66,10 @@ const { webidl } = require('./webidl') const { STATUS_CODES } = require('node:http') const GET_OR_HEAD = ['GET', 'HEAD'] +const defaultUserAgent = typeof __UNDICI_IS_NODE__ !== 'undefined' || typeof esbuildDetection !== 'undefined' + ? 'node' + : 'undici' + /** @type {import('buffer').resolveObjectURL} */ let resolveObjectURL @@ -1478,7 +1482,7 @@ async function httpNetworkOrCacheFetch ( // user agents should append `User-Agent`/default `User-Agent` value to // httpRequest’s header list. if (!httpRequest.headersList.contains('user-agent', true)) { - httpRequest.headersList.append('user-agent', typeof esbuildDetection === 'undefined' ? 'undici' : 'node', true) + httpRequest.headersList.append('user-agent', defaultUserAgent) } // 15. If httpRequest’s cache mode is "default" and httpRequest’s header From cebfdcddf46ce190a5be003366845adc7009adcb Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Fri, 9 Feb 2024 18:45:50 +0100 Subject: [PATCH 05/23] rephrase some comments (#2717) --- lib/fetch/index.js | 2 +- lib/fetch/util.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fetch/index.js b/lib/fetch/index.js index a11f0a8d506..a989295bc4b 100644 --- a/lib/fetch/index.js +++ b/lib/fetch/index.js @@ -369,7 +369,7 @@ function fetching ({ useParallelQueue = false, dispatcher // undici }) { - // This has bitten me in the ass more times than I'd like to admit. + // Ensure that the dispatcher is set accordingly assert(dispatcher) // 1. Let taskDestination be null. diff --git a/lib/fetch/util.js b/lib/fetch/util.js index 8812895bf4d..c5a6b46b170 100644 --- a/lib/fetch/util.js +++ b/lib/fetch/util.js @@ -1072,7 +1072,7 @@ function simpleRangeHeaderValue (value, allowWhitespace) { // 13. If allowWhitespace is true, collect a sequence of code points that are HTTP tab // or space, from data given position. - // Note from Khafra: its the same fucking step again lol + // Note from Khafra: its the same step as in #8 again lol if (allowWhitespace) { collectASequenceOfCodePoints( (char) => char === '\t' || char === ' ', From 50d691d366729433ae4f59b2950e755f31c3661e Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Fri, 9 Feb 2024 23:39:19 +0100 Subject: [PATCH 06/23] test: replace t.type with t.ok (#2720) --- test/client-connect.js | 2 +- test/client-pipeline.js | 26 ++++++------- test/client-request.js | 4 +- test/client-stream.js | 20 +++++----- test/client-timeout.js | 6 +-- test/client-upgrade.js | 16 ++++---- test/client.js | 6 +-- test/close-and-destroy.js | 16 ++++---- test/connect-timeout.js | 4 +- test/content-length.js | 22 +++++------ test/headers-as-array.js | 2 +- test/http2.js | 2 +- test/invalid-headers.js | 20 +++++----- test/issue-810.js | 6 +-- test/max-response-size.js | 2 +- test/mock-agent.js | 14 +++---- test/mock-client.js | 16 ++++---- test/mock-errors.js | 4 +- test/mock-interceptor.js | 14 +++---- test/mock-pool.js | 8 ++-- test/mock-scope.js | 6 +-- test/parser-issues.js | 2 +- test/pool.js | 24 ++++++------ test/request-crlf.js | 2 +- test/request-timeout.js | 50 ++++++++++++------------- test/socket-timeout.js | 2 +- test/utils/esm-wrapper.mjs | 6 +-- test/wpt/tests/resources/testharness.js | 2 +- 28 files changed, 152 insertions(+), 152 deletions(-) diff --git a/test/client-connect.js b/test/client-connect.js index 587361f9ef0..4917a526d0e 100644 --- a/test/client-connect.js +++ b/test/client-connect.js @@ -31,7 +31,7 @@ test('connect aborted after connect', (t) => { opaque: 'asd' }, (err, { opaque }) => { t.equal(opaque, 'asd') - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) }) t.equal(client[kBusy], true) }) diff --git a/test/client-pipeline.js b/test/client-pipeline.js index e37657456ff..cbc78b9270d 100644 --- a/test/client-pipeline.js +++ b/test/client-pipeline.js @@ -340,7 +340,7 @@ test('pipeline invalid handler return', (t) => { body.on('error', () => {}) }) .on('error', (err) => { - t.type(err, errors.InvalidReturnValueError) + t.ok(err instanceof errors.InvalidReturnValueError) }) .end() @@ -353,7 +353,7 @@ test('pipeline invalid handler return', (t) => { return {} }) .on('error', (err) => { - t.type(err, errors.InvalidReturnValueError) + t.ok(err instanceof errors.InvalidReturnValueError) }) .end() }) @@ -409,7 +409,7 @@ test('pipeline destroy and throw handler', (t) => { }) .end() .on('error', (err) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) }) .on('close', () => { t.ok(true, 'pass') @@ -449,7 +449,7 @@ test('pipeline abort res', (t) => { return body }) .on('error', (err) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) }) .end() }) @@ -474,7 +474,7 @@ test('pipeline abort server res', (t) => { t.fail() }) .on('error', (err) => { - t.type(err, errors.SocketError) + t.ok(err instanceof errors.SocketError) }) .end() }) @@ -505,7 +505,7 @@ test('pipeline abort duplex', (t) => { }, () => { t.fail() }).destroy().on('error', (err) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) }) }) }) @@ -558,7 +558,7 @@ test('pipeline abort piped res 2', (t) => { }, ({ body }) => { const pt = new PassThrough() body.on('error', (err) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) }) setImmediate(() => { pt.destroy() @@ -567,7 +567,7 @@ test('pipeline abort piped res 2', (t) => { return pt }) .on('error', (err) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) }) .end() }) @@ -628,7 +628,7 @@ test('pipeline abort server res after headers', (t) => { return data.body }) .on('error', (err) => { - t.type(err, errors.SocketError) + t.ok(err instanceof errors.SocketError) }) .end() }) @@ -656,7 +656,7 @@ test('pipeline w/ write abort server res after headers', (t) => { return data.body }) .on('error', (err) => { - t.type(err, errors.SocketError) + t.ok(err instanceof errors.SocketError) }) .resume() .write('asd') @@ -713,7 +713,7 @@ test('pipeline args validation', (t) => { const ret = client.pipeline(null, () => {}) ret.on('error', (err) => { t.ok(/opts/.test(err.message)) - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) }) @@ -866,7 +866,7 @@ test('pipeline CONNECT throw', (t) => { }, () => { t.fail() }).on('error', (err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) client.on('disconnect', () => { t.fail() @@ -1030,7 +1030,7 @@ test('pipeline abort after headers', (t) => { }) .end() .on('error', (err) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) }) }) }) diff --git a/test/client-request.js b/test/client-request.js index aa9405b2fcc..cafcd39989b 100644 --- a/test/client-request.js +++ b/test/client-request.js @@ -117,7 +117,7 @@ test('request abort before headers', (t) => { method: 'GET', signal }, (err) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) t.equal(signal.listenerCount('abort'), 0) }) t.equal(signal.listenerCount('abort'), 1) @@ -127,7 +127,7 @@ test('request abort before headers', (t) => { method: 'GET', signal }, (err) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) t.equal(signal.listenerCount('abort'), 0) }) t.equal(signal.listenerCount('abort'), 2) diff --git a/test/client-stream.js b/test/client-stream.js index a77804ace51..69843acf0df 100644 --- a/test/client-stream.js +++ b/test/client-stream.js @@ -263,17 +263,17 @@ test('stream args validation', (t) => { path: '/', method: 'GET' }, null, (err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) client.stream(null, null, (err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) try { client.stream(null, null, 'asd') } catch (err) { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) } }) @@ -285,11 +285,11 @@ test('stream args validation promise', (t) => { path: '/', method: 'GET' }, null).catch((err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) client.stream(null, null).catch((err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) }) @@ -337,7 +337,7 @@ test('stream server side destroy', (t) => { }, () => { t.fail() }, (err) => { - t.type(err, errors.SocketError) + t.ok(err instanceof errors.SocketError) }) }) }) @@ -360,7 +360,7 @@ test('stream invalid return', (t) => { }, () => { return {} }, (err) => { - t.type(err, errors.InvalidReturnValueError) + t.ok(err instanceof errors.InvalidReturnValueError) }) }) }) @@ -413,7 +413,7 @@ test('stream factory abort', (t) => { return new PassThrough() }, (err) => { t.equal(signal.listenerCount('abort'), 0) - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) }) t.equal(signal.listenerCount('abort'), 1) }) @@ -475,7 +475,7 @@ test('stream CONNECT throw', (t) => { method: 'CONNECT' }, () => { }, (err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) }) }) @@ -528,7 +528,7 @@ test('stream abort before dispatch', (t) => { }, () => { return pt }, (err) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) }) signal.emit('abort') }) diff --git a/test/client-timeout.js b/test/client-timeout.js index 38895c600c6..dd5b1da6505 100644 --- a/test/client-timeout.js +++ b/test/client-timeout.js @@ -40,7 +40,7 @@ test('refresh timeout on pause', (t) => { }, onError (err) { - t.type(err, errors.BodyTimeoutError) + t.ok(err instanceof errors.BodyTimeoutError) } }) }) @@ -96,7 +96,7 @@ test('start headers timeout after request body', (t) => { }, onError (err) { t.equal(body.readableEnded, true) - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) } }) }) @@ -153,7 +153,7 @@ test('start headers timeout after async iterator request body', (t) => { }, onError (err) { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) } }) }) diff --git a/test/client-upgrade.js b/test/client-upgrade.js index 84b84424e97..c33ab183363 100644 --- a/test/client-upgrade.js +++ b/test/client-upgrade.js @@ -151,7 +151,7 @@ test('upgrade invalid opts', (t) => { const client = new Client('http://localhost:5432') client.upgrade(null, err => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) t.equal(err.message, 'invalid opts') }) @@ -159,7 +159,7 @@ test('upgrade invalid opts', (t) => { client.upgrade(null, null) t.fail() } catch (err) { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) t.equal(err.message, 'invalid opts') } @@ -167,7 +167,7 @@ test('upgrade invalid opts', (t) => { client.upgrade({ path: '/' }, null) t.fail() } catch (err) { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) t.equal(err.message, 'invalid callback') } }) @@ -308,7 +308,7 @@ test('upgrade aborted', (t) => { opaque: 'asd' }, (err, { opaque }) => { t.equal(opaque, 'asd') - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) t.equal(signal.listenerCount('abort'), 0) }) t.equal(client[kBusy], true) @@ -351,7 +351,7 @@ test('basic aborted after res', (t) => { protocol: 'Websocket', signal }, (err) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) }) }) }) @@ -408,7 +408,7 @@ test('upgrade disconnect', (t) => { client.on('disconnect', (origin, [self], error) => { t.equal(client, self) - t.type(error, Error) + t.ok(error instanceof Error) }) client @@ -417,7 +417,7 @@ test('upgrade disconnect', (t) => { t.fail() }) .catch(error => { - t.type(error, Error) + t.ok(error instanceof Error) }) }) }) @@ -446,7 +446,7 @@ test('upgrade invalid signal', (t) => { opaque: 'asd' }, (err, { opaque }) => { t.equal(opaque, 'asd') - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) }) }) diff --git a/test/client.js b/test/client.js index 7f23ecd034d..7c3c8d0fcb3 100644 --- a/test/client.js +++ b/test/client.js @@ -1412,13 +1412,13 @@ test('request args validation', (t) => { const client = new Client('http://localhost:5000') client.request(null, (err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) try { client.request(null, 'asd') } catch (err) { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) } }) @@ -1428,7 +1428,7 @@ test('request args validation promise', (t) => { const client = new Client('http://localhost:5000') client.request(null).catch((err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) }) diff --git a/test/close-and-destroy.js b/test/close-and-destroy.js index 3a949502494..b946e3e18b6 100644 --- a/test/close-and-destroy.js +++ b/test/close-and-destroy.js @@ -72,10 +72,10 @@ test('destroy invoked all pending callbacks', (t) => { client.destroy() }) client.request({ path: '/', method: 'GET' }, (err) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) client.request({ path: '/', method: 'GET' }, (err) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) }) }) @@ -99,11 +99,11 @@ test('destroy invoked all pending callbacks ticked', (t) => { let ticked = false client.request({ path: '/', method: 'GET' }, (err) => { t.equal(ticked, true) - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) client.request({ path: '/', method: 'GET' }, (err) => { t.equal(ticked, true) - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) client.destroy() ticked = true @@ -223,10 +223,10 @@ test('closed and destroyed errors', (t) => { t.error(err) }) client.request({ path: '/', method: 'GET' }, (err) => { - t.type(err, errors.ClientClosedError) + t.ok(err instanceof errors.ClientClosedError) client.destroy() client.request({ path: '/', method: 'GET' }, (err) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) }) }) @@ -239,10 +239,10 @@ test('close after and destroy should error', (t) => { client.destroy() client.close((err) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) client.close().catch((err) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) }) diff --git a/test/connect-timeout.js b/test/connect-timeout.js index 9c001a35d97..5eab8ee1098 100644 --- a/test/connect-timeout.js +++ b/test/connect-timeout.js @@ -41,7 +41,7 @@ test('connect-timeout', t => { path: '/', method: 'GET' }, (err) => { - t.type(err, errors.ConnectTimeoutError) + t.ok(err instanceof errors.ConnectTimeoutError) clearTimeout(timeout) }) }) @@ -62,7 +62,7 @@ test('connect-timeout', t => { path: '/', method: 'GET' }, (err) => { - t.type(err, errors.ConnectTimeoutError) + t.ok(err instanceof errors.ConnectTimeoutError) clearTimeout(timeout) }) }) diff --git a/test/content-length.js b/test/content-length.js index aa5efb84167..6c124ed3530 100644 --- a/test/content-length.js +++ b/test/content-length.js @@ -25,7 +25,7 @@ test('request invalid content-length', (t) => { }, body: 'asd' }, (err, data) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) client.request({ @@ -36,7 +36,7 @@ test('request invalid content-length', (t) => { }, body: 'asdasdasdasdasdasda' }, (err, data) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) client.request({ @@ -47,7 +47,7 @@ test('request invalid content-length', (t) => { }, body: Buffer.alloc(9) }, (err, data) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) client.request({ @@ -58,7 +58,7 @@ test('request invalid content-length', (t) => { }, body: Buffer.alloc(11) }, (err, data) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) client.request({ @@ -69,7 +69,7 @@ test('request invalid content-length', (t) => { }, body: ['asd'] }, (err, data) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) client.request({ @@ -80,7 +80,7 @@ test('request invalid content-length', (t) => { }, body: ['asasdasdasdd'] }, (err, data) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) client.request({ @@ -91,7 +91,7 @@ test('request invalid content-length', (t) => { }, body: ['asasdasdasdd'] }, (err, data) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) }) }) @@ -130,7 +130,7 @@ function invalidContentLength (bodyType) { } }), bodyType) }, (err, data) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) client.request({ @@ -148,7 +148,7 @@ function invalidContentLength (bodyType) { } }), bodyType) }, (err, data) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) }) }) @@ -184,7 +184,7 @@ function zeroContentLength (bodyType) { } }), bodyType) }, (err, data) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) }) }) @@ -315,7 +315,7 @@ test('request DELETE, content-length=0, with body', (t) => { } }) }, (err) => { - t.type(err, errors.RequestContentLengthMismatchError) + t.ok(err instanceof errors.RequestContentLengthMismatchError) }) client.request({ diff --git a/test/headers-as-array.js b/test/headers-as-array.js index 315d55b4b64..e50605332e5 100644 --- a/test/headers-as-array.js +++ b/test/headers-as-array.js @@ -103,7 +103,7 @@ test('fail if headers array is odd', (t) => { method: 'GET', headers }, (err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) t.equal(err.message, 'headers array must be even') }) }) diff --git a/test/http2.js b/test/http2.js index 33c2b72aa91..538c6677788 100644 --- a/test/http2.js +++ b/test/http2.js @@ -273,7 +273,7 @@ test('Should support H2 GOAWAY (server-side)', async t => { const [url, disconnectClient, err] = await once(client, 'disconnect') - t.type(url, URL) + t.ok(url instanceof URL) t.same(disconnectClient, [client]) t.equal(err.message, 'HTTP/2: "GOAWAY" frame received with code 204') }) diff --git a/test/invalid-headers.js b/test/invalid-headers.js index caf9e0ae66a..0c011e97ac1 100644 --- a/test/invalid-headers.js +++ b/test/invalid-headers.js @@ -15,7 +15,7 @@ test('invalid headers', (t) => { 'content-length': 'asd' } }, (err, data) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) client.request({ @@ -23,7 +23,7 @@ test('invalid headers', (t) => { method: 'GET', headers: 1 }, (err, data) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) client.request({ @@ -33,7 +33,7 @@ test('invalid headers', (t) => { 'transfer-encoding': 'chunked' } }, (err, data) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) client.request({ @@ -43,7 +43,7 @@ test('invalid headers', (t) => { upgrade: 'asd' } }, (err, data) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) client.request({ @@ -53,7 +53,7 @@ test('invalid headers', (t) => { connection: 'asd' } }, (err, data) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) client.request({ @@ -63,7 +63,7 @@ test('invalid headers', (t) => { 'keep-alive': 'timeout=5' } }, (err, data) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) client.request({ @@ -73,7 +73,7 @@ test('invalid headers', (t) => { foo: {} } }, (err, data) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) client.request({ @@ -83,7 +83,7 @@ test('invalid headers', (t) => { expect: '100-continue' } }, (err, data) => { - t.type(err, errors.NotSupportedError) + t.ok(err instanceof errors.NotSupportedError) }) client.request({ @@ -93,7 +93,7 @@ test('invalid headers', (t) => { Expect: '100-continue' } }, (err, data) => { - t.type(err, errors.NotSupportedError) + t.ok(err instanceof errors.NotSupportedError) }) client.request({ @@ -103,6 +103,6 @@ test('invalid headers', (t) => { expect: 'asd' } }, (err, data) => { - t.type(err, errors.NotSupportedError) + t.ok(err instanceof errors.NotSupportedError) }) }) diff --git a/test/issue-810.js b/test/issue-810.js index 2640fd8d5c3..e18656c5869 100644 --- a/test/issue-810.js +++ b/test/issue-810.js @@ -34,14 +34,14 @@ test('https://github.com/mcollina/undici/issues/810', (t) => { // t.fail() FIX: Should fail. t.ok(true, 'pass') }).on('error', err => ( - t.type(err, errors.HTTPParserError) + t.ok(err instanceof errors.HTTPParserError) )) }) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.type(err, errors.HTTPParserError) + t.ok(err instanceof errors.HTTPParserError) }) }) }) @@ -129,7 +129,7 @@ test('https://github.com/mcollina/undici/issues/810 pipelining 2', (t) => { method: 'GET' }, (err, data) => { t.equal(err.code, 'HPE_INVALID_CONSTANT') - t.type(err, errors.HTTPParserError) + t.ok(err instanceof errors.HTTPParserError) }) }) }) diff --git a/test/max-response-size.js b/test/max-response-size.js index ca6ad40fa42..adf75c6fee2 100644 --- a/test/max-response-size.js +++ b/test/max-response-size.js @@ -84,7 +84,7 @@ test('max response size', (t) => { t.error(err) body.on('error', (err) => { t.ok(err) - t.type(err, errors.ResponseExceededMaxSizeError) + t.ok(err instanceof errors.ResponseExceededMaxSizeError) }) }) }) diff --git a/test/mock-agent.js b/test/mock-agent.js index 42dfb9554cc..ed58464b527 100644 --- a/test/mock-agent.js +++ b/test/mock-agent.js @@ -26,7 +26,7 @@ test('MockAgent - constructor', t => { t.plan(1) const mockAgent = new MockAgent() - t.type(mockAgent, Dispatcher) + t.ok(mockAgent instanceof Dispatcher) }) t.test('sets up mock agent with single connection', t => { @@ -62,7 +62,7 @@ test('MockAgent - get', t => { t.teardown(mockAgent.close.bind(mockAgent)) const mockClient = mockAgent.get(baseUrl) - t.type(mockClient, MockClient) + t.ok(mockClient instanceof MockClient) }) t.test('should return MockPool', (t) => { @@ -74,7 +74,7 @@ test('MockAgent - get', t => { t.teardown(mockAgent.close.bind(mockAgent)) const mockPool = mockAgent.get(baseUrl) - t.type(mockPool, MockPool) + t.ok(mockPool instanceof MockPool) }) t.test('should return the same instance if already created', (t) => { @@ -241,7 +241,7 @@ test('MockAgent - .close should clean up registered pools', async (t) => { // Register a pool const mockPool = mockAgent.get(baseUrl) - t.type(mockPool, MockPool) + t.ok(mockPool instanceof MockPool) t.equal(mockPool[kConnected], 1) t.equal(mockAgent[kClients].size, 1) @@ -259,7 +259,7 @@ test('MockAgent - .close should clean up registered clients', async (t) => { // Register a pool const mockClient = mockAgent.get(baseUrl) - t.type(mockClient, MockClient) + t.ok(mockClient instanceof MockClient) t.equal(mockClient[kConnected], 1) t.equal(mockAgent[kClients].size, 1) @@ -996,7 +996,7 @@ test('MockAgent - close removes all registered mock clients', async (t) => { try { await request(`${baseUrl}/foo`, { method: 'GET' }) } catch (err) { - t.type(err, ClientDestroyedError) + t.ok(err instanceof ClientDestroyedError) } }) @@ -1030,7 +1030,7 @@ test('MockAgent - close removes all registered mock pools', async (t) => { try { await request(`${baseUrl}/foo`, { method: 'GET' }) } catch (err) { - t.type(err, ClientDestroyedError) + t.ok(err instanceof ClientDestroyedError) } }) diff --git a/test/mock-client.js b/test/mock-client.js index 7845135b139..9622977cf1e 100644 --- a/test/mock-client.js +++ b/test/mock-client.js @@ -28,7 +28,7 @@ test('MockClient - constructor', t => { t.plan(1) const mockClient = new MockClient('http://localhost:9999', { agent: new MockAgent({ connections: 1 }) }) - t.type(mockClient, Dispatcher) + t.ok(mockClient instanceof Dispatcher) }) }) @@ -121,7 +121,7 @@ test('MockClient - intercept should return a MockInterceptor', (t) => { method: 'GET' }) - t.type(interceptor, MockInterceptor) + t.ok(interceptor instanceof MockInterceptor) }) test('MockClient - intercept validation', (t) => { @@ -218,7 +218,7 @@ test('MockClient - should be able to set as globalDispatcher', async (t) => { t.teardown(mockAgent.close.bind(mockAgent)) const mockClient = mockAgent.get(baseUrl) - t.type(mockClient, MockClient) + t.ok(mockClient instanceof MockClient) setGlobalDispatcher(mockClient) mockClient.intercept({ @@ -254,7 +254,7 @@ test('MockClient - should support query params', async (t) => { t.teardown(mockAgent.close.bind(mockAgent)) const mockClient = mockAgent.get(baseUrl) - t.type(mockClient, MockClient) + t.ok(mockClient instanceof MockClient) setGlobalDispatcher(mockClient) const query = { @@ -295,7 +295,7 @@ test('MockClient - should intercept query params with hardcoded path', async (t) t.teardown(mockAgent.close.bind(mockAgent)) const mockClient = mockAgent.get(baseUrl) - t.type(mockClient, MockClient) + t.ok(mockClient instanceof MockClient) setGlobalDispatcher(mockClient) const query = { @@ -335,7 +335,7 @@ test('MockClient - should intercept query params regardless of key ordering', as t.teardown(mockAgent.close.bind(mockAgent)) const mockClient = mockAgent.get(baseUrl) - t.type(mockClient, MockClient) + t.ok(mockClient instanceof MockClient) setGlobalDispatcher(mockClient) const query = { @@ -383,7 +383,7 @@ test('MockClient - should be able to use as a local dispatcher', async (t) => { t.teardown(mockAgent.close.bind(mockAgent)) const mockClient = mockAgent.get(baseUrl) - t.type(mockClient, MockClient) + t.ok(mockClient instanceof MockClient) mockClient.intercept({ path: '/foo', @@ -418,7 +418,7 @@ test('MockClient - basic intercept with MockClient.request', async (t) => { const mockAgent = new MockAgent({ connections: 1 }) t.teardown(mockAgent.close.bind(mockAgent)) const mockClient = mockAgent.get(baseUrl) - t.type(mockClient, MockClient) + t.ok(mockClient instanceof MockClient) mockClient.intercept({ path: '/foo?hello=there&see=ya', diff --git a/test/mock-errors.js b/test/mock-errors.js index a96de0bac84..1087f0cf588 100644 --- a/test/mock-errors.js +++ b/test/mock-errors.js @@ -13,7 +13,7 @@ test('mockErrors', (t) => { t.plan(4) const mockError = new mockErrors.MockNotMatchedError() - t.type(mockError, errors.UndiciError) + t.ok(mockError instanceof errors.UndiciError) t.same(mockError.name, 'MockNotMatchedError') t.same(mockError.code, 'UND_MOCK_ERR_MOCK_NOT_MATCHED') t.same(mockError.message, 'The request does not match any registered mock dispatches') @@ -23,7 +23,7 @@ test('mockErrors', (t) => { t.plan(4) const mockError = new mockErrors.MockNotMatchedError('custom message') - t.type(mockError, errors.UndiciError) + t.ok(mockError instanceof errors.UndiciError) t.same(mockError.name, 'MockNotMatchedError') t.same(mockError.code, 'UND_MOCK_ERR_MOCK_NOT_MATCHED') t.same(mockError.message, 'custom message') diff --git a/test/mock-interceptor.js b/test/mock-interceptor.js index a11377d3af0..787878395f4 100644 --- a/test/mock-interceptor.js +++ b/test/mock-interceptor.js @@ -28,7 +28,7 @@ test('MockInterceptor - reply', t => { method: '' }, []) const result = mockInterceptor.reply(200, 'hello') - t.type(result, MockScope) + t.ok(result instanceof MockScope) }) t.test('should error if passed options invalid', t => { @@ -53,7 +53,7 @@ test('MockInterceptor - reply callback', t => { method: '' }, []) const result = mockInterceptor.reply(200, () => 'hello') - t.type(result, MockScope) + t.ok(result instanceof MockScope) }) t.test('should error if passed options invalid', t => { @@ -82,7 +82,7 @@ test('MockInterceptor - reply options callback', t => { statusCode: 200, data: 'hello' })) - t.type(result, MockScope) + t.ok(result instanceof MockScope) // Test parameters @@ -181,7 +181,7 @@ test('MockInterceptor - replyWithError', t => { method: '' }, []) const result = mockInterceptor.replyWithError(new Error('kaboom')) - t.type(result, MockScope) + t.ok(result instanceof MockScope) }) t.test('should error if passed options invalid', t => { @@ -205,7 +205,7 @@ test('MockInterceptor - defaultReplyHeaders', t => { method: '' }, []) const result = mockInterceptor.defaultReplyHeaders({}) - t.type(result, MockInterceptor) + t.ok(result instanceof MockInterceptor) }) t.test('should error if passed options invalid', t => { @@ -229,7 +229,7 @@ test('MockInterceptor - defaultReplyTrailers', t => { method: '' }, []) const result = mockInterceptor.defaultReplyTrailers({}) - t.type(result, MockInterceptor) + t.ok(result instanceof MockInterceptor) }) t.test('should error if passed options invalid', t => { @@ -253,6 +253,6 @@ test('MockInterceptor - replyContentLength', t => { method: '' }, []) const result = mockInterceptor.defaultReplyTrailers({}) - t.type(result, MockInterceptor) + t.ok(result instanceof MockInterceptor) }) }) diff --git a/test/mock-pool.js b/test/mock-pool.js index fa79796471e..ca812d90866 100644 --- a/test/mock-pool.js +++ b/test/mock-pool.js @@ -29,7 +29,7 @@ test('MockPool - constructor', t => { t.plan(1) const mockPool = new MockPool('http://localhost:9999', { agent: new MockAgent() }) - t.type(mockPool, Dispatcher) + t.ok(mockPool instanceof Dispatcher) }) }) @@ -204,7 +204,7 @@ test('MockPool - should be able to set as globalDispatcher', async (t) => { t.teardown(mockAgent.close.bind(mockAgent)) const mockPool = mockAgent.get(baseUrl) - t.type(mockPool, MockPool) + t.ok(mockPool instanceof MockPool) setGlobalDispatcher(mockPool) mockPool.intercept({ @@ -240,7 +240,7 @@ test('MockPool - should be able to use as a local dispatcher', async (t) => { t.teardown(mockAgent.close.bind(mockAgent)) const mockPool = mockAgent.get(baseUrl) - t.type(mockPool, MockPool) + t.ok(mockPool instanceof MockPool) mockPool.intercept({ path: '/foo', @@ -275,7 +275,7 @@ test('MockPool - basic intercept with MockPool.request', async (t) => { const mockAgent = new MockAgent() t.teardown(mockAgent.close.bind(mockAgent)) const mockPool = mockAgent.get(baseUrl) - t.type(mockPool, MockPool) + t.ok(mockPool instanceof MockPool) mockPool.intercept({ path: '/foo?hello=there&see=ya', diff --git a/test/mock-scope.js b/test/mock-scope.js index 605ba582171..d8f41d90198 100644 --- a/test/mock-scope.js +++ b/test/mock-scope.js @@ -14,7 +14,7 @@ test('MockScope - delay', t => { method: '' }, []) const result = mockScope.delay(200) - t.type(result, MockScope) + t.ok(result instanceof MockScope) }) t.test('should error if passed options invalid', t => { @@ -41,7 +41,7 @@ test('MockScope - persist', t => { method: '' }, []) const result = mockScope.persist() - t.type(result, MockScope) + t.ok(result instanceof MockScope) }) }) @@ -55,7 +55,7 @@ test('MockScope - times', t => { method: '' }, []) const result = mockScope.times(200) - t.type(result, MockScope) + t.ok(result instanceof MockScope) }) t.test('should error if passed options invalid', t => { diff --git a/test/parser-issues.js b/test/parser-issues.js index aef7c42664e..3602ae1ba5e 100644 --- a/test/parser-issues.js +++ b/test/parser-issues.js @@ -56,7 +56,7 @@ test('parser fail', (t) => { path: '/' }, (err, data) => { t.ok(err) - t.type(err, errors.HTTPParserError) + t.ok(err instanceof errors.HTTPParserError) }) }) }) diff --git a/test/pool.js b/test/pool.js index b1c8722913e..af6a019c7a0 100644 --- a/test/pool.js +++ b/test/pool.js @@ -30,7 +30,7 @@ test('throws when connection is infinite', (t) => { try { new Pool(null, { connections: 0 / 0 }) // eslint-disable-line } catch (e) { - t.type(e, errors.InvalidArgumentError) + t.ok(e instanceof errors.InvalidArgumentError) t.equal(e.message, 'invalid connections') } }) @@ -41,7 +41,7 @@ test('throws when connections is negative', (t) => { try { new Pool(null, { connections: -1 }) // eslint-disable-line no-new } catch (e) { - t.type(e, errors.InvalidArgumentError) + t.ok(e instanceof errors.InvalidArgumentError) t.equal(e.message, 'invalid connections') } }) @@ -52,7 +52,7 @@ test('throws when connection is not number', (t) => { try { new Pool(null, { connections: true }) // eslint-disable-line no-new } catch (e) { - t.type(e, errors.InvalidArgumentError) + t.ok(e instanceof errors.InvalidArgumentError) t.equal(e.message, 'invalid connections') } }) @@ -63,7 +63,7 @@ test('throws when factory is not a function', (t) => { try { new Pool(null, { factory: '' }) // eslint-disable-line no-new } catch (e) { - t.type(e, errors.InvalidArgumentError) + t.ok(e instanceof errors.InvalidArgumentError) t.equal(e.message, 'factory must be a function.') } }) @@ -100,7 +100,7 @@ test('connect/disconnect event(s)', (t) => { }) pool.on('disconnect', (origin, [pool, client], error) => { t.ok(client instanceof Client) - t.type(error, errors.InformationalError) + t.ok(error instanceof errors.InformationalError) t.equal(error.code, 'UND_ERR_INFO') t.equal(error.message, 'socket idle timeout') }) @@ -155,7 +155,7 @@ test('basic get', (t) => { client.destroy((err) => { t.error(err) client.close((err) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) }) }) @@ -198,7 +198,7 @@ test('URL as arg', (t) => { client.destroy((err) => { t.error(err) client.close((err) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) }) }) @@ -225,7 +225,7 @@ test('basic get error async/await', (t) => { await client.destroy() await client.close().catch((err) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) }) }) @@ -596,7 +596,7 @@ test('pool pipeline args validation', (t) => { const ret = client.pipeline(null, () => {}) ret.on('error', (err) => { t.ok(/opts/.test(err.message)) - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) }) @@ -1025,7 +1025,7 @@ test('pool close waits for all requests', (t) => { path: '/', method: 'GET' }, (err) => { - t.type(err, errors.ClientClosedError) + t.ok(err instanceof errors.ClientClosedError) }) }) }) @@ -1050,7 +1050,7 @@ test('pool destroyed', (t) => { path: '/', method: 'GET' }, (err) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) }) }) @@ -1095,7 +1095,7 @@ test('pool destroy fails queued requests', (t) => { path: '/', method: 'GET' }, (err) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) }) }) diff --git a/test/request-crlf.js b/test/request-crlf.js index f3572062491..be33f767a4d 100644 --- a/test/request-crlf.js +++ b/test/request-crlf.js @@ -25,7 +25,7 @@ test('should validate content-type CRLF Injection', (t) => { }) t.fail('request should fail') } catch (e) { - t.type(e, errors.InvalidArgumentError) + t.ok(e instanceof errors.InvalidArgumentError) t.equal(e.message, 'invalid content-type header') } }) diff --git a/test/request-timeout.js b/test/request-timeout.js index 49d29a6223c..0db4417e0d5 100644 --- a/test/request-timeout.js +++ b/test/request-timeout.js @@ -31,7 +31,7 @@ test('request timeout', (t) => { t.teardown(client.destroy.bind(client)) client.request({ path: '/', method: 'GET' }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) }) }) @@ -53,7 +53,7 @@ test('request timeout with readable body', (t) => { const body = createReadStream(tempfile) client.request({ path: '/', method: 'POST', body }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) }) }) @@ -84,7 +84,7 @@ test('body timeout', (t) => { body.on('data', () => { clock.tick(100) }).on('error', (err) => { - t.type(err, errors.BodyTimeoutError) + t.ok(err instanceof errors.BodyTimeoutError) }) }) @@ -117,7 +117,7 @@ test('overridden request timeout', (t) => { t.teardown(client.destroy.bind(client)) client.request({ path: '/', method: 'GET', headersTimeout: 50 }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) clock.tick(50) @@ -150,7 +150,7 @@ test('overridden body timeout', (t) => { body.on('data', () => { clock.tick(100) }).on('error', (err) => { - t.type(err, errors.BodyTimeoutError) + t.ok(err instanceof errors.BodyTimeoutError) }) }) @@ -186,7 +186,7 @@ test('With EE signal', (t) => { t.teardown(client.destroy.bind(client)) client.request({ path: '/', method: 'GET', signal: ee }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) clock.tick(50) @@ -221,7 +221,7 @@ test('With abort-controller signal', (t) => { t.teardown(client.destroy.bind(client)) client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) clock.tick(50) @@ -257,7 +257,7 @@ test('Abort before timeout (EE)', (t) => { t.teardown(client.destroy.bind(client)) client.request({ path: '/', method: 'GET', signal: ee }, (err, response) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) clock.tick(100) }) }) @@ -292,7 +292,7 @@ test('Abort before timeout (abort-controller)', (t) => { t.teardown(client.destroy.bind(client)) client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => { - t.type(err, errors.RequestAbortedError) + t.ok(err instanceof errors.RequestAbortedError) clock.tick(100) }) }) @@ -326,15 +326,15 @@ test('Timeout with pipelining', (t) => { t.teardown(client.destroy.bind(client)) client.request({ path: '/', method: 'GET' }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) client.request({ path: '/', method: 'GET' }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) client.request({ path: '/', method: 'GET' }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) }) }) @@ -366,7 +366,7 @@ test('Global option', (t) => { t.teardown(client.destroy.bind(client)) client.request({ path: '/', method: 'GET' }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) clock.tick(50) @@ -400,7 +400,7 @@ test('Request options overrides global option', (t) => { t.teardown(client.destroy.bind(client)) client.request({ path: '/', method: 'GET' }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) clock.tick(50) @@ -421,7 +421,7 @@ test('client.destroy should cancel the timeout', (t) => { }) client.request({ path: '/', method: 'GET' }, (err, response) => { - t.type(err, errors.ClientDestroyedError) + t.ok(err instanceof errors.ClientDestroyedError) }) client.destroy(err => { @@ -453,7 +453,7 @@ test('client.close should wait for the timeout', (t) => { t.teardown(client.destroy.bind(client)) client.request({ path: '/', method: 'GET' }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) client.close((err) => { @@ -477,7 +477,7 @@ test('Validation', (t) => { }) t.teardown(client.destroy.bind(client)) } catch (err) { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) } try { @@ -486,7 +486,7 @@ test('Validation', (t) => { }) t.teardown(client.destroy.bind(client)) } catch (err) { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) } try { @@ -495,7 +495,7 @@ test('Validation', (t) => { }) t.teardown(client.destroy.bind(client)) } catch (err) { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) } try { @@ -504,7 +504,7 @@ test('Validation', (t) => { }) t.teardown(client.destroy.bind(client)) } catch (err) { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) } }) @@ -623,7 +623,7 @@ test('stream timeout', (t) => { }, (result) => { t.fail('Should not be called') }, (err) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) }) }) @@ -661,7 +661,7 @@ test('stream custom timeout', (t) => { }, (result) => { t.fail('Should not be called') }, (err) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) }) }) @@ -715,7 +715,7 @@ test('pipeline timeout', (t) => { } }), (err) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) } ) }) @@ -772,7 +772,7 @@ test('pipeline timeout', (t) => { } }), (err) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) } ) }) @@ -806,7 +806,7 @@ test('client.close should not deadlock', (t) => { path: '/', method: 'GET' }, (err, response) => { - t.type(err, errors.HeadersTimeoutError) + t.ok(err instanceof errors.HeadersTimeoutError) }) client.close((err) => { diff --git a/test/socket-timeout.js b/test/socket-timeout.js index f2ad9faa34a..a0facda8369 100644 --- a/test/socket-timeout.js +++ b/test/socket-timeout.js @@ -36,7 +36,7 @@ test('timeout with pipelining 1', (t) => { method: 'GET', opaque: 'asd' }, (err, data) => { - t.type(err, errors.HeadersTimeoutError) // we are expecting an error + t.ok(err instanceof errors.HeadersTimeoutError) // we are expecting an error t.equal(data.opaque, 'asd') }) diff --git a/test/utils/esm-wrapper.mjs b/test/utils/esm-wrapper.mjs index 51f8572a0bf..0e8ac9ffb7a 100644 --- a/test/utils/esm-wrapper.mjs +++ b/test/utils/esm-wrapper.mjs @@ -67,13 +67,13 @@ test('imported errors work with request args validation', (t) => { const client = new Client('http://localhost:5000') client.request(null, (err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) try { client.request(null, 'asd') } catch (err) { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) } }) @@ -83,7 +83,7 @@ test('imported errors work with request args validation promise', (t) => { const client = new Client('http://localhost:5000') client.request(null).catch((err) => { - t.type(err, errors.InvalidArgumentError) + t.ok(err instanceof errors.InvalidArgumentError) }) }) diff --git a/test/wpt/tests/resources/testharness.js b/test/wpt/tests/resources/testharness.js index bc7fb8961b9..a0011f03ac0 100644 --- a/test/wpt/tests/resources/testharness.js +++ b/test/wpt/tests/resources/testharness.js @@ -1247,7 +1247,7 @@ */ function is_node(object) { - // I use duck-typing instead of instanceof, because + // I use duck-typing instead of instanceof because // instanceof doesn't work if the node is from another window (like an // iframe's contentWindow): // http://www.w3.org/Bugs/Public/show_bug.cgi?id=12295 From 6db4bbe979d6bf1fc41bd106e98dba96e724c421 Mon Sep 17 00:00:00 2001 From: Khafra Date: Sat, 10 Feb 2024 04:22:13 -0500 Subject: [PATCH 07/23] remove useless options in web streams (#2729) --- lib/fetch/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/fetch/index.js b/lib/fetch/index.js index a989295bc4b..f65bfbe78da 100644 --- a/lib/fetch/index.js +++ b/lib/fetch/index.js @@ -1118,7 +1118,6 @@ function fetchFinale (fetchParams, response) { controller.enqueue(value) } }, - queuingStrategy: new ByteLengthQueuingStrategy({ highWaterMark: 16384 }), type: 'bytes' }) @@ -1933,7 +1932,6 @@ async function httpNetworkFetch ( // cancelAlgorithm set to cancelAlgorithm. const stream = new ReadableStream( { - highWaterMark: 16384, async start (controller) { fetchParams.controller.controller = controller }, @@ -1943,8 +1941,7 @@ async function httpNetworkFetch ( async cancel (reason) { await cancelAlgorithm(reason) }, - type: 'bytes', - queuingStrategy: new ByteLengthQueuingStrategy({ highWaterMark: 16384 }) + type: 'bytes' } ) From 94a9b5610fc7f791982f0b8039f169e9f67b4e83 Mon Sep 17 00:00:00 2001 From: Sole Cold <53977359+eddienubes@users.noreply.github.com> Date: Sun, 11 Feb 2024 12:31:11 +0100 Subject: [PATCH 08/23] Let's add superagent to the benchmark. closes #2730 (#2731) * feat: added superagent to benchmark.js * feat: added custom http agent to superagent --- benchmarks/benchmark.js | 19 +++++++++++++++++++ package.json | 2 ++ 2 files changed, 21 insertions(+) diff --git a/benchmarks/benchmark.js b/benchmarks/benchmark.js index 32b761a8a56..f63ece5ed16 100644 --- a/benchmarks/benchmark.js +++ b/benchmarks/benchmark.js @@ -10,6 +10,7 @@ const { Pool, Client, fetch, Agent, setGlobalDispatcher } = require('..') let nodeFetch const axios = require('axios') +let superagent let got const util = require('node:util') @@ -85,6 +86,11 @@ const requestAgent = new http.Agent({ maxSockets: connections }) +const superagentAgent = new http.Agent({ + keepAlive: true, + maxSockets: connections +}) + const undiciOptions = { path: '/', method: 'GET', @@ -318,6 +324,16 @@ if (process.env.PORT) { }).catch(console.log) }) } + + experiments.superagent = () => { + return makeParallelRequests(resolve => { + superagent.get(dest.url).pipe(new Writable({ + write (chunk, encoding, callback) { + callback() + } + })).on('finish', resolve) + }) + } } async function main () { @@ -326,6 +342,9 @@ async function main () { nodeFetch = _nodeFetch.default const _got = await import('got') got = _got.default + const _superagent = await import('superagent') + // https://github.com/ladjs/superagent/issues/1540#issue-561464561 + superagent = _superagent.agent().use((req) => req.agent(superagentAgent)) cronometro( experiments, diff --git a/package.json b/package.json index 1ce1a058b1b..7e4f45594d4 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "@matteo.collina/tspl": "^0.1.1", "@sinonjs/fake-timers": "^11.1.0", "@types/node": "^18.0.3", + "@types/superagent": "^8.1.3", "abort-controller": "^3.0.0", "axios": "^1.6.5", "borp": "^0.9.1", @@ -128,6 +129,7 @@ "sinon": "^17.0.1", "snazzy": "^9.0.0", "standard": "^17.0.0", + "superagent": "^8.1.2", "tap": "^16.1.0", "tsd": "^0.30.1", "typescript": "^5.0.2", From 1af7a96378ef29d545d573f65564bab0bc60c749 Mon Sep 17 00:00:00 2001 From: Khafra Date: Sun, 11 Feb 2024 12:23:40 -0500 Subject: [PATCH 09/23] convert node build to latin1 (#2673) --- package.json | 2 +- scripts/strip-comments.js | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 scripts/strip-comments.js diff --git a/package.json b/package.json index 7e4f45594d4..acbb493382d 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "docs" ], "scripts": { - "build:node": "npx esbuild@0.19.4 index-fetch.js --bundle --platform=node --outfile=undici-fetch.js --define:esbuildDetection=1 --keep-names", + "build:node": "npx esbuild@0.19.4 index-fetch.js --bundle --platform=node --outfile=undici-fetch.js --define:esbuildDetection=1 --keep-names && node scripts/strip-comments.js", "prebuild:wasm": "node build/wasm.js --prebuild", "build:wasm": "node build/wasm.js --docker", "lint": "standard | snazzy", diff --git a/scripts/strip-comments.js b/scripts/strip-comments.js new file mode 100644 index 00000000000..9e4396a5dea --- /dev/null +++ b/scripts/strip-comments.js @@ -0,0 +1,8 @@ +'use strict' + +const { readFileSync, writeFileSync } = require('node:fs') +const { transcode } = require('node:buffer') + +const buffer = transcode(readFileSync('./undici-fetch.js'), 'utf8', 'latin1') + +writeFileSync('./undici-fetch.js', buffer.toString('latin1')) From 4e69afd820b990dab428543ec39498bca586ffd4 Mon Sep 17 00:00:00 2001 From: Khafra Date: Mon, 12 Feb 2024 05:28:24 -0500 Subject: [PATCH 10/23] simplify formData body parsing (#2735) * simplify formData body parsing * perf: don't copy all headers * fixup --- lib/fetch/body.js | 63 ++++++++++++++--------------------------------- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/lib/fetch/body.js b/lib/fetch/body.js index 9ceb094ef8d..2781a7b90d9 100644 --- a/lib/fetch/body.js +++ b/lib/fetch/body.js @@ -15,12 +15,12 @@ const { FormData } = require('./formdata') const { kState } = require('./symbols') const { webidl } = require('./webidl') const { Blob, File: NativeFile } = require('node:buffer') -const { kBodyUsed } = require('../core/symbols') const assert = require('node:assert') const { isErrored } = require('../core/util') -const { isUint8Array, isArrayBuffer } = require('util/types') +const { isArrayBuffer } = require('util/types') const { File: UndiciFile } = require('./file') const { serializeAMimeType } = require('./dataURL') +const { Readable } = require('node:stream') /** @type {globalThis['File']} */ const File = NativeFile ?? UndiciFile @@ -291,29 +291,6 @@ function cloneBody (body) { } } -async function * consumeBody (body) { - if (body) { - if (isUint8Array(body)) { - yield body - } else { - const stream = body.stream - - if (util.isDisturbed(stream)) { - throw new TypeError('The body has already been consumed.') - } - - if (stream.locked) { - throw new TypeError('The stream is locked.') - } - - // Compat. - stream[kBodyUsed] = true - - yield * stream - } - } -} - function throwIfAborted (state) { if (state.aborted) { throw new DOMException('The operation was aborted.', 'AbortError') @@ -328,7 +305,7 @@ function bodyMixinMethods (instance) { // given a byte sequence bytes: return a Blob whose // contents are bytes and whose type attribute is this’s // MIME type. - return specConsumeBody(this, (bytes) => { + return consumeBody(this, (bytes) => { let mimeType = bodyMimeType(this) if (mimeType === null) { @@ -348,7 +325,7 @@ function bodyMixinMethods (instance) { // of running consume body with this and the following step // given a byte sequence bytes: return a new ArrayBuffer // whose contents are bytes. - return specConsumeBody(this, (bytes) => { + return consumeBody(this, (bytes) => { return new Uint8Array(bytes).buffer }, instance) }, @@ -356,13 +333,13 @@ function bodyMixinMethods (instance) { text () { // The text() method steps are to return the result of running // consume body with this and UTF-8 decode. - return specConsumeBody(this, utf8DecodeBytes, instance) + return consumeBody(this, utf8DecodeBytes, instance) }, json () { // The json() method steps are to return the result of running // consume body with this and parse JSON from bytes. - return specConsumeBody(this, parseJSONFromBytes, instance) + return consumeBody(this, parseJSONFromBytes, instance) }, async formData () { @@ -375,16 +352,15 @@ function bodyMixinMethods (instance) { // If mimeType’s essence is "multipart/form-data", then: if (mimeType !== null && mimeType.essence === 'multipart/form-data') { - const headers = {} - for (const [key, value] of this.headers) headers[key] = value - const responseFormData = new FormData() let busboy try { busboy = new Busboy({ - headers, + headers: { + 'content-type': serializeAMimeType(mimeType) + }, preservePath: true }) } catch (err) { @@ -427,8 +403,10 @@ function bodyMixinMethods (instance) { busboy.on('error', (err) => reject(new TypeError(err))) }) - if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk) - busboy.end() + if (this.body !== null) { + Readable.from(this[kState].body.stream).pipe(busboy) + } + await busboyResolve return responseFormData @@ -442,20 +420,17 @@ function bodyMixinMethods (instance) { // application/x-www-form-urlencoded parser will keep the BOM. // https://url.spec.whatwg.org/#concept-urlencoded-parser // Note that streaming decoder is stateful and cannot be reused - const streamingDecoder = new TextDecoder('utf-8', { ignoreBOM: true }) + const stream = this[kState].body.stream.pipeThrough(new TextDecoderStream('utf-8', { ignoreBOM: true })) - for await (const chunk of consumeBody(this[kState].body)) { - if (!isUint8Array(chunk)) { - throw new TypeError('Expected Uint8Array chunk') - } - text += streamingDecoder.decode(chunk, { stream: true }) + for await (const chunk of stream) { + text += chunk } - text += streamingDecoder.decode() + entries = new URLSearchParams(text) } catch (err) { // istanbul ignore next: Unclear when new URLSearchParams can fail on a string. // 2. If entries is failure, then throw a TypeError. - throw new TypeError(undefined, { cause: err }) + throw new TypeError(err) } // 3. Return a new FormData object whose entries are entries. @@ -493,7 +468,7 @@ function mixinBody (prototype) { * @param {(value: unknown) => unknown} convertBytesToJSValue * @param {Response|Request} instance */ -async function specConsumeBody (object, convertBytesToJSValue, instance) { +async function consumeBody (object, convertBytesToJSValue, instance) { webidl.brandCheck(object, instance) throwIfAborted(object[kState]) From 42adfca35369c6825ee968c7d7c66da7b55fea81 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Mon, 12 Feb 2024 12:01:36 +0100 Subject: [PATCH 11/23] chore: transform tests from tap to native test runner (#2719) --- test/client-head-reset-override.js | 92 +++++++++++++------------ test/client-post.js | 98 +++++++++++++++------------ test/client-reconnect.js | 57 ++++++++-------- test/client-unref.js | 32 +++++---- test/client-write-max-listeners.js | 31 +++++---- test/connect-errconnect.js | 13 ++-- test/fetch/issue-2294-patch-method.js | 9 +-- test/issue-1670.js | 6 +- test/issue-2065.js | 13 ++-- 9 files changed, 194 insertions(+), 157 deletions(-) diff --git a/test/client-head-reset-override.js b/test/client-head-reset-override.js index 9639e94860d..4582aa0a79c 100644 --- a/test/client-head-reset-override.js +++ b/test/client-head-reset-override.js @@ -1,62 +1,68 @@ 'use strict' +const { tspl } = require('@matteo.collina/tspl') +const { once } = require('node:events') const { createServer } = require('node:http') -const { test } = require('tap') +const { test, after } = require('node:test') const { Client } = require('..') -test('override HEAD reset', (t) => { +test('override HEAD reset', async (t) => { + t = tspl(t, { plan: 4 }) + const expected = 'testing123' const server = createServer((req, res) => { if (req.method === 'GET') { res.write(expected) } res.end() - }) - t.teardown(server.close.bind(server)) + }).listen(0) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => server.close()) - let done - client.on('disconnect', () => { - if (!done) { - t.fail() - } - }) + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) - client.request({ - path: '/', - method: 'HEAD', - reset: false - }, (err, res) => { - t.error(err) - res.body.resume() - }) + let done + client.on('disconnect', () => { + if (!done) { + t.fail() + } + }) - client.request({ - path: '/', - method: 'HEAD', - reset: false - }, (err, res) => { - t.error(err) - res.body.resume() - }) + client.request({ + path: '/', + method: 'HEAD', + reset: false + }, (err, res) => { + t.ifError(err) + res.body.resume() + }) - client.request({ - path: '/', - method: 'GET', - reset: false - }, (err, res) => { - t.error(err) - let str = '' - res.body.on('data', (data) => { - str += data - }).on('end', () => { - t.same(str, expected) - done = true - t.end() - }) + client.request({ + path: '/', + method: 'HEAD', + reset: false + }, (err, res) => { + t.ifError(err) + res.body.resume() + }) + + client.request({ + path: '/', + method: 'GET', + reset: false + }, (err, res) => { + t.ifError(err) + let str = '' + res.body.on('data', (data) => { + str += data + }).on('end', () => { + t.strictEqual(str, expected) + done = true + t.end() }) }) + + await t.completed }) diff --git a/test/client-post.js b/test/client-post.js index 82203ad36c7..e666faf0714 100644 --- a/test/client-post.js +++ b/test/client-post.js @@ -1,73 +1,83 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') +const { once } = require('node:events') const { Client } = require('..') const { createServer } = require('node:http') const { Blob } = require('node:buffer') -test('request post blob', { skip: !Blob }, (t) => { - t.plan(4) +test('request post blob', { skip: !Blob }, async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer(async (req, res) => { - t.equal(req.headers['content-type'], 'application/json') + t.strictEqual(req.headers['content-type'], 'application/json') let str = '' for await (const chunk of req) { str += chunk } - t.equal(str, 'asd') + t.strictEqual(str, 'asd') res.end() }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'GET', - body: new Blob(['asd'], { - type: 'application/json' - }) - }, (err, data) => { - t.error(err) - data.body.resume().on('end', () => { - t.ok(true, 'pass') - }) + after(server.close.bind(server)) + + server.listen(0) + + await once(server, 'listening') + + const client = new Client(`http://localhost:${server.address().port}`) + after(client.destroy.bind(client)) + + client.request({ + path: '/', + method: 'GET', + body: new Blob(['asd'], { + type: 'application/json' + }) + }, (err, data) => { + t.ifError(err) + data.body.resume().on('end', () => { + t.end() }) }) + await t.completed }) -test('request post arrayBuffer', { skip: !Blob }, (t) => { - t.plan(3) +test('request post arrayBuffer', { skip: !Blob }, async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer(async (req, res) => { let str = '' for await (const chunk of req) { str += chunk } - t.equal(str, 'asd') + t.strictEqual(str, 'asd') res.end() }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - - const buf = Buffer.from('asd') - const dst = new ArrayBuffer(buf.byteLength) - buf.copy(new Uint8Array(dst)) - - client.request({ - path: '/', - method: 'GET', - body: dst - }, (err, data) => { - t.error(err) - data.body.resume().on('end', () => { - t.ok(true, 'pass') - }) + + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.destroy()) + + const buf = Buffer.from('asd') + const dst = new ArrayBuffer(buf.byteLength) + buf.copy(new Uint8Array(dst)) + + client.request({ + path: '/', + method: 'GET', + body: dst + }, (err, data) => { + t.ifError(err) + data.body.resume().on('end', () => { + t.ok(true, 'pass') }) }) + + await t.completed }) diff --git a/test/client-reconnect.js b/test/client-reconnect.js index d8ed2ce4ddd..34355ce40ac 100644 --- a/test/client-reconnect.js +++ b/test/client-reconnect.js @@ -1,54 +1,57 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') +const { once } = require('node:events') const { Client } = require('..') const { createServer } = require('node:http') const FakeTimers = require('@sinonjs/fake-timers') const timers = require('../lib/timers') -test('multiple reconnect', (t) => { - t.plan(5) +test('multiple reconnect', async (t) => { + t = tspl(t, { plan: 5 }) let n = 0 const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) const server = createServer((req, res) => { n === 0 ? res.destroy() : res.end('ok') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + server.listen(0) + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(client.destroy.bind(client)) - client.request({ path: '/', method: 'GET' }, (err, data) => { - t.ok(err) - t.equal(err.code, 'UND_ERR_SOCKET') - }) - - client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) - data.body - .resume() - .on('end', () => { - t.ok(true, 'pass') - }) - }) + client.request({ path: '/', method: 'GET' }, (err, data) => { + t.ok(err) + t.strictEqual(err.code, 'UND_ERR_SOCKET') + }) - client.on('disconnect', () => { - if (++n === 1) { + client.request({ path: '/', method: 'GET' }, (err, data) => { + t.ifError(err) + data.body + .resume() + .on('end', () => { t.ok(true, 'pass') - } - process.nextTick(() => { - clock.tick(1000) }) + }) + + client.on('disconnect', () => { + if (++n === 1) { + t.ok(true, 'pass') + } + process.nextTick(() => { + clock.tick(1000) }) }) + await t.completed }) diff --git a/test/client-unref.js b/test/client-unref.js index f46376f9c46..49df4244e8e 100644 --- a/test/client-unref.js +++ b/test/client-unref.js @@ -3,35 +3,41 @@ const { Worker, isMainThread, workerData } = require('node:worker_threads') if (isMainThread) { - const tap = require('tap') + const { tspl } = require('@matteo.collina/tspl') + const { test, after } = require('node:test') + const { once } = require('node:events') const { createServer } = require('node:http') - tap.test('client automatically closes itself when idle', t => { - t.plan(1) + test('client automatically closes itself when idle', async t => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(server.close.bind(server)) server.keepAliveTimeout = 9999 - server.listen(0, () => { - const url = `http://localhost:${server.address().port}` - const worker = new Worker(__filename, { workerData: { url } }) - worker.on('exit', code => { - t.equal(code, 0) - }) + server.listen(0) + + await once(server, 'listening') + const url = `http://localhost:${server.address().port}` + const worker = new Worker(__filename, { workerData: { url } }) + worker.on('exit', code => { + t.strictEqual(code, 0) }) + await t.completed }) - tap.test('client automatically closes itself if the server is not there', t => { - t.plan(1) + test('client automatically closes itself if the server is not there', async t => { + t = tspl(t, { plan: 1 }) const url = 'http://localhost:4242' // hopefully empty port const worker = new Worker(__filename, { workerData: { url } }) worker.on('exit', code => { - t.equal(code, 0) + t.strictEqual(code, 0) }) + + await t.completed }) } else { const { Client } = require('..') diff --git a/test/client-write-max-listeners.js b/test/client-write-max-listeners.js index 237bb527f10..c76ce60b0ab 100644 --- a/test/client-write-max-listeners.js +++ b/test/client-write-max-listeners.js @@ -1,19 +1,21 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') +const { once } = require('node:events') const { Client } = require('..') const { createServer } = require('node:http') const { Readable } = require('node:stream') -test('socket close listener does not leak', (t) => { - t.plan(32) +test('socket close listener does not leak', async (t) => { + t = tspl(t, { plan: 32 }) const server = createServer() server.on('request', (req, res) => { res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const makeBody = () => { return new Readable({ @@ -26,7 +28,7 @@ test('socket close listener does not leak', (t) => { } const onRequest = (err, data) => { - t.error(err) + t.ifError(err) data.body.on('end', () => t.ok(true, 'pass')).resume() } @@ -36,16 +38,19 @@ test('socket close listener does not leak', (t) => { } } process.on('warning', onWarning) - t.teardown(() => { + after(() => { process.removeListener('warning', onWarning) }) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + server.listen(0) - for (let n = 0; n < 16; ++n) { - client.request({ path: '/', method: 'GET', body: makeBody() }, onRequest) - } - }) + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.destroy()) + + for (let n = 0; n < 16; ++n) { + client.request({ path: '/', method: 'GET', body: makeBody() }, onRequest) + } + + await t.completed }) diff --git a/test/connect-errconnect.js b/test/connect-errconnect.js index 85b11f83847..7c241c1453e 100644 --- a/test/connect-errconnect.js +++ b/test/connect-errconnect.js @@ -1,14 +1,15 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const net = require('node:net') -test('connect-connectionError', t => { - t.plan(2) +test('connect-connectionError', async t => { + t = tspl(t, { plan: 2 }) const client = new Client('http://localhost:9000') - t.teardown(client.close.bind(client)) + after(() => client.close()) client.once('connectionError', () => { t.ok(true, 'pass') @@ -27,6 +28,8 @@ test('connect-connectionError', t => { path: '/', method: 'GET' }, (err) => { - t.equal(err, _err) + t.strictEqual(err, _err) }) + + await t.completed }) diff --git a/test/fetch/issue-2294-patch-method.js b/test/fetch/issue-2294-patch-method.js index bac7ef51aa9..6223989c07c 100644 --- a/test/fetch/issue-2294-patch-method.js +++ b/test/fetch/issue-2294-patch-method.js @@ -1,19 +1,20 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Request } = require('../..') test('Using `patch` method emits a warning.', (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const { emitWarning } = process - t.teardown(() => { + after(() => { process.emitWarning = emitWarning }) process.emitWarning = (warning, options) => { - t.equal(options.code, 'UNDICI-FETCH-patch') + t.strictEqual(options.code, 'UNDICI-FETCH-patch') } // eslint-disable-next-line no-new diff --git a/test/issue-1670.js b/test/issue-1670.js index c27bdb272dc..7a0cda32669 100644 --- a/test/issue-1670.js +++ b/test/issue-1670.js @@ -1,12 +1,10 @@ 'use strict' -const { test } = require('tap') +const { test } = require('node:test') const { request } = require('..') -test('https://github.com/mcollina/undici/issues/810', async (t) => { +test('https://github.com/mcollina/undici/issues/810', async () => { const { body } = await request('https://api.github.com/user/emails') await body.text() - - t.end() }) diff --git a/test/issue-2065.js b/test/issue-2065.js index 5080353a584..14bca22d311 100644 --- a/test/issue-2065.js +++ b/test/issue-2065.js @@ -1,18 +1,21 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { createServer } = require('node:http') const { once } = require('node:events') const { createReadStream } = require('node:fs') const { File, FormData, request } = require('..') test('undici.request with a FormData body should set content-length header', async (t) => { + t = tspl(t, { plan: 1 }) + const server = createServer((req, res) => { t.ok(req.headers['content-length']) res.end() }).listen(0) - t.teardown(server.close.bind(server)) + after(() => server.close()) await once(server, 'listening') const body = new FormData() @@ -25,12 +28,14 @@ test('undici.request with a FormData body should set content-length header', asy }) test('undici.request with a FormData stream value should set transfer-encoding header', async (t) => { + t = tspl(t, { plan: 1 }) + const server = createServer((req, res) => { - t.equal(req.headers['transfer-encoding'], 'chunked') + t.strictEqual(req.headers['transfer-encoding'], 'chunked') res.end() }).listen(0) - t.teardown(server.close.bind(server)) + after(() => server.close()) await once(server, 'listening') class BlobFromStream { From 7f90f6364900b5b73b56eecec7c7bd2094f4eb34 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Mon, 12 Feb 2024 12:01:44 +0100 Subject: [PATCH 12/23] chore: migrate a batch of tests to node test runner (#2737) --- test/client-connect.js | 46 ++-- test/client-idempotent-body.js | 17 +- test/client-keep-alive.js | 478 +++++++++++++++++---------------- test/dispatcher.js | 6 +- test/errors.js | 32 +-- test/examples.js | 35 ++- test/headers-as-array.js | 94 ++++--- test/headers-crlf.js | 57 ++-- test/http-100.js | 195 +++++++------- test/inflight-and-close.js | 54 ++-- 10 files changed, 547 insertions(+), 467 deletions(-) diff --git a/test/client-connect.js b/test/client-connect.js index 4917a526d0e..e002a42c571 100644 --- a/test/client-connect.js +++ b/test/client-connect.js @@ -1,14 +1,16 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') +const { once } = require('node:events') const { Client, errors } = require('..') const http = require('node:http') const EE = require('node:events') const { kBusy } = require('../lib/core/symbols') // TODO: move to test/node-test/client-connect.js -test('connect aborted after connect', (t) => { - t.plan(3) +test('connect aborted after connect', async (t) => { + t = tspl(t, { plan: 3 }) const signal = new EE() const server = http.createServer((req, res) => { @@ -17,22 +19,26 @@ test('connect aborted after connect', (t) => { server.on('connect', (req, c, firstBodyChunk) => { signal.emit('abort') }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { - pipelining: 3 - }) - t.teardown(client.destroy.bind(client)) - - client.connect({ - path: '/', - signal, - opaque: 'asd' - }, (err, { opaque }) => { - t.equal(opaque, 'asd') - t.ok(err instanceof errors.RequestAbortedError) - }) - t.equal(client[kBusy], true) + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + + const client = new Client(`http://localhost:${server.address().port}`, { + pipelining: 3 }) + after(() => client.close()) + + client.connect({ + path: '/', + signal, + opaque: 'asd' + }, (err, { opaque }) => { + t.strictEqual(opaque, 'asd') + t.ok(err instanceof errors.RequestAbortedError) + }) + t.strictEqual(client[kBusy], true) + + await t.completed }) diff --git a/test/client-idempotent-body.js b/test/client-idempotent-body.js index 0575b6b8ebd..07004cb8296 100644 --- a/test/client-idempotent-body.js +++ b/test/client-idempotent-body.js @@ -1,11 +1,12 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const { createServer } = require('node:http') -test('idempotent retry', (t) => { - t.plan(11) +test('idempotent retry', async (t) => { + t = tspl(t, { plan: 11 }) const body = 'world' const server = createServer((req, res) => { @@ -13,17 +14,17 @@ test('idempotent retry', (t) => { req.on('data', data => { buf += data }).on('end', () => { - t.strictSame(buf, body) + t.strictEqual(buf, body) res.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const _err = new Error() @@ -36,8 +37,10 @@ test('idempotent retry', (t) => { }, () => { throw _err }, (err) => { - t.equal(err, _err) + t.strictEqual(err, _err) }) } }) + + await t.completed }) diff --git a/test/client-keep-alive.js b/test/client-keep-alive.js index 15e432c7b2c..b521624caec 100644 --- a/test/client-keep-alive.js +++ b/test/client-keep-alive.js @@ -1,6 +1,8 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') +const { once } = require('node:events') const { Client } = require('..') const timers = require('../lib/timers') const { kConnect } = require('../lib/core/symbols') @@ -8,8 +10,8 @@ const { createServer } = require('node:net') const http = require('node:http') const FakeTimers = require('@sinonjs/fake-timers') -test('keep-alive header', (t) => { - t.plan(2) +test('keep-alive header', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((socket) => { socket.write('HTTP/1.1 200 OK\r\n') @@ -18,41 +20,41 @@ test('keep-alive header', (t) => { socket.write('Connection: keep-alive\r\n') socket.write('\r\n\r\n') }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - const timeout = setTimeout(() => { - t.fail() - }, 4e3) - client.on('disconnect', () => { - t.ok(true, 'pass') - clearTimeout(timeout) - }) - }).resume() - }) + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + const timeout = setTimeout(() => { + t.fail() + }, 4e3) + client.on('disconnect', () => { + t.ok(true, 'pass') + clearTimeout(timeout) + }) + }).resume() }) + await t.completed }) -test('keep-alive header 0', (t) => { - t.plan(2) +test('keep-alive header 0', async (t) => { + t = tspl(t, { plan: 2 }) const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { - Object.assign(timers, orgTimers) - }) + after(() => { Object.assign(timers, orgTimers) }) const server = createServer((socket) => { socket.write('HTTP/1.1 200 OK\r\n') @@ -61,31 +63,33 @@ test('keep-alive header 0', (t) => { socket.write('Connection: keep-alive\r\n') socket.write('\r\n\r\n') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { - keepAliveTimeoutThreshold: 500 - }) - t.teardown(client.destroy.bind(client)) + server.listen(0) - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - client.on('disconnect', () => { - t.ok(true, 'pass') - }) - clock.tick(600) - }).resume() - }) + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`, { + keepAliveTimeoutThreshold: 500 }) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + client.on('disconnect', () => { + t.ok(true, 'pass') + }) + clock.tick(600) + }).resume() + }) + await t.completed }) -test('keep-alive header 1', (t) => { - t.plan(2) +test('keep-alive header 1', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((socket) => { socket.write('HTTP/1.1 200 OK\r\n') @@ -94,32 +98,34 @@ test('keep-alive header 1', (t) => { socket.write('Connection: keep-alive\r\n') socket.write('\r\n\r\n') }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - const timeout = setTimeout(() => { - t.fail() - }, 0) - client.on('disconnect', () => { - t.ok(true, 'pass') - clearTimeout(timeout) - }) - }).resume() - }) + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + const timeout = setTimeout(() => { + t.fail() + }, 0) + client.on('disconnect', () => { + t.ok(true, 'pass') + clearTimeout(timeout) + }) + }).resume() }) + await t.completed }) -test('keep-alive header no postfix', (t) => { - t.plan(2) +test('keep-alive header no postfix', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((socket) => { socket.write('HTTP/1.1 200 OK\r\n') @@ -128,32 +134,34 @@ test('keep-alive header no postfix', (t) => { socket.write('Connection: keep-alive\r\n') socket.write('\r\n\r\n') }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - const timeout = setTimeout(() => { - t.fail() - }, 4e3) - client.on('disconnect', () => { - t.ok(true, 'pass') - clearTimeout(timeout) - }) - }).resume() - }) + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + const timeout = setTimeout(() => { + t.fail() + }, 4e3) + client.on('disconnect', () => { + t.ok(true, 'pass') + clearTimeout(timeout) + }) + }).resume() }) + await t.completed }) -test('keep-alive not timeout', (t) => { - t.plan(2) +test('keep-alive not timeout', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((socket) => { socket.write('HTTP/1.1 200 OK\r\n') @@ -162,34 +170,36 @@ test('keep-alive not timeout', (t) => { socket.write('Connection: keep-alive\r\n') socket.write('\r\n\r\n') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { - keepAliveTimeout: 1e3 - }) - t.teardown(client.destroy.bind(client)) + server.listen(0) - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - const timeout = setTimeout(() => { - t.fail() - }, 3e3) - client.on('disconnect', () => { - t.ok(true, 'pass') - clearTimeout(timeout) - }) - }).resume() - }) + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`, { + keepAliveTimeout: 1e3 }) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + const timeout = setTimeout(() => { + t.fail() + }, 3e3) + client.on('disconnect', () => { + t.ok(true, 'pass') + clearTimeout(timeout) + }) + }).resume() + }) + await t.completed }) -test('keep-alive threshold', (t) => { - t.plan(2) +test('keep-alive threshold', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((socket) => { socket.write('HTTP/1.1 200 OK\r\n') @@ -198,35 +208,37 @@ test('keep-alive threshold', (t) => { socket.write('Connection: keep-alive\r\n') socket.write('\r\n\r\n') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { - keepAliveTimeout: 30e3, - keepAliveTimeoutThreshold: 29e3 - }) - t.teardown(client.destroy.bind(client)) + server.listen(0) - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - const timeout = setTimeout(() => { - t.fail() - }, 5e3) - client.on('disconnect', () => { - t.ok(true, 'pass') - clearTimeout(timeout) - }) - }).resume() - }) + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`, { + keepAliveTimeout: 30e3, + keepAliveTimeoutThreshold: 29e3 }) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + const timeout = setTimeout(() => { + t.fail() + }, 5e3) + client.on('disconnect', () => { + t.ok(true, 'pass') + clearTimeout(timeout) + }) + }).resume() + }) + await t.completed }) -test('keep-alive max keepalive', (t) => { - t.plan(2) +test('keep-alive max keepalive', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((socket) => { socket.write('HTTP/1.1 200 OK\r\n') @@ -235,35 +247,37 @@ test('keep-alive max keepalive', (t) => { socket.write('Connection: keep-alive\r\n') socket.write('\r\n\r\n') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { - keepAliveTimeout: 30e3, - keepAliveMaxTimeout: 1e3 - }) - t.teardown(client.destroy.bind(client)) + server.listen(0) - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - const timeout = setTimeout(() => { - t.fail() - }, 3e3) - client.on('disconnect', () => { - t.ok(true, 'pass') - clearTimeout(timeout) - }) - }).resume() - }) + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`, { + keepAliveTimeout: 30e3, + keepAliveMaxTimeout: 1e3 }) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + const timeout = setTimeout(() => { + t.fail() + }, 3e3) + client.on('disconnect', () => { + t.ok(true, 'pass') + clearTimeout(timeout) + }) + }).resume() + }) + await t.completed }) -test('connection close', (t) => { - t.plan(4) +test('connection close', async (t) => { + t = tspl(t, { plan: 4 }) let close = false const server = createServer((socket) => { @@ -276,84 +290,88 @@ test('connection close', (t) => { socket.write('Connection: close\r\n') socket.write('\r\n\r\n') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { - pipelining: 2 - }) - t.teardown(client.destroy.bind(client)) + server.listen(0) - client[kConnect](() => { - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - const timeout = setTimeout(() => { - t.fail() - }, 3e3) - client.once('disconnect', () => { - close = false - t.ok(true, 'pass') - clearTimeout(timeout) - }) - }).resume() - }) + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`, { + pipelining: 2 + }) + after(() => client.close()) - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - const timeout = setTimeout(() => { - t.fail() - }, 3e3) - client.once('disconnect', () => { - t.ok(true, 'pass') - clearTimeout(timeout) - }) - }).resume() - }) + client[kConnect](() => { + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + const timeout = setTimeout(() => { + t.fail() + }, 3e3) + client.once('disconnect', () => { + close = false + t.ok(true, 'pass') + clearTimeout(timeout) + }) + }).resume() + }) + + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + const timeout = setTimeout(() => { + t.fail() + }, 3e3) + client.once('disconnect', () => { + t.ok(true, 'pass') + clearTimeout(timeout) + }) + }).resume() }) }) + await t.completed }) -test('Disable keep alive', (t) => { - t.plan(7) +test('Disable keep alive', async (t) => { + t = tspl(t, { plan: 7 }) const ports = [] const server = http.createServer((req, res) => { - t.notOk(ports.includes(req.socket.remotePort)) + t.strictEqual(ports.includes(req.socket.remotePort), false) ports.push(req.socket.remotePort) - t.match(req.headers, { connection: 'close' }) + t.strictEqual(req.headers.connection, 'close') res.writeHead(200, { connection: 'close' }) res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 0 }) - t.teardown(client.destroy.bind(client)) + server.listen(0) - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - client.request({ - path: '/', - method: 'GET' - }, (err, { body }) => { - t.error(err) - body.on('end', () => { - t.ok(true, 'pass') - }).resume() - }) - }).resume() - }) + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 0 }) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + client.request({ + path: '/', + method: 'GET' + }, (err, { body }) => { + t.ifError(err) + body.on('end', () => { + t.ok(true, 'pass') + }).resume() + }) + }).resume() }) + await t.completed }) diff --git a/test/dispatcher.js b/test/dispatcher.js index 22750a1e81c..d004c5e5e27 100644 --- a/test/dispatcher.js +++ b/test/dispatcher.js @@ -1,14 +1,14 @@ 'use strict' -const t = require('tap') -const { test } = t +const { tspl } = require('@matteo.collina/tspl') +const { test } = require('node:test') const Dispatcher = require('../lib/dispatcher') class PoorImplementation extends Dispatcher {} test('dispatcher implementation', (t) => { - t.plan(6) + t = tspl(t, { plan: 6 }) const dispatcher = new Dispatcher() t.throws(() => dispatcher.dispatch(), Error, 'throws on unimplemented dispatch') diff --git a/test/errors.js b/test/errors.js index a6f17ef9b09..e34b406a905 100644 --- a/test/errors.js +++ b/test/errors.js @@ -1,7 +1,7 @@ 'use strict' -const t = require('tap') -const { test } = t +const { tspl } = require('@matteo.collina/tspl') +const { describe, test } = require('node:test') const errors = require('../lib/core/errors') @@ -31,51 +31,47 @@ const scenarios = [ ] scenarios.forEach(scenario => { - test(scenario.name, t => { + describe(scenario.name, () => { const SAMPLE_MESSAGE = 'sample message' const errorWithDefaultMessage = () => new scenario.ErrorClass() const errorWithProvidedMessage = () => new scenario.ErrorClass(SAMPLE_MESSAGE) test('should use default message', t => { - t.plan(1) + t = tspl(t, { plan: 1 }) const error = errorWithDefaultMessage() - t.equal(error.message, scenario.defaultMessage) + t.strictEqual(error.message, scenario.defaultMessage) }) test('should use provided message', t => { - t.plan(1) + t = tspl(t, { plan: 1 }) const error = errorWithProvidedMessage() - t.equal(error.message, SAMPLE_MESSAGE) + t.strictEqual(error.message, SAMPLE_MESSAGE) }) test('should have proper fields', t => { - t.plan(6) + t = tspl(t, { plan: 6 }) const errorInstances = [errorWithDefaultMessage(), errorWithProvidedMessage()] errorInstances.forEach(error => { - t.equal(error.name, scenario.name) - t.equal(error.code, scenario.code) + t.strictEqual(error.name, scenario.name) + t.strictEqual(error.code, scenario.code) t.ok(error.stack) }) }) - - t.end() }) }) -test('Default HTTPParseError Codes', t => { +describe('Default HTTPParseError Codes', () => { test('code and data should be undefined when not set', t => { - t.plan(2) + t = tspl(t, { plan: 2 }) const error = new errors.HTTPParserError('HTTPParserError') - t.equal(error.code, undefined) - t.equal(error.data, undefined) + t.strictEqual(error.code, undefined) + t.strictEqual(error.data, undefined) }) - - t.end() }) diff --git a/test/examples.js b/test/examples.js index 7096970662f..d344236b68d 100644 --- a/test/examples.js +++ b/test/examples.js @@ -1,10 +1,14 @@ 'use strict' +const { tspl } = require('@matteo.collina/tspl') const { createServer } = require('node:http') -const { test } = require('tap') +const { test, after } = require('node:test') +const { once } = require('node:events') const examples = require('../examples/request.js') test('request examples', async (t) => { + t = tspl(t, { plan: 7 }) + let lastReq const exampleServer = createServer((req, res) => { lastReq = req @@ -32,28 +36,33 @@ test('request examples', async (t) => { res.end('{"error":"an error"}') }) - t.teardown(exampleServer.close.bind(exampleServer)) - t.teardown(errorServer.close.bind(errorServer)) + after(() => exampleServer.close()) + after(() => errorServer.close()) + + exampleServer.listen(0) + errorServer.listen(0) - await exampleServer.listen(0) - await errorServer.listen(0) + await Promise.all([ + once(exampleServer, 'listening'), + once(errorServer, 'listening') + ]) await examples.getRequest(exampleServer.address().port) - t.equal(lastReq.method, 'GET') + t.strictEqual(lastReq.method, 'GET') await examples.postJSONRequest(exampleServer.address().port) - t.equal(lastReq.method, 'POST') - t.equal(lastReq.headers['content-type'], 'application/json') + t.strictEqual(lastReq.method, 'POST') + t.strictEqual(lastReq.headers['content-type'], 'application/json') await examples.postFormRequest(exampleServer.address().port) - t.equal(lastReq.method, 'POST') - t.equal(lastReq.headers['content-type'], 'application/x-www-form-urlencoded') + t.strictEqual(lastReq.method, 'POST') + t.strictEqual(lastReq.headers['content-type'], 'application/x-www-form-urlencoded') await examples.deleteRequest(exampleServer.address().port) - t.equal(lastReq.method, 'DELETE') + t.strictEqual(lastReq.method, 'DELETE') await examples.deleteRequest(errorServer.address().port) - t.equal(lastReq.method, 'DELETE') + t.strictEqual(lastReq.method, 'DELETE') - t.end() + await t.completed }) diff --git a/test/headers-as-array.js b/test/headers-as-array.js index e50605332e5..693979e92b7 100644 --- a/test/headers-as-array.js +++ b/test/headers-as-array.js @@ -1,102 +1,122 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, errors } = require('..') const { createServer } = require('node:http') -test('handle headers as array', (t) => { - t.plan(1) +test('handle headers as array', async (t) => { + t = tspl(t, { plan: 3 }) const headers = ['a', '1', 'b', '2', 'c', '3'] const server = createServer((req, res) => { - t.match(req.headers, { a: '1', b: '2', c: '3' }) + t.strictEqual(req.headers.a, '1') + t.strictEqual(req.headers.b, '2') + t.strictEqual(req.headers.c, '3') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', headers - }, () => {}) + }, () => { }) }) + + await t.completed }) -test('handle multi-valued headers as array', (t) => { - t.plan(1) +test('handle multi-valued headers as array', async (t) => { + t = tspl(t, { plan: 4 }) const headers = ['a', '1', 'b', '2', 'c', '3', 'd', '4', 'd', '5'] const server = createServer((req, res) => { - t.match(req.headers, { a: '1', b: '2', c: '3', d: '4, 5' }) + t.strictEqual(req.headers.a, '1') + t.strictEqual(req.headers.b, '2') + t.strictEqual(req.headers.c, '3') + t.strictEqual(req.headers.d, '4, 5') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', headers - }, () => {}) + }, () => { }) }) + + await t.completed }) -test('handle headers with array', (t) => { - t.plan(1) +test('handle headers with array', async (t) => { + t = tspl(t, { plan: 4 }) const headers = { a: '1', b: '2', c: '3', d: ['4'] } const server = createServer((req, res) => { - t.match(req.headers, { a: '1', b: '2', c: '3', d: '4' }) + t.strictEqual(req.headers.a, '1') + t.strictEqual(req.headers.b, '2') + t.strictEqual(req.headers.c, '3') + t.strictEqual(req.headers.d, '4') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', headers - }, () => {}) + }, () => { }) }) + + await t.completed }) -test('handle multi-valued headers', (t) => { - t.plan(1) +test('handle multi-valued headers', async (t) => { + t = tspl(t, { plan: 4 }) const headers = { a: '1', b: '2', c: '3', d: ['4', '5'] } const server = createServer((req, res) => { - t.match(req.headers, { a: '1', b: '2', c: '3', d: '4, 5' }) + t.strictEqual(req.headers.a, '1') + t.strictEqual(req.headers.b, '2') + t.strictEqual(req.headers.c, '3') + t.strictEqual(req.headers.d, '4, 5') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', headers - }, () => {}) + }, () => { }) }) + + await t.completed }) -test('fail if headers array is odd', (t) => { - t.plan(2) +test('fail if headers array is odd', async (t) => { + t = tspl(t, { plan: 2 }) const headers = ['a', '1', 'b', '2', 'c', '3', 'd'] const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -104,20 +124,22 @@ test('fail if headers array is odd', (t) => { headers }, (err) => { t.ok(err instanceof errors.InvalidArgumentError) - t.equal(err.message, 'headers array must be even') + t.strictEqual(err.message, 'headers array must be even') }) }) + + await t.completed }) -test('fail if headers is not an object or an array', (t) => { - t.plan(2) +test('fail if headers is not an object or an array', async (t) => { + t = tspl(t, { plan: 2 }) const headers = 'not an object or an array' const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -125,7 +147,9 @@ test('fail if headers is not an object or an array', (t) => { headers }, (err) => { t.ok(err instanceof errors.InvalidArgumentError) - t.equal(err.message, 'headers must be an object or an array') + t.strictEqual(err.message, 'headers must be an object or an array') }) }) + + await t.completed }) diff --git a/test/headers-crlf.js b/test/headers-crlf.js index d41e924aca1..8660259dbbd 100644 --- a/test/headers-crlf.js +++ b/test/headers-crlf.js @@ -1,36 +1,41 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') +const { once } = require('node:events') const { Client } = require('..') const { createServer } = require('node:http') -test('CRLF Injection in Nodejs ‘undici’ via host', (t) => { - t.plan(1) +test('CRLF Injection in Nodejs ‘undici’ via host', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer(async (req, res) => { res.end() }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) - - const unsanitizedContentTypeInput = '12 \r\n\r\naaa:aaa' - - try { - const { body } = await client.request({ - path: '/', - method: 'POST', - headers: { - 'content-type': 'application/json', - host: unsanitizedContentTypeInput - }, - body: 'asd' - }) - await body.dump() - } catch (err) { - t.same(err.code, 'UND_ERR_INVALID_ARG') - } - }) + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + const unsanitizedContentTypeInput = '12 \r\n\r\naaa:aaa' + + try { + const { body } = await client.request({ + path: '/', + method: 'POST', + headers: { + 'content-type': 'application/json', + host: unsanitizedContentTypeInput + }, + body: 'asd' + }) + await body.dump() + } catch (err) { + t.strictEqual(err.code, 'UND_ERR_INVALID_ARG') + } + await t.completed }) diff --git a/test/http-100.js b/test/http-100.js index 434b53a5c2f..43e75a02e10 100644 --- a/test/http-100.js +++ b/test/http-100.js @@ -1,41 +1,46 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const { createServer } = require('node:http') const net = require('node:net') +const { once } = require('node:events') -test('ignore informational response', (t) => { - t.plan(2) +test('ignore informational response', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.writeProcessing() req.pipe(res) }) - t.teardown(server.close.bind(server)) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'POST', - body: 'hello' - }, (err, response) => { - t.error(err) - const bufs = [] - response.body.on('data', (buf) => { - bufs.push(buf) - }) - response.body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) - }) + after(() => server.close()) + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + client.request({ + path: '/', + method: 'POST', + body: 'hello' + }, (err, response) => { + t.ifError(err) + const bufs = [] + response.body.on('data', (buf) => { + bufs.push(buf) + }) + response.body.on('end', () => { + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) + + await t.completed }) -test('error 103 body', (t) => { - t.plan(2) +test('error 103 body', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer((socket) => { socket.write('HTTP/1.1 103 Early Hints\r\n') @@ -43,99 +48,107 @@ test('error 103 body', (t) => { socket.write('\r\n') socket.write('a\r\n') }) - t.teardown(server.close.bind(server)) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'GET' - }, (err) => { - t.equal(err.code, 'HPE_INVALID_CONSTANT') - }) - client.on('disconnect', () => { - t.ok(true, 'pass') - }) + after(() => server.close()) + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err) => { + t.strictEqual(err.code, 'HPE_INVALID_CONSTANT') }) + client.on('disconnect', () => { + t.ok(true, 'pass') + }) + await t.completed }) -test('error 100 body', (t) => { - t.plan(2) +test('error 100 body', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer((socket) => { socket.write('HTTP/1.1 100 Early Hints\r\n') socket.write('\r\n') }) - t.teardown(server.close.bind(server)) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'GET' - }, (err) => { - t.equal(err.message, 'bad response') - }) - client.on('disconnect', () => { - t.ok(true, 'pass') - }) + after(() => server.close()) + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err) => { + t.strictEqual(err.message, 'bad response') }) + client.on('disconnect', () => { + t.ok(true, 'pass') + }) + await t.completed }) -test('error 101 upgrade', (t) => { - t.plan(2) +test('error 101 upgrade', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer((socket) => { socket.write('HTTP/1.1 101 Switching Protocols\r\nUpgrade: example/1\r\nConnection: Upgrade\r\n') socket.write('\r\n') }) - t.teardown(server.close.bind(server)) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'GET' - }, (err) => { - t.equal(err.message, 'bad upgrade') - }) - client.on('disconnect', () => { - t.ok(true, 'pass') - }) + after(() => server.close()) + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err) => { + t.strictEqual(err.message, 'bad upgrade') }) + client.on('disconnect', () => { + t.ok(true, 'pass') + }) + await t.completed }) -test('1xx response without timeouts', t => { - t.plan(2) +test('1xx response without timeouts', async t => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.writeProcessing() setTimeout(() => req.pipe(res), 2000) }) - t.teardown(server.close.bind(server)) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { - bodyTimeout: 0, - headersTimeout: 0 + after(() => server.close()) + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`, { + bodyTimeout: 0, + headersTimeout: 0 + }) + after(() => client.close()) + + client.request({ + path: '/', + method: 'POST', + body: 'hello' + }, (err, response) => { + t.ifError(err) + const bufs = [] + response.body.on('data', (buf) => { + bufs.push(buf) }) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'POST', - body: 'hello' - }, (err, response) => { - t.error(err) - const bufs = [] - response.body.on('data', (buf) => { - bufs.push(buf) - }) - response.body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) - }) + response.body.on('end', () => { + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) + await t.completed }) diff --git a/test/inflight-and-close.js b/test/inflight-and-close.js index 576a8c568ff..075cdba1668 100644 --- a/test/inflight-and-close.js +++ b/test/inflight-and-close.js @@ -1,31 +1,37 @@ 'use strict' -const t = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test } = require('node:test') const { request } = require('..') const http = require('node:http') -const server = http.createServer((req, res) => { - res.writeHead(200) - res.end('Response body') - res.socket.end() // Close the connection immediately with every response -}).listen(0, '127.0.0.1', function () { - const url = `http://127.0.0.1:${this.address().port}` - request(url) - .then(({ statusCode, headers, body }) => { - t.ok(true, 'first response') - body.resume() - body.on('close', function () { - t.ok(true, 'first body closed') - }) - return request(url) - .then(({ statusCode, headers, body }) => { - t.ok(true, 'second response') - body.resume() - body.on('close', function () { - server.close() - }) +test('inflight and close', async (t) => { + t = tspl(t, { plan: 3 }) + + const server = http.createServer((req, res) => { + res.writeHead(200) + res.end('Response body') + res.socket.end() // Close the connection immediately with every response + }).listen(0, '127.0.0.1', function () { + const url = `http://127.0.0.1:${this.address().port}` + request(url) + .then(({ statusCode, headers, body }) => { + t.ok(true, 'first response') + body.resume() + body.on('close', function () { + t.ok(true, 'first body closed') }) - }).catch((err) => { - t.error(err) - }) + return request(url) + .then(({ statusCode, headers, body }) => { + t.ok(true, 'second response') + body.resume() + body.on('close', function () { + server.close() + }) + }) + }).catch((err) => { + t.ifError(err) + }) + }) + await t.completed }) From c27b00e5aca8ccc98f24e1e08ce2b7f10b46101f Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Mon, 12 Feb 2024 12:01:52 +0100 Subject: [PATCH 13/23] chore: migrate a batch of tests to node test runner (#2739) --- test/mock-agent.js | 775 +++++++++++---------- test/mock-client.js | 140 ++-- test/mock-errors.js | 41 +- test/mock-interceptor-unused-assertions.js | 104 +-- test/mock-interceptor.js | 126 ++-- test/mock-pool.js | 136 ++-- test/mock-scope.js | 35 +- test/mock-utils.js | 63 +- 8 files changed, 703 insertions(+), 717 deletions(-) diff --git a/test/mock-agent.js b/test/mock-agent.js index ed58464b527..80b04e658e8 100644 --- a/test/mock-agent.js +++ b/test/mock-agent.js @@ -1,6 +1,7 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after, describe } = require('node:test') const { createServer } = require('node:http') const { promisify } = require('node:util') const { request, setGlobalDispatcher, MockAgent, Agent } = require('..') @@ -14,93 +15,87 @@ const Dispatcher = require('../lib/dispatcher') const { MockNotMatchedError } = require('../lib/mock/mock-errors') const { fetch } = require('..') -test('MockAgent - constructor', t => { - t.plan(5) - - t.test('sets up mock agent', t => { - t.plan(1) +describe('MockAgent - constructor', () => { + test('sets up mock agent', t => { + t = tspl(t, { plan: 1 }) t.doesNotThrow(() => new MockAgent()) }) - t.test('should implement the Dispatcher API', t => { - t.plan(1) + test('should implement the Dispatcher API', t => { + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent() t.ok(mockAgent instanceof Dispatcher) }) - t.test('sets up mock agent with single connection', t => { - t.plan(1) + test('sets up mock agent with single connection', t => { + t = tspl(t, { plan: 1 }) t.doesNotThrow(() => new MockAgent({ connections: 1 })) }) - t.test('should error passed agent is not valid', t => { - t.plan(2) + test('should error passed agent is not valid', t => { + t = tspl(t, { plan: 2 }) t.throws(() => new MockAgent({ agent: {} }), new InvalidArgumentError('Argument opts.agent must implement Agent')) t.throws(() => new MockAgent({ agent: { dispatch: '' } }), new InvalidArgumentError('Argument opts.agent must implement Agent')) }) - t.test('should be able to specify the agent to mock', t => { - t.plan(1) + test('should be able to specify the agent to mock', t => { + t = tspl(t, { plan: 1 }) const agent = new Agent() - t.teardown(agent.close.bind(agent)) + after(() => agent.close()) const mockAgent = new MockAgent({ agent }) - t.equal(mockAgent[kAgent], agent) + t.strictEqual(mockAgent[kAgent], agent) }) }) -test('MockAgent - get', t => { - t.plan(3) - - t.test('should return MockClient', (t) => { - t.plan(1) +describe('MockAgent - get', t => { + test('should return MockClient', (t) => { + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) t.ok(mockClient instanceof MockClient) }) - t.test('should return MockPool', (t) => { - t.plan(1) + test('should return MockPool', (t) => { + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) t.ok(mockPool instanceof MockPool) }) - t.test('should return the same instance if already created', (t) => { - t.plan(1) + test('should return the same instance if already created', (t) => { + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool1 = mockAgent.get(baseUrl) const mockPool2 = mockAgent.get(baseUrl) - t.equal(mockPool1, mockPool2) + t.strictEqual(mockPool1, mockPool2) }) }) -test('MockAgent - dispatch', t => { - t.plan(3) - - t.test('should call the dispatch method of the MockPool', (t) => { - t.plan(1) +describe('MockAgent - dispatch', () => { + test('should call the dispatch method of the MockPool', (t) => { + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) @@ -121,13 +116,13 @@ test('MockAgent - dispatch', t => { })) }) - t.test('should call the dispatch method of the MockClient', (t) => { - t.plan(1) + test('should call the dispatch method of the MockClient', (t) => { + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) @@ -148,13 +143,13 @@ test('MockAgent - dispatch', t => { })) }) - t.test('should throw if handler is not valid on redirect', (t) => { - t.plan(7) + test('should throw if handler is not valid on redirect', (t) => { + t = tspl(t, { plan: 7 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) t.throws(() => mockAgent.dispatch({ origin: baseUrl, @@ -233,7 +228,7 @@ test('MockAgent - dispatch', t => { }) test('MockAgent - .close should clean up registered pools', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const baseUrl = 'http://localhost:9999' @@ -243,15 +238,15 @@ test('MockAgent - .close should clean up registered pools', async (t) => { const mockPool = mockAgent.get(baseUrl) t.ok(mockPool instanceof MockPool) - t.equal(mockPool[kConnected], 1) - t.equal(mockAgent[kClients].size, 1) + t.strictEqual(mockPool[kConnected], 1) + t.strictEqual(mockAgent[kClients].size, 1) await mockAgent.close() - t.equal(mockPool[kConnected], 0) - t.equal(mockAgent[kClients].size, 0) + t.strictEqual(mockPool[kConnected], 0) + t.strictEqual(mockAgent[kClients].size, 0) }) test('MockAgent - .close should clean up registered clients', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const baseUrl = 'http://localhost:9999' @@ -261,15 +256,15 @@ test('MockAgent - .close should clean up registered clients', async (t) => { const mockClient = mockAgent.get(baseUrl) t.ok(mockClient instanceof MockClient) - t.equal(mockClient[kConnected], 1) - t.equal(mockAgent[kClients].size, 1) + t.strictEqual(mockClient[kConnected], 1) + t.strictEqual(mockAgent[kClients].size, 1) await mockAgent.close() - t.equal(mockClient[kConnected], 0) - t.equal(mockAgent[kClients].size, 0) + t.strictEqual(mockClient[kConnected], 0) + t.strictEqual(mockAgent[kClients].size, 0) }) test('MockAgent - [kClients] should match encapsulated agent', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -277,14 +272,14 @@ test('MockAgent - [kClients] should match encapsulated agent', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const agent = new Agent() - t.teardown(agent.close.bind(agent)) + after(() => agent.close()) const mockAgent = new MockAgent({ agent }) @@ -295,11 +290,11 @@ test('MockAgent - [kClients] should match encapsulated agent', async (t) => { }).reply(200, 'hello') // The MockAgent should encapsulate the input agent clients - t.equal(mockAgent[kClients].size, agent[kClients].size) + t.strictEqual(mockAgent[kClients].size, agent[kClients].size) }) test('MockAgent - basic intercept with MockAgent.request', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -307,14 +302,14 @@ test('MockAgent - basic intercept with MockAgent.request', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -332,18 +327,18 @@ test('MockAgent - basic intercept with MockAgent.request', async (t) => { method: 'POST', body: 'form1=data1&form2=data2' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') - t.same(trailers, { 'content-md5': 'test' }) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) }) test('MockAgent - basic intercept with request', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -351,7 +346,7 @@ test('MockAgent - basic intercept with request', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -359,7 +354,7 @@ test('MockAgent - basic intercept with request', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -375,18 +370,18 @@ test('MockAgent - basic intercept with request', async (t) => { method: 'POST', body: 'form1=data1&form2=data2' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') - t.same(trailers, { 'content-md5': 'test' }) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) }) test('MockAgent - should support local agents', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -394,7 +389,7 @@ test('MockAgent - should support local agents', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -402,7 +397,7 @@ test('MockAgent - should support local agents', async (t) => { const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -421,18 +416,18 @@ test('MockAgent - should support local agents', async (t) => { body: 'form1=data1&form2=data2', dispatcher: mockAgent }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') - t.same(trailers, { 'content-md5': 'test' }) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) }) test('MockAgent - should support specifying custom agents to mock', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -440,14 +435,14 @@ test('MockAgent - should support specifying custom agents to mock', async (t) => t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const agent = new Agent() - t.teardown(agent.close.bind(agent)) + after(() => agent.close()) const mockAgent = new MockAgent({ agent }) setGlobalDispatcher(mockAgent) @@ -468,18 +463,18 @@ test('MockAgent - should support specifying custom agents to mock', async (t) => method: 'POST', body: 'form1=data1&form2=data2' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') - t.same(trailers, { 'content-md5': 'test' }) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) }) test('MockAgent - basic Client intercept with request', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -487,7 +482,7 @@ test('MockAgent - basic Client intercept with request', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -495,7 +490,7 @@ test('MockAgent - basic Client intercept with request', async (t) => { const mockAgent = new MockAgent({ connections: 1 }) setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) mockClient.intercept({ @@ -513,18 +508,18 @@ test('MockAgent - basic Client intercept with request', async (t) => { method: 'POST', body: 'form1=data1&form2=data2' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') - t.same(trailers, { 'content-md5': 'test' }) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) }) test('MockAgent - basic intercept with multiple pools', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -532,7 +527,7 @@ test('MockAgent - basic intercept with multiple pools', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -540,7 +535,7 @@ test('MockAgent - basic intercept with multiple pools', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool1 = mockAgent.get(baseUrl) const mockPool2 = mockAgent.get('http://localhost:9999') @@ -565,18 +560,18 @@ test('MockAgent - basic intercept with multiple pools', async (t) => { method: 'POST', body: 'form1=data1&form2=data2' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') - t.same(trailers, { 'content-md5': 'test' }) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar-1' }) }) test('MockAgent - should handle multiple responses for an interceptor', async (t) => { - t.plan(6) + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -584,7 +579,7 @@ test('MockAgent - should handle multiple responses for an interceptor', async (t t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -592,7 +587,7 @@ test('MockAgent - should handle multiple responses for an interceptor', async (t const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) @@ -615,11 +610,11 @@ test('MockAgent - should handle multiple responses for an interceptor', async (t const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'POST' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) } @@ -628,26 +623,26 @@ test('MockAgent - should handle multiple responses for an interceptor', async (t const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'POST' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { hello: 'there' }) } }) test('MockAgent - should call original Pool dispatch if request not found', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -655,28 +650,28 @@ test('MockAgent - should call original Pool dispatch if request not found', asyn const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') }) test('MockAgent - should call original Client dispatch if request not found', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -684,20 +679,20 @@ test('MockAgent - should call original Client dispatch if request not found', as const mockAgent = new MockAgent({ connections: 1 }) setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') }) test('MockAgent - should handle string responses', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -705,7 +700,7 @@ test('MockAgent - should handle string responses', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -713,7 +708,7 @@ test('MockAgent - should handle string responses', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -724,22 +719,20 @@ test('MockAgent - should handle string responses', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'POST' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') }) test('MockAgent - should handle basic concurrency for requests', { jobs: 5 }, async (t) => { - t.plan(5) - const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) await Promise.all([...Array(5).keys()].map(idx => - t.test(`concurrent job (${idx})`, async (innerTest) => { - innerTest.plan(2) + test(`concurrent job (${idx})`, async (t) => { + t = tspl(t, { plan: 2 }) const baseUrl = 'http://localhost:9999' @@ -752,10 +745,10 @@ test('MockAgent - should handle basic concurrency for requests', { jobs: 5 }, as const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'POST' }) - innerTest.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const jsonResponse = JSON.parse(await getResponse(body)) - innerTest.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: `bar ${idx}` }) }) @@ -763,7 +756,7 @@ test('MockAgent - should handle basic concurrency for requests', { jobs: 5 }, as }) test('MockAgent - handle delays to simulate work', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -771,7 +764,7 @@ test('MockAgent - handle delays to simulate work', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -779,7 +772,7 @@ test('MockAgent - handle delays to simulate work', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -792,16 +785,16 @@ test('MockAgent - handle delays to simulate work', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'POST' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') const elapsedInMs = process.hrtime(start)[1] / 1e6 t.ok(elapsedInMs >= 50, `Elapsed time is not greater than 50ms: ${elapsedInMs}`) }) test('MockAgent - should persist requests', async (t) => { - t.plan(8) + t = tspl(t, { plan: 8 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -809,7 +802,7 @@ test('MockAgent - should persist requests', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -817,7 +810,7 @@ test('MockAgent - should persist requests', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -836,12 +829,12 @@ test('MockAgent - should persist requests', async (t) => { method: 'POST', body: 'form1=data1&form2=data2' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') - t.same(trailers, { 'content-md5': 'test' }) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) } @@ -851,19 +844,19 @@ test('MockAgent - should persist requests', async (t) => { method: 'POST', body: 'form1=data1&form2=data2' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') - t.same(trailers, { 'content-md5': 'test' }) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) } }) test('MockAgent - handle persists with delayed requests', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -871,7 +864,7 @@ test('MockAgent - handle persists with delayed requests', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -879,7 +872,7 @@ test('MockAgent - handle persists with delayed requests', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -891,25 +884,25 @@ test('MockAgent - handle persists with delayed requests', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'POST' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') } { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'POST' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') } }) test('MockAgent - calling close on a mock pool should not affect other mock pools', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -917,7 +910,7 @@ test('MockAgent - calling close on a mock pool should not affect other mock pool t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -925,7 +918,7 @@ test('MockAgent - calling close on a mock pool should not affect other mock pool const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPoolToClose = mockAgent.get('http://localhost:9999') mockPoolToClose.intercept({ @@ -949,25 +942,25 @@ test('MockAgent - calling close on a mock pool should not affect other mock pool const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') } { const { statusCode, body } = await request(`${baseUrl}/bar`, { method: 'POST' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'bar') + t.strictEqual(response, 'bar') } }) test('MockAgent - close removes all registered mock clients', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -975,7 +968,7 @@ test('MockAgent - close removes all registered mock clients', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -991,7 +984,7 @@ test('MockAgent - close removes all registered mock clients', async (t) => { }).reply(200, 'foo') await mockAgent.close() - t.equal(mockAgent[kClients].size, 0) + t.strictEqual(mockAgent[kClients].size, 0) try { await request(`${baseUrl}/foo`, { method: 'GET' }) @@ -1001,7 +994,7 @@ test('MockAgent - close removes all registered mock clients', async (t) => { }) test('MockAgent - close removes all registered mock pools', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1009,7 +1002,7 @@ test('MockAgent - close removes all registered mock pools', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1025,7 +1018,7 @@ test('MockAgent - close removes all registered mock pools', async (t) => { }).reply(200, 'foo') await mockAgent.close() - t.equal(mockAgent[kClients].size, 0) + t.strictEqual(mockAgent[kClients].size, 0) try { await request(`${baseUrl}/foo`, { method: 'GET' }) @@ -1035,7 +1028,7 @@ test('MockAgent - close removes all registered mock pools', async (t) => { }) test('MockAgent - should handle replyWithError', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1043,7 +1036,7 @@ test('MockAgent - should handle replyWithError', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1051,7 +1044,7 @@ test('MockAgent - should handle replyWithError', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1063,15 +1056,15 @@ test('MockAgent - should handle replyWithError', async (t) => { }) test('MockAgent - should support setting a reply to respond a set amount of times', async (t) => { - t.plan(9) + t = tspl(t, { plan: 9 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1079,7 +1072,7 @@ test('MockAgent - should support setting a reply to respond a set amount of time const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1089,32 +1082,32 @@ test('MockAgent - should support setting a reply to respond a set amount of time { const { statusCode, body } = await request(`${baseUrl}/foo`) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') } { const { statusCode, body } = await request(`${baseUrl}/foo`) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') } { const { statusCode, headers, body } = await request(`${baseUrl}/foo`) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') } }) test('MockAgent - persist overrides times', async (t) => { - t.plan(6) + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1122,7 +1115,7 @@ test('MockAgent - persist overrides times', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1130,7 +1123,7 @@ test('MockAgent - persist overrides times', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1142,42 +1135,42 @@ test('MockAgent - persist overrides times', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') } { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') } { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') } }) test('MockAgent - matcher should not find mock dispatch if path is of unsupported type', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1185,7 +1178,7 @@ test('MockAgent - matcher should not find mock dispatch if path is of unsupporte const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1196,14 +1189,14 @@ test('MockAgent - matcher should not find mock dispatch if path is of unsupporte const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') }) test('MockAgent - should match path with regex', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1211,7 +1204,7 @@ test('MockAgent - should match path with regex', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1219,7 +1212,7 @@ test('MockAgent - should match path with regex', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1231,25 +1224,25 @@ test('MockAgent - should match path with regex', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') } { const { statusCode, body } = await request(`${baseUrl}/hello/foobar`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') } }) test('MockAgent - should match path with function', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1257,7 +1250,7 @@ test('MockAgent - should match path with function', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1265,7 +1258,7 @@ test('MockAgent - should match path with function', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1276,14 +1269,14 @@ test('MockAgent - should match path with function', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - should match method with regex', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1291,7 +1284,7 @@ test('MockAgent - should match method with regex', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1299,7 +1292,7 @@ test('MockAgent - should match method with regex', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1310,14 +1303,14 @@ test('MockAgent - should match method with regex', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - should match method with function', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1325,7 +1318,7 @@ test('MockAgent - should match method with function', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1333,7 +1326,7 @@ test('MockAgent - should match method with function', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1344,14 +1337,14 @@ test('MockAgent - should match method with function', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - should match body with regex', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1359,7 +1352,7 @@ test('MockAgent - should match body with regex', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1367,7 +1360,7 @@ test('MockAgent - should match body with regex', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1380,14 +1373,14 @@ test('MockAgent - should match body with regex', async (t) => { method: 'GET', body: 'hello=there' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - should match body with function', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1395,7 +1388,7 @@ test('MockAgent - should match body with function', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1403,7 +1396,7 @@ test('MockAgent - should match body with function', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1416,21 +1409,21 @@ test('MockAgent - should match body with function', async (t) => { method: 'GET', body: 'hello=there' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - should match headers with string', async (t) => { - t.plan(6) + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { res.end('should not be called') t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1438,7 +1431,7 @@ test('MockAgent - should match headers with string', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1489,21 +1482,21 @@ test('MockAgent - should match headers with string', async (t) => { Host: 'example.com' } }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - should match headers with regex', async (t) => { - t.plan(6) + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { res.end('should not be called') t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1511,7 +1504,7 @@ test('MockAgent - should match headers with regex', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1562,21 +1555,21 @@ test('MockAgent - should match headers with regex', async (t) => { Host: 'example.com' } }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - should match headers with function', async (t) => { - t.plan(6) + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { res.end('should not be called') t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1584,7 +1577,7 @@ test('MockAgent - should match headers with function', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1635,14 +1628,14 @@ test('MockAgent - should match headers with function', async (t) => { Host: 'example.com' } }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - should match url with regex', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1650,7 +1643,7 @@ test('MockAgent - should match url with regex', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1658,7 +1651,7 @@ test('MockAgent - should match url with regex', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(new RegExp(baseUrl)) mockPool.intercept({ @@ -1669,14 +1662,14 @@ test('MockAgent - should match url with regex', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - should match url with function', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1684,7 +1677,7 @@ test('MockAgent - should match url with function', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1692,7 +1685,7 @@ test('MockAgent - should match url with function', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get((value) => baseUrl === value) mockPool.intercept({ @@ -1703,14 +1696,14 @@ test('MockAgent - should match url with function', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - handle default reply headers', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1718,7 +1711,7 @@ test('MockAgent - handle default reply headers', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1726,7 +1719,7 @@ test('MockAgent - handle default reply headers', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1737,18 +1730,18 @@ test('MockAgent - handle default reply headers', async (t) => { const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.same(headers, { + t.strictEqual(statusCode, 200) + t.deepStrictEqual(headers, { foo: 'bar', hello: 'there' }) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - handle default reply trailers', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1756,7 +1749,7 @@ test('MockAgent - handle default reply trailers', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1764,7 +1757,7 @@ test('MockAgent - handle default reply trailers', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1775,18 +1768,18 @@ test('MockAgent - handle default reply trailers', async (t) => { const { statusCode, trailers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.same(trailers, { + t.strictEqual(statusCode, 200) + t.deepStrictEqual(trailers, { foo: 'bar', hello: 'there' }) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - return calculated content-length if specified', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1794,7 +1787,7 @@ test('MockAgent - return calculated content-length if specified', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1802,7 +1795,7 @@ test('MockAgent - return calculated content-length if specified', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1813,18 +1806,18 @@ test('MockAgent - return calculated content-length if specified', async (t) => { const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.same(headers, { + t.strictEqual(statusCode, 200) + t.deepStrictEqual(headers, { hello: 'there', - 'content-length': 3 + 'content-length': '3' }) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') }) test('MockAgent - return calculated content-length for object response if specified', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -1832,7 +1825,7 @@ test('MockAgent - return calculated content-length for object response if specif t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1840,7 +1833,7 @@ test('MockAgent - return calculated content-length for object response if specif const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1851,26 +1844,26 @@ test('MockAgent - return calculated content-length for object response if specif const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.same(headers, { + t.strictEqual(statusCode, 200) + t.deepStrictEqual(headers, { hello: 'there', - 'content-length': 13 + 'content-length': '13' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { foo: 'bar' }) + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) }) test('MockAgent - should activate and deactivate mock clients', async (t) => { - t.plan(9) + t = tspl(t, { plan: 9 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1878,7 +1871,7 @@ test('MockAgent - should activate and deactivate mock clients', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1890,10 +1883,10 @@ test('MockAgent - should activate and deactivate mock clients', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') } mockAgent.deactivate() @@ -1902,11 +1895,11 @@ test('MockAgent - should activate and deactivate mock clients', async (t) => { const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') } mockAgent.activate() @@ -1915,23 +1908,23 @@ test('MockAgent - should activate and deactivate mock clients', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.equal(response, 'foo') + t.strictEqual(response, 'foo') } }) test('MockAgent - enableNetConnect should allow all original dispatches to be called if dispatch not found', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1939,7 +1932,7 @@ test('MockAgent - enableNetConnect should allow all original dispatches to be ca const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1952,23 +1945,23 @@ test('MockAgent - enableNetConnect should allow all original dispatches to be ca const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') }) test('MockAgent - enableNetConnect with a host string should allow all original dispatches to be called if mockDispatch not found', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -1976,7 +1969,7 @@ test('MockAgent - enableNetConnect with a host string should allow all original const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -1989,23 +1982,23 @@ test('MockAgent - enableNetConnect with a host string should allow all original const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') }) test('MockAgent - enableNetConnect when called with host string multiple times should allow all original dispatches to be called if mockDispatch not found', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2013,7 +2006,7 @@ test('MockAgent - enableNetConnect when called with host string multiple times s const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -2027,23 +2020,23 @@ test('MockAgent - enableNetConnect when called with host string multiple times s const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') }) test('MockAgent - enableNetConnect with a host regex should allow all original dispatches to be called if mockDispatch not found', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2051,7 +2044,7 @@ test('MockAgent - enableNetConnect with a host regex should allow all original d const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -2064,23 +2057,23 @@ test('MockAgent - enableNetConnect with a host regex should allow all original d const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') }) test('MockAgent - enableNetConnect with a function should allow all original dispatches to be called if mockDispatch not found', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2088,7 +2081,7 @@ test('MockAgent - enableNetConnect with a function should allow all original dis const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -2101,19 +2094,19 @@ test('MockAgent - enableNetConnect with a function should allow all original dis const { statusCode, headers, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const response = await getResponse(body) - t.equal(response, 'hello') + t.strictEqual(response, 'hello') }) test('MockAgent - enableNetConnect with an unknown input should throw', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get('http://localhost:9999') mockPool.intercept({ @@ -2125,14 +2118,14 @@ test('MockAgent - enableNetConnect with an unknown input should throw', async (t }) test('MockAgent - enableNetConnect should throw if dispatch not matched for path and the origin was not allowed by net connect', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { t.fail('should not be called') t.end() res.end('should not be called') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2140,7 +2133,7 @@ test('MockAgent - enableNetConnect should throw if dispatch not matched for path const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -2156,14 +2149,14 @@ test('MockAgent - enableNetConnect should throw if dispatch not matched for path }) test('MockAgent - enableNetConnect should throw if dispatch not matched for method and the origin was not allowed by net connect', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { t.fail('should not be called') t.end() res.end('should not be called') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2171,7 +2164,7 @@ test('MockAgent - enableNetConnect should throw if dispatch not matched for meth const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -2187,14 +2180,14 @@ test('MockAgent - enableNetConnect should throw if dispatch not matched for meth }) test('MockAgent - enableNetConnect should throw if dispatch not matched for body and the origin was not allowed by net connect', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { t.fail('should not be called') t.end() res.end('should not be called') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2202,7 +2195,7 @@ test('MockAgent - enableNetConnect should throw if dispatch not matched for body const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -2220,14 +2213,14 @@ test('MockAgent - enableNetConnect should throw if dispatch not matched for body }) test('MockAgent - enableNetConnect should throw if dispatch not matched for headers and the origin was not allowed by net connect', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { t.fail('should not be called') t.end() res.end('should not be called') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2235,7 +2228,7 @@ test('MockAgent - enableNetConnect should throw if dispatch not matched for head const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -2257,15 +2250,15 @@ test('MockAgent - enableNetConnect should throw if dispatch not matched for head }) test('MockAgent - disableNetConnect should throw if dispatch not found by net connect', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { - t.equal(req.url, '/foo') - t.equal(req.method, 'GET') + t.strictEqual(req.url, '/foo') + t.strictEqual(req.method, 'GET') res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2273,7 +2266,7 @@ test('MockAgent - disableNetConnect should throw if dispatch not found by net co const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ @@ -2289,14 +2282,14 @@ test('MockAgent - disableNetConnect should throw if dispatch not found by net co }) test('MockAgent - headers function interceptor', async (t) => { - t.plan(7) + t = tspl(t, { plan: 7 }) const server = createServer((req, res) => { t.fail('should not be called') t.end() res.end('should not be called') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2304,7 +2297,7 @@ test('MockAgent - headers function interceptor', async (t) => { const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) // Disable net connect so we can make sure it matches properly @@ -2314,7 +2307,7 @@ test('MockAgent - headers function interceptor', async (t) => { path: '/foo', method: 'GET', headers (headers) { - t.equal(typeof headers, 'object') + t.strictEqual(typeof headers, 'object') return !Object.keys(headers).includes('authorization') } }).reply(200, 'foo').times(2) @@ -2333,27 +2326,27 @@ test('MockAgent - headers function interceptor', async (t) => { foo: 'bar' } }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) } { const { statusCode } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) } }) test('MockAgent - clients are not garbage collected', async (t) => { const samples = 250 - t.plan(2) + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { t.fail('should not be called') t.end() res.end('should not be called') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2394,16 +2387,18 @@ test('MockAgent - clients are not garbage collected', async (t) => { results.add(statusCode) } - t.equal(results.size, 1) + t.strictEqual(results.size, 1) t.ok(results.has(200)) }) // https://github.com/nodejs/undici/issues/1321 test('MockAgent - using fetch yields correct statusText', async (t) => { + t = tspl(t, { plan: 4 }) + const mockAgent = new MockAgent() mockAgent.disableNetConnect() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get('http://localhost:3000') @@ -2414,8 +2409,8 @@ test('MockAgent - using fetch yields correct statusText', async (t) => { const { status, statusText } = await fetch('http://localhost:3000/statusText') - t.equal(status, 200) - t.equal(statusText, 'OK') + t.strictEqual(status, 200) + t.strictEqual(statusText, 'OK') mockPool.intercept({ path: '/unknownStatusText', @@ -2423,17 +2418,19 @@ test('MockAgent - using fetch yields correct statusText', async (t) => { }).reply(420, 'Everyday') const unknownStatusCodeRes = await fetch('http://localhost:3000/unknownStatusText') - t.equal(unknownStatusCodeRes.status, 420) - t.equal(unknownStatusCodeRes.statusText, 'unknown') + t.strictEqual(unknownStatusCodeRes.status, 420) + t.strictEqual(unknownStatusCodeRes.statusText, 'unknown') t.end() }) // https://github.com/nodejs/undici/issues/1556 test('MockAgent - using fetch yields a headers object in the reply callback', async (t) => { + t = tspl(t, { plan: 1 }) + const mockAgent = new MockAgent() mockAgent.disableNetConnect() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get('http://localhost:3000') @@ -2441,7 +2438,7 @@ test('MockAgent - using fetch yields a headers object in the reply callback', as path: '/headers', method: 'GET' }).reply(200, (opts) => { - t.same(opts.headers, { + t.deepStrictEqual(opts.headers, { accept: '*/*', 'accept-language': '*', 'sec-fetch-mode': 'cors', @@ -2456,15 +2453,17 @@ test('MockAgent - using fetch yields a headers object in the reply callback', as dispatcher: mockAgent }) - t.end() + await t.completed }) // https://github.com/nodejs/undici/issues/1579 test('MockAgent - headers in mock dispatcher intercept should be case-insensitive', async (t) => { + t = tspl(t, { plan: 1 }) + const mockAgent = new MockAgent() mockAgent.disableNetConnect() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get('https://example.com') @@ -2485,11 +2484,15 @@ test('MockAgent - headers in mock dispatcher intercept should be case-insensitiv } }) - t.end() + t.ok(true, 'end') + + await t.completed }) // https://github.com/nodejs/undici/issues/1757 test('MockAgent - reply callback can be asynchronous', async (t) => { + t = tspl(t, { plan: 2 }) + class MiniflareDispatcher extends Dispatcher { constructor (inner, options) { super(options) @@ -2514,7 +2517,7 @@ test('MockAgent - reply callback can be asynchronous', async (t) => { mockAgent.disableNetConnect() setGlobalDispatcher(new MiniflareDispatcher(mockAgent)) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) mockClient.intercept({ path: () => true, @@ -2538,7 +2541,7 @@ test('MockAgent - reply callback can be asynchronous', async (t) => { body: JSON.stringify({ foo: 'bar' }) }) - t.same(await response.json(), { foo: 'bar' }) + t.deepStrictEqual(await response.json(), { foo: 'bar' }) } { @@ -2557,11 +2560,13 @@ test('MockAgent - reply callback can be asynchronous', async (t) => { duplex: 'half' }) - t.same(await response.json(), { foo: 'bar' }) + t.deepStrictEqual(await response.json(), { foo: 'bar' }) } }) test('MockAgent - headers should be array of strings', async (t) => { + t = tspl(t, { plan: 1 }) + const mockAgent = new MockAgent() mockAgent.disableNetConnect() setGlobalDispatcher(mockAgent) @@ -2585,7 +2590,7 @@ test('MockAgent - headers should be array of strings', async (t) => { method: 'GET' }) - t.same(headers['set-cookie'], [ + t.deepStrictEqual(headers['set-cookie'], [ 'foo=bar', 'bar=baz', 'baz=qux' @@ -2594,7 +2599,7 @@ test('MockAgent - headers should be array of strings', async (t) => { // https://github.com/nodejs/undici/issues/2418 test('MockAgent - Sending ReadableStream body', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent() setGlobalDispatcher(mockAgent) @@ -2604,8 +2609,8 @@ test('MockAgent - Sending ReadableStream body', async (t) => { req.pipe(res) }) - t.teardown(mockAgent.close.bind(mockAgent)) - t.teardown(server.close.bind(server)) + after(() => mockAgent.close()) + after(() => server.close()) await promisify(server.listen.bind(server))(0) @@ -2622,18 +2627,18 @@ test('MockAgent - Sending ReadableStream body', async (t) => { duplex: 'half' }) - t.same(await response.text(), 'test') + t.deepStrictEqual(await response.text(), 'test') }) // https://github.com/nodejs/undici/issues/2616 test('MockAgent - headers should be array of strings (fetch)', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent() mockAgent.disableNetConnect() setGlobalDispatcher(mockAgent) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get('http://localhost:3000') @@ -2652,5 +2657,5 @@ test('MockAgent - headers should be array of strings (fetch)', async (t) => { method: 'GET' }) - t.same(response.headers.getSetCookie(), ['foo=bar', 'bar=baz', 'baz=qux']) + t.deepStrictEqual(response.headers.getSetCookie(), ['foo=bar', 'bar=baz', 'baz=qux']) }) diff --git a/test/mock-client.js b/test/mock-client.js index 9622977cf1e..ef6721b42be 100644 --- a/test/mock-client.js +++ b/test/mock-client.js @@ -1,6 +1,7 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after, describe } = require('node:test') const { createServer } = require('node:http') const { promisify } = require('node:util') const { MockAgent, MockClient, setGlobalDispatcher, request } = require('..') @@ -11,37 +12,33 @@ const { MockInterceptor } = require('../lib/mock/mock-interceptor') const { getResponse } = require('../lib/mock/mock-utils') const Dispatcher = require('../lib/dispatcher') -test('MockClient - constructor', t => { - t.plan(3) - - t.test('fails if opts.agent does not implement `get` method', t => { - t.plan(1) +describe('MockClient - constructor', () => { + test('fails if opts.agent does not implement `get` method', t => { + t = tspl(t, { plan: 1 }) t.throws(() => new MockClient('http://localhost:9999', { agent: { get: 'not a function' } }), InvalidArgumentError) }) - t.test('sets agent', t => { - t.plan(1) + test('sets agent', t => { + t = tspl(t, { plan: 1 }) t.doesNotThrow(() => new MockClient('http://localhost:9999', { agent: new MockAgent({ connections: 1 }) })) }) - t.test('should implement the Dispatcher API', t => { - t.plan(1) + test('should implement the Dispatcher API', t => { + t = tspl(t, { plan: 1 }) const mockClient = new MockClient('http://localhost:9999', { agent: new MockAgent({ connections: 1 }) }) t.ok(mockClient instanceof Dispatcher) }) }) -test('MockClient - dispatch', t => { - t.plan(2) - - t.test('should handle a single interceptor', (t) => { - t.plan(1) +describe('MockClient - dispatch', () => { + test('should handle a single interceptor', (t) => { + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) @@ -70,13 +67,13 @@ test('MockClient - dispatch', t => { })) }) - t.test('should directly throw error from mockDispatch function if error is not a MockNotMatchedError', (t) => { - t.plan(1) + test('should directly throw error from mockDispatch function if error is not a MockNotMatchedError', (t) => { + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) @@ -107,12 +104,12 @@ test('MockClient - dispatch', t => { }) test('MockClient - intercept should return a MockInterceptor', (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) @@ -124,62 +121,60 @@ test('MockClient - intercept should return a MockInterceptor', (t) => { t.ok(interceptor instanceof MockInterceptor) }) -test('MockClient - intercept validation', (t) => { - t.plan(4) - - t.test('it should error if no options specified in the intercept', t => { - t.plan(1) +describe('MockClient - intercept validation', () => { + test('it should error if no options specified in the intercept', t => { + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get('http://localhost:9999') t.throws(() => mockClient.intercept(), new InvalidArgumentError('opts must be an object')) }) - t.test('it should error if no path specified in the intercept', t => { - t.plan(1) + test('it should error if no path specified in the intercept', t => { + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get('http://localhost:9999') t.throws(() => mockClient.intercept({}), new InvalidArgumentError('opts.path must be defined')) }) - t.test('it should default to GET if no method specified in the intercept', t => { - t.plan(1) + test('it should default to GET if no method specified in the intercept', t => { + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get('http://localhost:9999') t.doesNotThrow(() => mockClient.intercept({ path: '/foo' })) }) - t.test('it should uppercase the method - https://github.com/nodejs/undici/issues/1320', t => { - t.plan(1) + test('it should uppercase the method - https://github.com/nodejs/undici/issues/1320', t => { + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent() const mockClient = mockAgent.get('http://localhost:3000') - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) mockClient.intercept({ path: '/test', method: 'patch' }).reply(200, 'Hello!') - t.equal(mockClient[kDispatches][0].method, 'PATCH') + t.strictEqual(mockClient[kDispatches][0].method, 'PATCH') }) }) test('MockClient - close should run without error', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) mockClient[kDispatches] = [ @@ -196,11 +191,12 @@ test('MockClient - close should run without error', async (t) => { } ] - await t.resolves(mockClient.close()) + await mockClient.close() + t.ok(true, 'pass') }) test('MockClient - should be able to set as globalDispatcher', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -208,14 +204,14 @@ test('MockClient - should be able to set as globalDispatcher', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) t.ok(mockClient instanceof MockClient) @@ -229,14 +225,14 @@ test('MockClient - should be able to set as globalDispatcher', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.same(response, 'hello') + t.deepStrictEqual(response, 'hello') }) test('MockClient - should support query params', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -244,14 +240,14 @@ test('MockClient - should support query params', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) t.ok(mockClient instanceof MockClient) @@ -270,14 +266,14 @@ test('MockClient - should support query params', async (t) => { method: 'GET', query }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.same(response, 'hello') + t.deepStrictEqual(response, 'hello') }) test('MockClient - should intercept query params with hardcoded path', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -285,14 +281,14 @@ test('MockClient - should intercept query params with hardcoded path', async (t) t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) t.ok(mockClient instanceof MockClient) @@ -310,14 +306,14 @@ test('MockClient - should intercept query params with hardcoded path', async (t) method: 'GET', query }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.same(response, 'hello') + t.deepStrictEqual(response, 'hello') }) test('MockClient - should intercept query params regardless of key ordering', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -325,14 +321,14 @@ test('MockClient - should intercept query params regardless of key ordering', as t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) t.ok(mockClient instanceof MockClient) @@ -358,14 +354,14 @@ test('MockClient - should intercept query params regardless of key ordering', as method: 'GET', query }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.same(response, 'hello') + t.deepStrictEqual(response, 'hello') }) test('MockClient - should be able to use as a local dispatcher', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -373,14 +369,14 @@ test('MockClient - should be able to use as a local dispatcher', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) t.ok(mockClient instanceof MockClient) @@ -394,14 +390,14 @@ test('MockClient - should be able to use as a local dispatcher', async (t) => { method: 'GET', dispatcher: mockClient }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.same(response, 'hello') + t.deepStrictEqual(response, 'hello') }) test('MockClient - basic intercept with MockClient.request', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -409,14 +405,14 @@ test('MockClient - basic intercept with MockClient.request', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const mockAgent = new MockAgent({ connections: 1 }) - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockClient = mockAgent.get(baseUrl) t.ok(mockClient instanceof MockClient) @@ -435,12 +431,12 @@ test('MockClient - basic intercept with MockClient.request', async (t) => { method: 'POST', body: 'form1=data1&form2=data2' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') - t.same(trailers, { 'content-md5': 'test' }) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) }) diff --git a/test/mock-errors.js b/test/mock-errors.js index 1087f0cf588..58ec2b52b9f 100644 --- a/test/mock-errors.js +++ b/test/mock-errors.js @@ -1,32 +1,27 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { describe, test } = require('node:test') const { mockErrors, errors } = require('..') -test('mockErrors', (t) => { - t.plan(1) +describe('MockNotMatchedError', () => { + test('should implement an UndiciError', t => { + t = tspl(t, { plan: 4 }) - t.test('MockNotMatchedError', t => { - t.plan(2) - - t.test('should implement an UndiciError', t => { - t.plan(4) - - const mockError = new mockErrors.MockNotMatchedError() - t.ok(mockError instanceof errors.UndiciError) - t.same(mockError.name, 'MockNotMatchedError') - t.same(mockError.code, 'UND_MOCK_ERR_MOCK_NOT_MATCHED') - t.same(mockError.message, 'The request does not match any registered mock dispatches') - }) + const mockError = new mockErrors.MockNotMatchedError() + t.ok(mockError instanceof errors.UndiciError) + t.deepStrictEqual(mockError.name, 'MockNotMatchedError') + t.deepStrictEqual(mockError.code, 'UND_MOCK_ERR_MOCK_NOT_MATCHED') + t.deepStrictEqual(mockError.message, 'The request does not match any registered mock dispatches') + }) - t.test('should set a custom message', t => { - t.plan(4) + test('should set a custom message', t => { + t = tspl(t, { plan: 4 }) - const mockError = new mockErrors.MockNotMatchedError('custom message') - t.ok(mockError instanceof errors.UndiciError) - t.same(mockError.name, 'MockNotMatchedError') - t.same(mockError.code, 'UND_MOCK_ERR_MOCK_NOT_MATCHED') - t.same(mockError.message, 'custom message') - }) + const mockError = new mockErrors.MockNotMatchedError('custom message') + t.ok(mockError instanceof errors.UndiciError) + t.deepStrictEqual(mockError.name, 'MockNotMatchedError') + t.deepStrictEqual(mockError.code, 'UND_MOCK_ERR_MOCK_NOT_MATCHED') + t.deepStrictEqual(mockError.message, 'custom message') }) }) diff --git a/test/mock-interceptor-unused-assertions.js b/test/mock-interceptor-unused-assertions.js index 2fe8b824f9f..e6f5360a3f9 100644 --- a/test/mock-interceptor-unused-assertions.js +++ b/test/mock-interceptor-unused-assertions.js @@ -1,6 +1,7 @@ 'use strict' -const { test, beforeEach, afterEach } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, beforeEach, afterEach } = require('node:test') const { MockAgent, setGlobalDispatcher } = require('..') const PendingInterceptorsFormatter = require('../lib/mock/pending-interceptors-formatter') const util = require('../lib/core/util') @@ -41,12 +42,14 @@ function mockAgentWithOneInterceptor () { } test('1 pending interceptor', t => { - t.plan(2) - - const err = t.throws(() => mockAgentWithOneInterceptor().assertNoPendingInterceptors({ pendingInterceptorsFormatter })) - - t.same(err.message, tableRowsAlignedToLeft - ? ` + t = tspl(t, { plan: 1 }) + + try { + mockAgentWithOneInterceptor().assertNoPendingInterceptors({ pendingInterceptorsFormatter }) + t.fail('Should have thrown') + } catch (err) { + t.deepStrictEqual(err.message, tableRowsAlignedToLeft + ? ` 1 interceptor is pending: ┌─────────┬────────┬───────────────────────┬──────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -55,7 +58,7 @@ test('1 pending interceptor', t => { │ 0 │ 'GET' │ 'https://example.com' │ '/' │ 200 │ '❌' │ 0 │ 1 │ └─────────┴────────┴───────────────────────┴──────┴─────────────┴────────────┴─────────────┴───────────┘ `.trim() - : ` + : ` 1 interceptor is pending: ┌─────────┬────────┬───────────────────────┬──────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -64,20 +67,22 @@ test('1 pending interceptor', t => { │ 0 │ 'GET' │ 'https://example.com' │ '/' │ 200 │ '❌' │ 0 │ 1 │ └─────────┴────────┴───────────────────────┴──────┴─────────────┴────────────┴─────────────┴───────────┘ `.trim()) + } }) test('2 pending interceptors', t => { - t.plan(2) + t = tspl(t, { plan: 1 }) const withTwoInterceptors = mockAgentWithOneInterceptor() withTwoInterceptors .get(origin) .intercept({ method: 'get', path: '/some/path' }) .reply(204, 'OK') - const err = t.throws(() => withTwoInterceptors.assertNoPendingInterceptors({ pendingInterceptorsFormatter })) - - t.same(err.message, tableRowsAlignedToLeft - ? ` + try { + withTwoInterceptors.assertNoPendingInterceptors({ pendingInterceptorsFormatter }) + } catch (err) { + t.deepStrictEqual(err.message, tableRowsAlignedToLeft + ? ` 2 interceptors are pending: ┌─────────┬────────┬──────────────────────────┬──────────────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -87,7 +92,7 @@ test('2 pending interceptors', t => { │ 1 │ 'GET' │ 'https://localhost:9999' │ '/some/path' │ 204 │ '❌' │ 0 │ 1 │ └─────────┴────────┴──────────────────────────┴──────────────┴─────────────┴────────────┴─────────────┴───────────┘ `.trim() - : ` + : ` 2 interceptors are pending: ┌─────────┬────────┬──────────────────────────┬──────────────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -97,10 +102,11 @@ test('2 pending interceptors', t => { │ 1 │ 'GET' │ 'https://localhost:9999' │ '/some/path' │ 204 │ '❌' │ 0 │ 1 │ └─────────┴────────┴──────────────────────────┴──────────────┴─────────────┴────────────┴─────────────┴───────────┘ `.trim()) + } }) test('Variations of persist(), times(), and pending status', async t => { - t.plan(7) + t = tspl(t, { plan: 6 }) // Agent with unused interceptor const agent = mockAgentWithOneInterceptor() @@ -118,20 +124,20 @@ test('Variations of persist(), times(), and pending status', async t => { .intercept({ method: 'GET', path: '/persistent/used' }) .reply(200, 'OK') .persist() - t.same((await agent.request({ origin, method: 'GET', path: '/persistent/used' })).statusCode, 200) + t.deepStrictEqual((await agent.request({ origin, method: 'GET', path: '/persistent/used' })).statusCode, 200) // Consumed without persist() agent.get(origin) .intercept({ method: 'post', path: '/transient/pending' }) .reply(201, 'Created') - t.same((await agent.request({ origin, method: 'POST', path: '/transient/pending' })).statusCode, 201) + t.deepStrictEqual((await agent.request({ origin, method: 'POST', path: '/transient/pending' })).statusCode, 201) // Partially pending with times() agent.get(origin) .intercept({ method: 'get', path: '/times/partial' }) .reply(200, 'OK') .times(5) - t.same((await agent.request({ origin, method: 'GET', path: '/times/partial' })).statusCode, 200) + t.deepStrictEqual((await agent.request({ origin, method: 'GET', path: '/times/partial' })).statusCode, 200) // Unused with times() agent.get(origin) @@ -144,13 +150,15 @@ test('Variations of persist(), times(), and pending status', async t => { .intercept({ method: 'get', path: '/times/pending' }) .reply(200, 'OK') .times(2) - t.same((await agent.request({ origin, method: 'GET', path: '/times/pending' })).statusCode, 200) - t.same((await agent.request({ origin, method: 'GET', path: '/times/pending' })).statusCode, 200) - - const err = t.throws(() => agent.assertNoPendingInterceptors({ pendingInterceptorsFormatter })) - - t.same(err.message, tableRowsAlignedToLeft - ? ` + t.deepStrictEqual((await agent.request({ origin, method: 'GET', path: '/times/pending' })).statusCode, 200) + t.deepStrictEqual((await agent.request({ origin, method: 'GET', path: '/times/pending' })).statusCode, 200) + + try { + agent.assertNoPendingInterceptors({ pendingInterceptorsFormatter }) + t.fail('Should have thrown') + } catch (err) { + t.deepStrictEqual(err.message, tableRowsAlignedToLeft + ? ` 4 interceptors are pending: ┌─────────┬────────┬──────────────────────────┬──────────────────────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -162,7 +170,7 @@ test('Variations of persist(), times(), and pending status', async t => { │ 3 │ 'GET' │ 'https://localhost:9999' │ '/times/unused' │ 200 │ '❌' │ 0 │ 2 │ └─────────┴────────┴──────────────────────────┴──────────────────────┴─────────────┴────────────┴─────────────┴───────────┘ `.trim() - : ` + : ` 4 interceptors are pending: ┌─────────┬────────┬──────────────────────────┬──────────────────────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -174,45 +182,48 @@ test('Variations of persist(), times(), and pending status', async t => { │ 3 │ 'GET' │ 'https://localhost:9999' │ '/times/unused' │ 200 │ '❌' │ 0 │ 2 │ └─────────┴────────┴──────────────────────────┴──────────────────────┴─────────────┴────────────┴─────────────┴───────────┘ `.trim()) + } }) test('works when no interceptors are registered', t => { - t.plan(2) + t = tspl(t, { plan: 2 }) const agent = new MockAgent() agent.disableNetConnect() - t.same(agent.pendingInterceptors(), []) + t.deepStrictEqual(agent.pendingInterceptors(), []) t.doesNotThrow(() => agent.assertNoPendingInterceptors()) }) test('works when all interceptors are pending', async t => { - t.plan(4) + t = tspl(t, { plan: 4 }) const agent = new MockAgent() agent.disableNetConnect() agent.get(origin).intercept({ method: 'get', path: '/' }).reply(200, 'OK') - t.same((await agent.request({ origin, method: 'GET', path: '/' })).statusCode, 200) + t.deepStrictEqual((await agent.request({ origin, method: 'GET', path: '/' })).statusCode, 200) agent.get(origin).intercept({ method: 'get', path: '/persistent' }).reply(200, 'OK') - t.same((await agent.request({ origin, method: 'GET', path: '/persistent' })).statusCode, 200) + t.deepStrictEqual((await agent.request({ origin, method: 'GET', path: '/persistent' })).statusCode, 200) - t.same(agent.pendingInterceptors(), []) + t.deepStrictEqual(agent.pendingInterceptors(), []) t.doesNotThrow(() => agent.assertNoPendingInterceptors()) }) test('defaults to rendering output with terminal color when process.env.CI is unset', t => { - t.plan(2) + t = tspl(t, { plan: 1 }) // This ensures that the test works in an environment where the CI env var is set. const oldCiEnvVar = process.env.CI delete process.env.CI - const err = t.throws( - () => mockAgentWithOneInterceptor().assertNoPendingInterceptors()) - t.same(err.message, tableRowsAlignedToLeft - ? ` + try { + mockAgentWithOneInterceptor().assertNoPendingInterceptors() + t.fail('Shoudl have thrown') + } catch (err) { + t.deepStrictEqual(err.message, tableRowsAlignedToLeft + ? ` 1 interceptor is pending: ┌─────────┬────────┬───────────────────────┬──────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -221,7 +232,7 @@ test('defaults to rendering output with terminal color when process.env.CI is un │ 0 │ \u001b[32m'GET'\u001b[39m │ \u001b[32m'https://example.com'\u001b[39m │ \u001b[32m'/'\u001b[39m │ \u001b[33m200\u001b[39m │ \u001b[32m'❌'\u001b[39m │ \u001b[33m0\u001b[39m │ \u001b[33m1\u001b[39m │ └─────────┴────────┴───────────────────────┴──────┴─────────────┴────────────┴─────────────┴───────────┘ `.trim() - : ` + : ` 1 interceptor is pending: ┌─────────┬────────┬───────────────────────┬──────┬─────────────┬────────────┬─────────────┬───────────┐ @@ -231,19 +242,20 @@ test('defaults to rendering output with terminal color when process.env.CI is un └─────────┴────────┴───────────────────────┴──────┴─────────────┴────────────┴─────────────┴───────────┘ `.trim()) - // Re-set the CI env var if it were set. - // Assigning `undefined` does not work, - // because reading the env var afterwards yields the string 'undefined', - // so we need to re-set it conditionally. - if (oldCiEnvVar != null) { - process.env.CI = oldCiEnvVar + // Re-set the CI env var if it were set. + // Assigning `undefined` does not work, + // because reading the env var afterwards yields the string 'undefined', + // so we need to re-set it conditionally. + if (oldCiEnvVar != null) { + process.env.CI = oldCiEnvVar + } } }) test('returns unused interceptors', t => { - t.plan(1) + t = tspl(t, { plan: 1 }) - t.same(mockAgentWithOneInterceptor().pendingInterceptors(), [ + t.deepStrictEqual(mockAgentWithOneInterceptor().pendingInterceptors(), [ { timesInvoked: 0, times: 1, diff --git a/test/mock-interceptor.js b/test/mock-interceptor.js index 787878395f4..036ea69df98 100644 --- a/test/mock-interceptor.js +++ b/test/mock-interceptor.js @@ -1,28 +1,26 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { describe, test, after } = require('node:test') const { MockInterceptor, MockScope } = require('../lib/mock/mock-interceptor') const MockAgent = require('../lib/mock/mock-agent') const { kDispatchKey } = require('../lib/mock/mock-symbols') const { InvalidArgumentError } = require('../lib/core/errors') -test('MockInterceptor - path', t => { - t.plan(1) - t.test('should remove hash fragment from paths', t => { - t.plan(1) +describe('MockInterceptor - path', () => { + test('should remove hash fragment from paths', t => { + t = tspl(t, { plan: 1 }) const mockInterceptor = new MockInterceptor({ path: '#foobar', method: '' }, []) - t.equal(mockInterceptor[kDispatchKey].path, '') + t.strictEqual(mockInterceptor[kDispatchKey].path, '') }) }) -test('MockInterceptor - reply', t => { - t.plan(2) - - t.test('should return MockScope', t => { - t.plan(1) +describe('MockInterceptor - reply', () => { + test('should return MockScope', t => { + t = tspl(t, { plan: 1 }) const mockInterceptor = new MockInterceptor({ path: '', method: '' @@ -31,8 +29,8 @@ test('MockInterceptor - reply', t => { t.ok(result instanceof MockScope) }) - t.test('should error if passed options invalid', t => { - t.plan(2) + test('should error if passed options invalid', t => { + t = tspl(t, { plan: 2 }) const mockInterceptor = new MockInterceptor({ path: '', @@ -43,11 +41,9 @@ test('MockInterceptor - reply', t => { }) }) -test('MockInterceptor - reply callback', t => { - t.plan(2) - - t.test('should return MockScope', t => { - t.plan(1) +describe('MockInterceptor - reply callback', () => { + test('should return MockScope', t => { + t = tspl(t, { plan: 1 }) const mockInterceptor = new MockInterceptor({ path: '', method: '' @@ -56,23 +52,21 @@ test('MockInterceptor - reply callback', t => { t.ok(result instanceof MockScope) }) - t.test('should error if passed options invalid', t => { - t.plan(2) + test('should error if passed options invalid', t => { + t = tspl(t, { plan: 2 }) const mockInterceptor = new MockInterceptor({ path: '', method: '' }, []) t.throws(() => mockInterceptor.reply(), new InvalidArgumentError('statusCode must be defined')) - t.throws(() => mockInterceptor.reply(200, () => {}, 'hello'), new InvalidArgumentError('responseOptions must be an object')) + t.throws(() => mockInterceptor.reply(200, () => { }, 'hello'), new InvalidArgumentError('responseOptions must be an object')) }) }) -test('MockInterceptor - reply options callback', t => { - t.plan(2) - - t.test('should return MockScope', t => { - t.plan(2) +describe('MockInterceptor - reply options callback', () => { + test('should return MockScope', t => { + t = tspl(t, { plan: 2 }) const mockInterceptor = new MockInterceptor({ path: '', @@ -88,7 +82,7 @@ test('MockInterceptor - reply options callback', t => { const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) @@ -96,7 +90,7 @@ test('MockInterceptor - reply options callback', t => { path: '/test', method: 'GET' }).reply((options) => { - t.strictSame(options, { path: '/test', method: 'GET', headers: { foo: 'bar' } }) + t.deepStrictEqual(options, { path: '/test', method: 'GET', headers: { foo: 'bar' } }) return { statusCode: 200, data: 'hello' } }) @@ -105,25 +99,25 @@ test('MockInterceptor - reply options callback', t => { method: 'GET', headers: { foo: 'bar' } }, { - onHeaders: () => {}, - onData: () => {}, - onComplete: () => {} + onHeaders: () => { }, + onData: () => { }, + onComplete: () => { } }) }) - t.test('should error if passed options invalid', async (t) => { - t.plan(3) + test('should error if passed options invalid', async (t) => { + t = tspl(t, { plan: 3 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) mockPool.intercept({ path: '/test', method: 'GET' - }).reply(() => {}) + }).reply(() => { }) mockPool.intercept({ path: '/test3', @@ -146,36 +140,34 @@ test('MockInterceptor - reply options callback', t => { path: '/test', method: 'GET' }, { - onHeaders: () => {}, - onData: () => {}, - onComplete: () => {} + onHeaders: () => { }, + onData: () => { }, + onComplete: () => { } }), new InvalidArgumentError('reply options callback must return an object')) t.throws(() => mockPool.dispatch({ path: '/test3', method: 'GET' }, { - onHeaders: () => {}, - onData: () => {}, - onComplete: () => {} + onHeaders: () => { }, + onData: () => { }, + onComplete: () => { } }), new InvalidArgumentError('responseOptions must be an object')) t.throws(() => mockPool.dispatch({ path: '/test4', method: 'GET' }, { - onHeaders: () => {}, - onData: () => {}, - onComplete: () => {} + onHeaders: () => { }, + onData: () => { }, + onComplete: () => { } }), new InvalidArgumentError('statusCode must be defined')) }) }) -test('MockInterceptor - replyWithError', t => { - t.plan(2) - - t.test('should return MockScope', t => { - t.plan(1) +describe('MockInterceptor - replyWithError', () => { + test('should return MockScope', t => { + t = tspl(t, { plan: 1 }) const mockInterceptor = new MockInterceptor({ path: '', method: '' @@ -184,8 +176,8 @@ test('MockInterceptor - replyWithError', t => { t.ok(result instanceof MockScope) }) - t.test('should error if passed options invalid', t => { - t.plan(1) + test('should error if passed options invalid', t => { + t = tspl(t, { plan: 1 }) const mockInterceptor = new MockInterceptor({ path: '', @@ -195,11 +187,9 @@ test('MockInterceptor - replyWithError', t => { }) }) -test('MockInterceptor - defaultReplyHeaders', t => { - t.plan(2) - - t.test('should return MockInterceptor', t => { - t.plan(1) +describe('MockInterceptor - defaultReplyHeaders', () => { + test('should return MockInterceptor', t => { + t = tspl(t, { plan: 1 }) const mockInterceptor = new MockInterceptor({ path: '', method: '' @@ -208,8 +198,8 @@ test('MockInterceptor - defaultReplyHeaders', t => { t.ok(result instanceof MockInterceptor) }) - t.test('should error if passed options invalid', t => { - t.plan(1) + test('should error if passed options invalid', t => { + t = tspl(t, { plan: 1 }) const mockInterceptor = new MockInterceptor({ path: '', @@ -219,11 +209,9 @@ test('MockInterceptor - defaultReplyHeaders', t => { }) }) -test('MockInterceptor - defaultReplyTrailers', t => { - t.plan(2) - - t.test('should return MockInterceptor', t => { - t.plan(1) +describe('MockInterceptor - defaultReplyTrailers', () => { + test('should return MockInterceptor', t => { + t = tspl(t, { plan: 1 }) const mockInterceptor = new MockInterceptor({ path: '', method: '' @@ -232,8 +220,8 @@ test('MockInterceptor - defaultReplyTrailers', t => { t.ok(result instanceof MockInterceptor) }) - t.test('should error if passed options invalid', t => { - t.plan(1) + test('should error if passed options invalid', t => { + t = tspl(t, { plan: 1 }) const mockInterceptor = new MockInterceptor({ path: '', @@ -243,11 +231,9 @@ test('MockInterceptor - defaultReplyTrailers', t => { }) }) -test('MockInterceptor - replyContentLength', t => { - t.plan(1) - - t.test('should return MockInterceptor', t => { - t.plan(1) +describe('MockInterceptor - replyContentLength', () => { + test('should return MockInterceptor', t => { + t = tspl(t, { plan: 1 }) const mockInterceptor = new MockInterceptor({ path: '', method: '' diff --git a/test/mock-pool.js b/test/mock-pool.js index ca812d90866..0b690fe6d48 100644 --- a/test/mock-pool.js +++ b/test/mock-pool.js @@ -1,6 +1,7 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after, describe } = require('node:test') const { createServer } = require('node:http') const { promisify } = require('node:util') const { MockAgent, MockPool, getGlobalDispatcher, setGlobalDispatcher, request } = require('..') @@ -12,37 +13,33 @@ const { getResponse } = require('../lib/mock/mock-utils') const Dispatcher = require('../lib/dispatcher') const { fetch } = require('..') -test('MockPool - constructor', t => { - t.plan(3) - - t.test('fails if opts.agent does not implement `get` method', t => { - t.plan(1) +describe('MockPool - constructor', () => { + test('fails if opts.agent does not implement `get` method', t => { + t = tspl(t, { plan: 1 }) t.throws(() => new MockPool('http://localhost:9999', { agent: { get: 'not a function' } }), InvalidArgumentError) }) - t.test('sets agent', t => { - t.plan(1) + test('sets agent', t => { + t = tspl(t, { plan: 1 }) t.doesNotThrow(() => new MockPool('http://localhost:9999', { agent: new MockAgent() })) }) - t.test('should implement the Dispatcher API', t => { - t.plan(1) + test('should implement the Dispatcher API', t => { + t = tspl(t, { plan: 1 }) const mockPool = new MockPool('http://localhost:9999', { agent: new MockAgent() }) t.ok(mockPool instanceof Dispatcher) }) }) -test('MockPool - dispatch', t => { - t.plan(2) - - t.test('should handle a single interceptor', (t) => { - t.plan(1) +describe('MockPool - dispatch', () => { + test('should handle a single interceptor', (t) => { + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) @@ -66,18 +63,18 @@ test('MockPool - dispatch', t => { method: 'GET' }, { onHeaders: (_statusCode, _headers, resume) => resume(), - onData: () => {}, - onComplete: () => {} + onData: () => { }, + onComplete: () => { } })) }) - t.test('should directly throw error from mockDispatch function if error is not a MockNotMatchedError', (t) => { - t.plan(1) + test('should directly throw error from mockDispatch function if error is not a MockNotMatchedError', (t) => { + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) @@ -101,19 +98,19 @@ test('MockPool - dispatch', t => { method: 'GET' }, { onHeaders: (_statusCode, _headers, resume) => { throw new Error('kaboom') }, - onData: () => {}, - onComplete: () => {} + onData: () => { }, + onComplete: () => { } }), new Error('kaboom')) }) }) test('MockPool - intercept should return a MockInterceptor', (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) @@ -125,33 +122,31 @@ test('MockPool - intercept should return a MockInterceptor', (t) => { t.ok(interceptor instanceof MockInterceptor) }) -test('MockPool - intercept validation', (t) => { - t.plan(3) - - t.test('it should error if no options specified in the intercept', t => { - t.plan(1) +describe('MockPool - intercept validation', () => { + test('it should error if no options specified in the intercept', t => { + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get('http://localhost:9999') t.throws(() => mockPool.intercept(), new InvalidArgumentError('opts must be an object')) }) - t.test('it should error if no path specified in the intercept', t => { - t.plan(1) + test('it should error if no path specified in the intercept', t => { + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get('http://localhost:9999') t.throws(() => mockPool.intercept({}), new InvalidArgumentError('opts.path must be defined')) }) - t.test('it should default to GET if no method specified in the intercept', t => { - t.plan(1) + test('it should default to GET if no method specified in the intercept', t => { + t = tspl(t, { plan: 1 }) const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get('http://localhost:9999') t.doesNotThrow(() => mockPool.intercept({ path: '/foo' })) @@ -159,12 +154,12 @@ test('MockPool - intercept validation', (t) => { }) test('MockPool - close should run without error', async (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const baseUrl = 'http://localhost:9999' const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) @@ -182,11 +177,12 @@ test('MockPool - close should run without error', async (t) => { } ] - await t.resolves(mockPool.close()) + await mockPool.close() + t.ok(true, 'pass') }) test('MockPool - should be able to set as globalDispatcher', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -194,14 +190,14 @@ test('MockPool - should be able to set as globalDispatcher', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) t.ok(mockPool instanceof MockPool) @@ -215,14 +211,14 @@ test('MockPool - should be able to set as globalDispatcher', async (t) => { const { statusCode, body } = await request(`${baseUrl}/foo`, { method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.same(response, 'hello') + t.deepStrictEqual(response, 'hello') }) test('MockPool - should be able to use as a local dispatcher', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -230,14 +226,14 @@ test('MockPool - should be able to use as a local dispatcher', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) t.ok(mockPool instanceof MockPool) @@ -251,14 +247,14 @@ test('MockPool - should be able to use as a local dispatcher', async (t) => { method: 'GET', dispatcher: mockPool }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const response = await getResponse(body) - t.same(response, 'hello') + t.deepStrictEqual(response, 'hello') }) test('MockPool - basic intercept with MockPool.request', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') @@ -266,14 +262,14 @@ test('MockPool - basic intercept with MockPool.request', async (t) => { t.fail('should not be called') t.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const baseUrl = `http://localhost:${server.address().port}` const mockAgent = new MockAgent() - t.teardown(mockAgent.close.bind(mockAgent)) + after(() => mockAgent.close()) const mockPool = mockAgent.get(baseUrl) t.ok(mockPool instanceof MockPool) @@ -292,25 +288,27 @@ test('MockPool - basic intercept with MockPool.request', async (t) => { method: 'POST', body: 'form1=data1&form2=data2' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'application/json') - t.same(trailers, { 'content-md5': 'test' }) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'application/json') + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) const jsonResponse = JSON.parse(await getResponse(body)) - t.same(jsonResponse, { + t.deepStrictEqual(jsonResponse, { foo: 'bar' }) }) // https://github.com/nodejs/undici/issues/1546 test('MockPool - correct errors when consuming invalid JSON body', async (t) => { + t = tspl(t, { plan: 1 }) + const oldDispatcher = getGlobalDispatcher() const mockAgent = new MockAgent() mockAgent.disableNetConnect() setGlobalDispatcher(mockAgent) - t.teardown(() => setGlobalDispatcher(oldDispatcher)) + after(() => setGlobalDispatcher(oldDispatcher)) const mockPool = mockAgent.get('https://google.com') mockPool.intercept({ @@ -324,6 +322,8 @@ test('MockPool - correct errors when consuming invalid JSON body', async (t) => }) test('MockPool - allows matching headers in fetch', async (t) => { + t = tspl(t, { plan: 2 }) + const oldDispatcher = getGlobalDispatcher() const baseUrl = 'http://localhost:9999' @@ -331,7 +331,7 @@ test('MockPool - allows matching headers in fetch', async (t) => { mockAgent.disableNetConnect() setGlobalDispatcher(mockAgent) - t.teardown(async () => { + after(async () => { await mockAgent.close() setGlobalDispatcher(oldDispatcher) }) @@ -345,23 +345,19 @@ test('MockPool - allows matching headers in fetch', async (t) => { } }).reply(200, { ok: 1 }).times(3) - await t.resolves( - fetch(`${baseUrl}/foo`, { - headers: { - accept: 'application/json' - } - }) - ) + await fetch(`${baseUrl}/foo`, { + headers: { + accept: 'application/json' + } + }) // no 'accept: application/json' header sent, not matched await t.rejects(fetch(`${baseUrl}/foo`)) // not 'accept: application/json', not matched - await t.rejects(fetch(`${baseUrl}/foo`), { + await t.rejects(fetch(`${baseUrl}/foo`, { headers: { accept: 'text/plain' } - }, TypeError) - - t.end() + }), new TypeError('fetch failed')) }) diff --git a/test/mock-scope.js b/test/mock-scope.js index d8f41d90198..0344b99d0bc 100644 --- a/test/mock-scope.js +++ b/test/mock-scope.js @@ -1,14 +1,13 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, describe } = require('node:test') const { MockScope } = require('../lib/mock/mock-interceptor') const { InvalidArgumentError } = require('../lib/core/errors') -test('MockScope - delay', t => { - t.plan(2) - - t.test('should return MockScope', t => { - t.plan(1) +describe('MockScope - delay', () => { + test('should return MockScope', t => { + t = tspl(t, { plan: 1 }) const mockScope = new MockScope({ path: '', method: '' @@ -17,8 +16,8 @@ test('MockScope - delay', t => { t.ok(result instanceof MockScope) }) - t.test('should error if passed options invalid', t => { - t.plan(4) + test('should error if passed options invalid', t => { + t = tspl(t, { plan: 4 }) const mockScope = new MockScope({ path: '', @@ -31,11 +30,9 @@ test('MockScope - delay', t => { }) }) -test('MockScope - persist', t => { - t.plan(1) - - t.test('should return MockScope', t => { - t.plan(1) +describe('MockScope - persist', () => { + test('should return MockScope', t => { + t = tspl(t, { plan: 1 }) const mockScope = new MockScope({ path: '', method: '' @@ -45,11 +42,9 @@ test('MockScope - persist', t => { }) }) -test('MockScope - times', t => { - t.plan(2) - - t.test('should return MockScope', t => { - t.plan(1) +describe('MockScope - times', t => { + test('should return MockScope', t => { + t = tspl(t, { plan: 1 }) const mockScope = new MockScope({ path: '', method: '' @@ -58,8 +53,8 @@ test('MockScope - times', t => { t.ok(result instanceof MockScope) }) - t.test('should error if passed options invalid', t => { - t.plan(4) + test('should error if passed options invalid', t => { + t = tspl(t, { plan: 4 }) const mockScope = new MockScope({ path: '', diff --git a/test/mock-utils.js b/test/mock-utils.js index 4acc8558390..baf0933ba57 100644 --- a/test/mock-utils.js +++ b/test/mock-utils.js @@ -1,6 +1,7 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, describe } = require('node:test') const { MockNotMatchedError } = require('../lib/mock/mock-errors') const { deleteMockDispatch, @@ -11,7 +12,7 @@ const { } = require('../lib/mock/mock-utils') test('deleteMockDispatch - should do nothing if not able to find mock dispatch', (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const key = { url: 'url', @@ -23,11 +24,9 @@ test('deleteMockDispatch - should do nothing if not able to find mock dispatch', t.doesNotThrow(() => deleteMockDispatch([], key)) }) -test('getMockDispatch', (t) => { - t.plan(3) - - t.test('it should find a mock dispatch', (t) => { - t.plan(1) +describe('getMockDispatch', () => { + test('it should find a mock dispatch', (t) => { + t = tspl(t, { plan: 1 }) const dispatches = [ { path: 'path', @@ -40,15 +39,15 @@ test('getMockDispatch', (t) => { path: 'path', method: 'method' }) - t.same(result, { + t.deepStrictEqual(result, { path: 'path', method: 'method', consumed: false }) }) - t.test('it should skip consumed dispatches', (t) => { - t.plan(1) + test('it should skip consumed dispatches', (t) => { + t = tspl(t, { plan: 1 }) const dispatches = [ { path: 'path', @@ -66,15 +65,15 @@ test('getMockDispatch', (t) => { path: 'path', method: 'method' }) - t.same(result, { + t.deepStrictEqual(result, { path: 'path', method: 'method', consumed: false }) }) - t.test('it should throw if dispatch not found', (t) => { - t.plan(1) + test('it should throw if dispatch not found', (t) => { + t = tspl(t, { plan: 1 }) const dispatches = [ { path: 'path', @@ -90,29 +89,29 @@ test('getMockDispatch', (t) => { }) }) -test('getResponseData', (t) => { - t.plan(3) - - t.test('it should stringify objects', (t) => { - t.plan(1) +describe('getResponseData', () => { + test('it should stringify objects', (t) => { + t = tspl(t, { plan: 1 }) const responseData = getResponseData({ str: 'string', num: 42 }) - t.equal(responseData, '{"str":"string","num":42}') + t.strictEqual(responseData, '{"str":"string","num":42}') }) - t.test('it should return strings untouched', (t) => { - t.plan(1) + test('it should return strings untouched', (t) => { + t = tspl(t, { plan: 1 }) const responseData = getResponseData('test') - t.equal(responseData, 'test') + t.strictEqual(responseData, 'test') }) - t.test('it should return buffers untouched', (t) => { - t.plan(1) + test('it should return buffers untouched', (t) => { + t = tspl(t, { plan: 1 }) const responseData = getResponseData(Buffer.from('test')) t.ok(Buffer.isBuffer(responseData)) }) }) test('getStatusText', (t) => { + t = tspl(t, { plan: 64 }) + for (const statusCode of [ 100, 101, 102, 103, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, @@ -126,23 +125,25 @@ test('getStatusText', (t) => { t.ok(getStatusText(statusCode)) } - t.equal(getStatusText(420), 'unknown') + t.strictEqual(getStatusText(420), 'unknown') t.end() }) test('getHeaderByName', (t) => { + t = tspl(t, { plan: 6 }) + const headersRecord = { key: 'value' } - t.equal(getHeaderByName(headersRecord, 'key'), 'value') - t.equal(getHeaderByName(headersRecord, 'anotherKey'), undefined) + t.strictEqual(getHeaderByName(headersRecord, 'key'), 'value') + t.strictEqual(getHeaderByName(headersRecord, 'anotherKey'), undefined) const headersArray = ['key', 'value'] - t.equal(getHeaderByName(headersArray, 'key'), 'value') - t.equal(getHeaderByName(headersArray, 'anotherKey'), undefined) + t.strictEqual(getHeaderByName(headersArray, 'key'), 'value') + t.strictEqual(getHeaderByName(headersArray, 'anotherKey'), undefined) const { Headers } = require('../index') @@ -150,8 +151,8 @@ test('getHeaderByName', (t) => { ['key', 'value'] ]) - t.equal(getHeaderByName(headers, 'key'), 'value') - t.equal(getHeaderByName(headers, 'anotherKey'), null) + t.strictEqual(getHeaderByName(headers, 'key'), 'value') + t.strictEqual(getHeaderByName(headers, 'anotherKey'), null) t.end() }) From e49471f6258a0c73e97f697e97543daa0d824639 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Mon, 12 Feb 2024 12:02:05 +0100 Subject: [PATCH 14/23] chore: migrate a batch of tests to node test runner (#2740) --- test/redirect-pipeline.js | 27 +-- test/redirect-relative.js | 13 +- test/redirect-request.js | 325 +++++++++++++++++++----------- test/redirect-stream.js | 220 ++++++++++---------- test/redirect-upgrade.js | 15 +- test/utils/redirecting-servers.js | 41 ++-- 6 files changed, 365 insertions(+), 276 deletions(-) diff --git a/test/redirect-pipeline.js b/test/redirect-pipeline.js index d958ee513f1..98896fae19c 100644 --- a/test/redirect-pipeline.js +++ b/test/redirect-pipeline.js @@ -1,6 +1,7 @@ 'use strict' -const t = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test } = require('node:test') const { pipeline: undiciPipeline } = require('..') const { pipeline: streamPipelineCb } = require('node:stream') const { promisify } = require('node:util') @@ -9,42 +10,42 @@ const { startRedirectingServer } = require('./utils/redirecting-servers') const streamPipeline = promisify(streamPipelineCb) -t.test('should not follow redirection by default if not using RedirectAgent', async t => { - t.plan(3) +test('should not follow redirection by default if not using RedirectAgent', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const serverRoot = await startRedirectingServer(t) + const serverRoot = await startRedirectingServer() await streamPipeline( createReadable('REQUEST'), undiciPipeline(`http://${serverRoot}/`, {}, ({ statusCode, headers, body }) => { - t.equal(statusCode, 302) - t.equal(headers.location, `http://${serverRoot}/302/1`) + t.strictEqual(statusCode, 302) + t.strictEqual(headers.location, `http://${serverRoot}/302/1`) return body }), createWritable(body) ) - t.equal(body.length, 0) + t.strictEqual(body.length, 0) }) -t.test('should not follow redirects when using RedirectAgent within pipeline', async t => { - t.plan(3) +test('should not follow redirects when using RedirectAgent within pipeline', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const serverRoot = await startRedirectingServer(t) + const serverRoot = await startRedirectingServer() await streamPipeline( createReadable('REQUEST'), undiciPipeline(`http://${serverRoot}/`, { maxRedirections: 1 }, ({ statusCode, headers, body }) => { - t.equal(statusCode, 302) - t.equal(headers.location, `http://${serverRoot}/302/1`) + t.strictEqual(statusCode, 302) + t.strictEqual(headers.location, `http://${serverRoot}/302/1`) return body }), createWritable(body) ) - t.equal(body.length, 0) + t.strictEqual(body.length, 0) }) diff --git a/test/redirect-relative.js b/test/redirect-relative.js index ca9c5411ba4..e4d45406e75 100644 --- a/test/redirect-relative.js +++ b/test/redirect-relative.js @@ -1,15 +1,16 @@ 'use strict' -const t = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test } = require('node:test') const { request } = require('..') const { startRedirectingWithRelativePath } = require('./utils/redirecting-servers') -t.test('should redirect to relative URL according to RFC 7231', async t => { - t.plan(2) +test('should redirect to relative URL according to RFC 7231', async t => { + t = tspl(t, { plan: 2 }) - const server = await startRedirectingWithRelativePath(t) + const server = await startRedirectingWithRelativePath() const { statusCode, body } = await request(`http://${server}`, { maxRedirections: 3 @@ -17,6 +18,6 @@ t.test('should redirect to relative URL according to RFC 7231', async t => { const finalPath = await body.text() - t.equal(statusCode, 200) - t.equal(finalPath, '/absolute/b') + t.strictEqual(statusCode, 200) + t.strictEqual(finalPath, '/absolute/b') }) diff --git a/test/redirect-request.js b/test/redirect-request.js index d200ec17aa8..e7554b929f6 100644 --- a/test/redirect-request.js +++ b/test/redirect-request.js @@ -1,6 +1,7 @@ 'use strict' -const t = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const undici = require('..') const { startRedirectingServer, @@ -20,12 +21,14 @@ for (const factory of [ ]) { const request = (t, server, opts, ...args) => { const dispatcher = factory(server, opts) - t.teardown(() => dispatcher.close()) + after(() => dispatcher.close()) return undici.request(args[0], { ...args[1], dispatcher }, args[2]) } - t.test('should always have a history with the final URL even if no redirections were followed', async t => { - const server = await startRedirectingServer(t) + test('should always have a history with the final URL even if no redirections were followed', async t => { + t = tspl(t, { plan: 4 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream, context: { history } } = await request(t, server, undefined, `http://${server}/200?key=value`, { maxRedirections: 10 @@ -33,25 +36,33 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.same(history.map(x => x.toString()), [`http://${server}/200?key=value`]) - t.equal(body, `GET /5 key=value :: host@${server} connection@keep-alive`) + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.deepStrictEqual(history.map(x => x.toString()), [`http://${server}/200?key=value`]) + t.strictEqual(body, `GET /5 key=value :: host@${server} connection@keep-alive`) + + await t.completed }) - t.test('should not follow redirection by default if not using RedirectAgent', async t => { - const server = await startRedirectingServer(t) + test('should not follow redirection by default if not using RedirectAgent', async t => { + t = tspl(t, { plan: 3 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}`) const body = await bodyStream.text() - t.equal(statusCode, 302) - t.equal(headers.location, `http://${server}/302/1`) - t.equal(body.length, 0) + t.strictEqual(statusCode, 302) + t.strictEqual(headers.location, `http://${server}/302/1`) + t.strictEqual(body.length, 0) + + await t.completed }) - t.test('should follow redirection after a HTTP 300', async t => { - const server = await startRedirectingServer(t) + test('should follow redirection after a HTTP 300', async t => { + t = tspl(t, { plan: 4 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream, context: { history } } = await request(t, server, undefined, `http://${server}/300?key=value`, { maxRedirections: 10 @@ -59,9 +70,9 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.same(history.map(x => x.toString()), [ + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.deepStrictEqual(history.map(x => x.toString()), [ `http://${server}/300?key=value`, `http://${server}/300/1?key=value`, `http://${server}/300/2?key=value`, @@ -69,18 +80,22 @@ for (const factory of [ `http://${server}/300/4?key=value`, `http://${server}/300/5?key=value` ]) - t.equal(body, `GET /5 key=value :: host@${server} connection@keep-alive`) + t.strictEqual(body, `GET /5 key=value :: host@${server} connection@keep-alive`) + + await t.completed }) - t.test('should follow redirection after a HTTP 300 default', async t => { - const server = await startRedirectingServer(t) + test('should follow redirection after a HTTP 300 default', async t => { + t = tspl(t, { plan: 4 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream, context: { history } } = await request(t, server, { maxRedirections: 10 }, `http://${server}/300?key=value`) const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.same(history.map(x => x.toString()), [ + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.deepStrictEqual(history.map(x => x.toString()), [ `http://${server}/300?key=value`, `http://${server}/300/1?key=value`, `http://${server}/300/2?key=value`, @@ -88,11 +103,15 @@ for (const factory of [ `http://${server}/300/4?key=value`, `http://${server}/300/5?key=value` ]) - t.equal(body, `GET /5 key=value :: host@${server} connection@keep-alive`) + t.strictEqual(body, `GET /5 key=value :: host@${server} connection@keep-alive`) + + await t.completed }) - t.test('should follow redirection after a HTTP 301', async t => { - const server = await startRedirectingServer(t) + test('should follow redirection after a HTTP 301', async t => { + t = tspl(t, { plan: 3 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/301`, { method: 'POST', @@ -102,13 +121,14 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.equal(body, `POST /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`) + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.strictEqual(body, `POST /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`) }) - t.test('should follow redirection after a HTTP 302', async t => { - const server = await startRedirectingServer(t) + test('should follow redirection after a HTTP 302', async t => { + t = tspl(t, { plan: 3 }) + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/302`, { method: 'PUT', @@ -118,13 +138,15 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.equal(body, `PUT /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`) + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.strictEqual(body, `PUT /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`) }) - t.test('should follow redirection after a HTTP 303 changing method to GET', async t => { - const server = await startRedirectingServer(t) + test('should follow redirection after a HTTP 303 changing method to GET', async t => { + t = tspl(t, { plan: 3 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/303`, { method: 'PATCH', @@ -134,13 +156,17 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.equal(body, `GET /5 :: host@${server} connection@keep-alive`) + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.strictEqual(body, `GET /5 :: host@${server} connection@keep-alive`) + + await t.completed }) - t.test('should remove Host and request body related headers when following HTTP 303 (array)', async t => { - const server = await startRedirectingServer(t) + test('should remove Host and request body related headers when following HTTP 303 (array)', async t => { + t = tspl(t, { plan: 3 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/303`, { method: 'PATCH', @@ -165,13 +191,17 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.equal(body, `GET /5 :: host@${server} connection@keep-alive x-foo1@1 x-foo2@2 x-foo3@3 x-bar@4`) + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.strictEqual(body, `GET /5 :: host@${server} connection@keep-alive x-foo1@1 x-foo2@2 x-foo3@3 x-bar@4`) + + await t.completed }) - t.test('should remove Host and request body related headers when following HTTP 303 (object)', async t => { - const server = await startRedirectingServer(t) + test('should remove Host and request body related headers when following HTTP 303 (object)', async t => { + t = tspl(t, { plan: 3 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/303`, { method: 'PATCH', @@ -189,13 +219,17 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.equal(body, `GET /5 :: host@${server} connection@keep-alive x-foo1@1 x-foo2@2 x-foo3@3 x-bar@4`) + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.strictEqual(body, `GET /5 :: host@${server} connection@keep-alive x-foo1@1 x-foo2@2 x-foo3@3 x-bar@4`) + + await t.completed }) - t.test('should follow redirection after a HTTP 307', async t => { - const server = await startRedirectingServer(t) + test('should follow redirection after a HTTP 307', async t => { + t = tspl(t, { plan: 3 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/307`, { method: 'DELETE', @@ -204,13 +238,17 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.equal(body, `DELETE /5 :: host@${server} connection@keep-alive`) + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.strictEqual(body, `DELETE /5 :: host@${server} connection@keep-alive`) + + await t.completed }) - t.test('should follow redirection after a HTTP 308', async t => { - const server = await startRedirectingServer(t) + test('should follow redirection after a HTTP 308', async t => { + t = tspl(t, { plan: 3 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/308`, { method: 'OPTIONS', @@ -219,13 +257,17 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.equal(body, `OPTIONS /5 :: host@${server} connection@keep-alive`) + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.strictEqual(body, `OPTIONS /5 :: host@${server} connection@keep-alive`) + + await t.completed }) - t.test('should ignore HTTP 3xx response bodies', async t => { - const server = await startRedirectingWithBodyServer(t) + test('should ignore HTTP 3xx response bodies', async t => { + t = tspl(t, { plan: 4 }) + + const server = await startRedirectingWithBodyServer() const { statusCode, headers, body: bodyStream, context: { history } } = await request(t, server, undefined, `http://${server}/`, { maxRedirections: 10 @@ -233,27 +275,35 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.same(history.map(x => x.toString()), [`http://${server}/`, `http://${server}/end`]) - t.equal(body, 'FINAL') + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.deepStrictEqual(history.map(x => x.toString()), [`http://${server}/`, `http://${server}/end`]) + t.strictEqual(body, 'FINAL') + + await t.completed }) - t.test('should ignore query after redirection', async t => { - const server = await startRedirectingWithQueryParams(t) + test('should ignore query after redirection', async t => { + t = tspl(t, { plan: 3 }) + + const server = await startRedirectingWithQueryParams() const { statusCode, headers, context: { history } } = await request(t, server, undefined, `http://${server}/`, { maxRedirections: 10, query: { param1: 'first' } }) - t.equal(statusCode, 200) - t.notOk(headers.location) - t.same(history.map(x => x.toString()), [`http://${server}/`, `http://${server}/?param2=second`]) + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.deepStrictEqual(history.map(x => x.toString()), [`http://${server}/`, `http://${server}/?param2=second`]) + + await t.completed }) - t.test('should follow a redirect chain up to the allowed number of times', async t => { - const server = await startRedirectingServer(t) + test('should follow a redirect chain up to the allowed number of times', async t => { + t = tspl(t, { plan: 4 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream, context: { history } } = await request(t, server, undefined, `http://${server}/300`, { maxRedirections: 2 @@ -261,27 +311,24 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 300) - t.equal(headers.location, `http://${server}/300/3`) - t.same(history.map(x => x.toString()), [`http://${server}/300`, `http://${server}/300/1`, `http://${server}/300/2`]) - t.equal(body.length, 0) + t.strictEqual(statusCode, 300) + t.strictEqual(headers.location, `http://${server}/300/3`) + t.deepStrictEqual(history.map(x => x.toString()), [`http://${server}/300`, `http://${server}/300/1`, `http://${server}/300/2`]) + t.strictEqual(body.length, 0) + + await t.completed }) - t.test('should follow a redirect chain up to the allowed number of times for redirectionLimitReached', async t => { - const server = await startRedirectingServer(t) + test('should follow a redirect chain up to the allowed number of times for redirectionLimitReached', async t => { + t = tspl(t, { plan: 1 }) + + const server = await startRedirectingServer() try { - const { statusCode, headers, body: bodyStream, context: { history } } = await request(t, server, undefined, `http://${server}/300`, { + await request(t, server, undefined, `http://${server}/300`, { maxRedirections: 2, throwOnMaxRedirect: true }) - - const body = await bodyStream.text() - - t.equal(statusCode, 300) - t.equal(headers.location, `http://${server}/300/2`) - t.same(history.map(x => x.toString()), [`http://${server}/300`, `http://${server}/300/1`]) - t.equal(body.length, 0) } catch (error) { if (error.message.startsWith('max redirects')) { t.ok(true, 'Max redirects handled correctly') @@ -289,11 +336,15 @@ for (const factory of [ t.fail(`Unexpected error: ${error.message}`) } } + + await t.completed }) - t.test('when a Location response header is NOT present', async t => { + test('when a Location response header is NOT present', async t => { + t = tspl(t, { plan: 6 * 3 }) + const redirectCodes = [300, 301, 302, 303, 307, 308] - const server = await startRedirectingWithoutLocationServer(t) + const server = await startRedirectingWithoutLocationServer() for (const code of redirectCodes) { const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/${code}`, { @@ -302,13 +353,16 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, code) - t.notOk(headers.location) - t.equal(body.length, 0) + t.strictEqual(statusCode, code) + t.ok(!headers.location) + t.strictEqual(body.length, 0) } + await t.completed }) - t.test('should not allow invalid maxRedirections arguments', async t => { + test('should not allow invalid maxRedirections arguments', async t => { + t = tspl(t, { plan: 1 }) + try { await request(t, 'localhost', undefined, 'http://localhost', { method: 'GET', @@ -317,11 +371,14 @@ for (const factory of [ t.fail('Did not throw') } catch (err) { - t.equal(err.message, 'maxRedirections must be a positive number') + t.strictEqual(err.message, 'maxRedirections must be a positive number') } + await t.completed }) - t.test('should not allow invalid maxRedirections arguments default', async t => { + test('should not allow invalid maxRedirections arguments default', async t => { + t = tspl(t, { plan: 1 }) + try { await request(t, 'localhost', { maxRedirections: 'INVALID' @@ -331,12 +388,16 @@ for (const factory of [ t.fail('Did not throw') } catch (err) { - t.equal(err.message, 'maxRedirections must be a positive number') + t.strictEqual(err.message, 'maxRedirections must be a positive number') } + + await t.completed }) - t.test('should not follow redirects when using ReadableStream request bodies', async t => { - const server = await startRedirectingServer(t) + test('should not follow redirects when using ReadableStream request bodies', async t => { + t = tspl(t, { plan: 3 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/301`, { method: 'POST', @@ -346,13 +407,17 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 301) - t.equal(headers.location, `http://${server}/301/2`) - t.equal(body.length, 0) + t.strictEqual(statusCode, 301) + t.strictEqual(headers.location, `http://${server}/301/2`) + t.strictEqual(body.length, 0) + + await t.completed }) - t.test('should not follow redirects when using Readable request bodies', async t => { - const server = await startRedirectingServer(t) + test('should not follow redirects when using Readable request bodies', async t => { + t = tspl(t, { plan: 3 }) + + const server = await startRedirectingServer() const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/301`, { method: 'POST', @@ -362,14 +427,17 @@ for (const factory of [ const body = await bodyStream.text() - t.equal(statusCode, 301) - t.equal(headers.location, `http://${server}/301/1`) - t.equal(body.length, 0) + t.strictEqual(statusCode, 301) + t.strictEqual(headers.location, `http://${server}/301/1`) + t.strictEqual(body.length, 0) + await t.completed }) } -t.test('should follow redirections when going cross origin', async t => { - const [server1, server2, server3] = await startRedirectingChainServers(t) +test('should follow redirections when going cross origin', async t => { + t = tspl(t, { plan: 4 }) + + const [server1, server2, server3] = await startRedirectingChainServers() const { statusCode, headers, body: bodyStream, context: { history } } = await undici.request(`http://${server1}`, { method: 'POST', @@ -378,9 +446,9 @@ t.test('should follow redirections when going cross origin', async t => { const body = await bodyStream.text() - t.equal(statusCode, 200) - t.notOk(headers.location) - t.same(history.map(x => x.toString()), [ + t.strictEqual(statusCode, 200) + t.ok(!headers.location) + t.deepStrictEqual(history.map(x => x.toString()), [ `http://${server1}/`, `http://${server2}/`, `http://${server3}/`, @@ -388,11 +456,13 @@ t.test('should follow redirections when going cross origin', async t => { `http://${server3}/end`, `http://${server1}/end` ]) - t.equal(body, 'POST') + t.strictEqual(body, 'POST') + + await t.completed }) -t.test('should handle errors (callback)', t => { - t.plan(1) +test('should handle errors (callback)', async t => { + t = tspl(t, { plan: 1 }) undici.request( 'http://localhost:0', @@ -403,19 +473,27 @@ t.test('should handle errors (callback)', t => { t.match(error.code, /EADDRNOTAVAIL|ECONNREFUSED/) } ) + + await t.completed }) -t.test('should handle errors (promise)', async t => { +test('should handle errors (promise)', async t => { + t = tspl(t, { plan: 1 }) + try { await undici.request('http://localhost:0', { maxRedirections: 10 }) t.fail('Did not throw') } catch (error) { t.match(error.code, /EADDRNOTAVAIL|ECONNREFUSED/) } + + await t.completed }) -t.test('removes authorization header on third party origin', async t => { - const [server1] = await startRedirectingWithAuthorization(t, 'secret') +test('removes authorization header on third party origin', async t => { + t = tspl(t, { plan: 1 }) + + const [server1] = await startRedirectingWithAuthorization('secret') const { body: bodyStream } = await undici.request(`http://${server1}`, { maxRedirections: 10, headers: { @@ -425,11 +503,14 @@ t.test('removes authorization header on third party origin', async t => { const body = await bodyStream.text() - t.equal(body, '') + t.strictEqual(body, '') + + await t.completed }) -t.test('removes cookie header on third party origin', async t => { - const [server1] = await startRedirectingWithCookie(t, 'a=b') +test('removes cookie header on third party origin', async t => { + t = tspl(t, { plan: 1 }) + const [server1] = await startRedirectingWithCookie('a=b') const { body: bodyStream } = await undici.request(`http://${server1}`, { maxRedirections: 10, headers: { @@ -439,5 +520,7 @@ t.test('removes cookie header on third party origin', async t => { const body = await bodyStream.text() - t.equal(body, '') + t.strictEqual(body, '') + + await t.completed }) diff --git a/test/redirect-stream.js b/test/redirect-stream.js index 55dd97beb49..c50e5033135 100644 --- a/test/redirect-stream.js +++ b/test/redirect-stream.js @@ -1,6 +1,7 @@ 'use strict' -const t = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, describe } = require('node:test') const { stream } = require('..') const { startRedirectingServer, @@ -12,19 +13,19 @@ const { } = require('./utils/redirecting-servers') const { createReadable, createWritable } = require('./utils/stream') -t.test('should always have a history with the final URL even if no redirections were followed', async t => { - t.plan(4) +test('should always have a history with the final URL even if no redirections were followed', async t => { + t = tspl(t, { plan: 4 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream( `http://${server}/200?key=value`, { opaque: body, maxRedirections: 10 }, ({ statusCode, headers, opaque, context: { history } }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) - t.same(history.map(x => x.toString()), [ + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) + t.deepStrictEqual(history.map(x => x.toString()), [ `http://${server}/200?key=value` ]) @@ -32,38 +33,38 @@ t.test('should always have a history with the final URL even if no redirections } ) - t.equal(body.join(''), `GET /5 key=value :: host@${server} connection@keep-alive`) + t.strictEqual(body.join(''), `GET /5 key=value :: host@${server} connection@keep-alive`) }) -t.test('should not follow redirection by default if not using RedirectAgent', async t => { - t.plan(3) +test('should not follow redirection by default if not using RedirectAgent', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream(`http://${server}`, { opaque: body }, ({ statusCode, headers, opaque }) => { - t.equal(statusCode, 302) - t.equal(headers.location, `http://${server}/302/1`) + t.strictEqual(statusCode, 302) + t.strictEqual(headers.location, `http://${server}/302/1`) return createWritable(opaque) }) - t.equal(body.length, 0) + t.strictEqual(body.length, 0) }) -t.test('should follow redirection after a HTTP 300', async t => { - t.plan(4) +test('should follow redirection after a HTTP 300', async t => { + t = tspl(t, { plan: 4 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream( `http://${server}/300?key=value`, { opaque: body, maxRedirections: 10 }, ({ statusCode, headers, opaque, context: { history } }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) - t.same(history.map(x => x.toString()), [ + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) + t.deepStrictEqual(history.map(x => x.toString()), [ `http://${server}/300?key=value`, `http://${server}/300/1?key=value`, `http://${server}/300/2?key=value`, @@ -76,70 +77,70 @@ t.test('should follow redirection after a HTTP 300', async t => { } ) - t.equal(body.join(''), `GET /5 key=value :: host@${server} connection@keep-alive`) + t.strictEqual(body.join(''), `GET /5 key=value :: host@${server} connection@keep-alive`) }) -t.test('should follow redirection after a HTTP 301', async t => { - t.plan(3) +test('should follow redirection after a HTTP 301', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream( `http://${server}/301`, { method: 'POST', body: 'REQUEST', opaque: body, maxRedirections: 10 }, ({ statusCode, headers, opaque }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) return createWritable(opaque) } ) - t.equal(body.join(''), `POST /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`) + t.strictEqual(body.join(''), `POST /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`) }) -t.test('should follow redirection after a HTTP 302', async t => { - t.plan(3) +test('should follow redirection after a HTTP 302', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream( `http://${server}/302`, { method: 'PUT', body: Buffer.from('REQUEST'), opaque: body, maxRedirections: 10 }, ({ statusCode, headers, opaque }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) return createWritable(opaque) } ) - t.equal(body.join(''), `PUT /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`) + t.strictEqual(body.join(''), `PUT /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`) }) -t.test('should follow redirection after a HTTP 303 changing method to GET', async t => { - t.plan(3) +test('should follow redirection after a HTTP 303 changing method to GET', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream(`http://${server}/303`, { opaque: body, maxRedirections: 10 }, ({ statusCode, headers, opaque }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) return createWritable(opaque) }) - t.equal(body.join(''), `GET /5 :: host@${server} connection@keep-alive`) + t.strictEqual(body.join(''), `GET /5 :: host@${server} connection@keep-alive`) }) -t.test('should remove Host and request body related headers when following HTTP 303 (array)', async t => { - t.plan(3) +test('should remove Host and request body related headers when following HTTP 303 (array)', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream( `http://${server}/303`, @@ -165,21 +166,21 @@ t.test('should remove Host and request body related headers when following HTTP maxRedirections: 10 }, ({ statusCode, headers, opaque }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) return createWritable(opaque) } ) - t.equal(body.join(''), `GET /5 :: host@${server} connection@keep-alive x-foo1@1 x-foo2@2 x-foo3@3 x-bar@4`) + t.strictEqual(body.join(''), `GET /5 :: host@${server} connection@keep-alive x-foo1@1 x-foo2@2 x-foo3@3 x-bar@4`) }) -t.test('should remove Host and request body related headers when following HTTP 303 (object)', async t => { - t.plan(3) +test('should remove Host and request body related headers when following HTTP 303 (object)', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream( `http://${server}/303`, @@ -198,111 +199,111 @@ t.test('should remove Host and request body related headers when following HTTP maxRedirections: 10 }, ({ statusCode, headers, opaque }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) return createWritable(opaque) } ) - t.equal(body.join(''), `GET /5 :: host@${server} connection@keep-alive x-foo1@1 x-foo2@2 x-foo3@3 x-bar@4`) + t.strictEqual(body.join(''), `GET /5 :: host@${server} connection@keep-alive x-foo1@1 x-foo2@2 x-foo3@3 x-bar@4`) }) -t.test('should follow redirection after a HTTP 307', async t => { - t.plan(3) +test('should follow redirection after a HTTP 307', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream( `http://${server}/307`, { method: 'DELETE', opaque: body, maxRedirections: 10 }, ({ statusCode, headers, opaque }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) return createWritable(opaque) } ) - t.equal(body.join(''), `DELETE /5 :: host@${server} connection@keep-alive`) + t.strictEqual(body.join(''), `DELETE /5 :: host@${server} connection@keep-alive`) }) -t.test('should follow redirection after a HTTP 308', async t => { - t.plan(3) +test('should follow redirection after a HTTP 308', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream( `http://${server}/308`, { method: 'OPTIONS', opaque: body, maxRedirections: 10 }, ({ statusCode, headers, opaque }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) return createWritable(opaque) } ) - t.equal(body.join(''), `OPTIONS /5 :: host@${server} connection@keep-alive`) + t.strictEqual(body.join(''), `OPTIONS /5 :: host@${server} connection@keep-alive`) }) -t.test('should ignore HTTP 3xx response bodies', async t => { - t.plan(4) +test('should ignore HTTP 3xx response bodies', async t => { + t = tspl(t, { plan: 4 }) const body = [] - const server = await startRedirectingWithBodyServer(t) + const server = await startRedirectingWithBodyServer() await stream( `http://${server}/`, { opaque: body, maxRedirections: 10 }, ({ statusCode, headers, opaque, context: { history } }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) - t.same(history.map(x => x.toString()), [`http://${server}/`, `http://${server}/end`]) + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) + t.deepStrictEqual(history.map(x => x.toString()), [`http://${server}/`, `http://${server}/end`]) return createWritable(opaque) } ) - t.equal(body.join(''), 'FINAL') + t.strictEqual(body.join(''), 'FINAL') }) -t.test('should follow a redirect chain up to the allowed number of times', async t => { - t.plan(4) +test('should follow a redirect chain up to the allowed number of times', async t => { + t = tspl(t, { plan: 4 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream( `http://${server}/300`, { opaque: body, maxRedirections: 2 }, ({ statusCode, headers, opaque, context: { history } }) => { - t.equal(statusCode, 300) - t.equal(headers.location, `http://${server}/300/3`) - t.same(history.map(x => x.toString()), [`http://${server}/300`, `http://${server}/300/1`, `http://${server}/300/2`]) + t.strictEqual(statusCode, 300) + t.strictEqual(headers.location, `http://${server}/300/3`) + t.deepStrictEqual(history.map(x => x.toString()), [`http://${server}/300`, `http://${server}/300/1`, `http://${server}/300/2`]) return createWritable(opaque) } ) - t.equal(body.length, 0) + t.strictEqual(body.length, 0) }) -t.test('should follow redirections when going cross origin', async t => { - t.plan(4) +test('should follow redirections when going cross origin', async t => { + t = tspl(t, { plan: 4 }) - const [server1, server2, server3] = await startRedirectingChainServers(t) + const [server1, server2, server3] = await startRedirectingChainServers() const body = [] await stream( `http://${server1}`, { method: 'POST', opaque: body, maxRedirections: 10 }, ({ statusCode, headers, opaque, context: { history } }) => { - t.equal(statusCode, 200) - t.notOk(headers.location) - t.same(history.map(x => x.toString()), [ + t.strictEqual(statusCode, 200) + t.strictEqual(headers.location, undefined) + t.deepStrictEqual(history.map(x => x.toString()), [ `http://${server1}/`, `http://${server2}/`, `http://${server3}/`, @@ -315,16 +316,16 @@ t.test('should follow redirections when going cross origin', async t => { } ) - t.equal(body.join(''), 'POST') + t.strictEqual(body.join(''), 'POST') }) -t.test('when a Location response header is NOT present', async t => { +describe('when a Location response header is NOT present', async () => { const redirectCodes = [300, 301, 302, 303, 307, 308] - const server = await startRedirectingWithoutLocationServer(t) + const server = await startRedirectingWithoutLocationServer() for (const code of redirectCodes) { - t.test(`should return the original response after a HTTP ${code}`, async t => { - t.plan(3) + test(`should return the original response after a HTTP ${code}`, async t => { + t = tspl(t, { plan: 3 }) const body = [] @@ -332,23 +333,24 @@ t.test('when a Location response header is NOT present', async t => { `http://${server}/${code}`, { opaque: body, maxRedirections: 10 }, ({ statusCode, headers, opaque }) => { - t.equal(statusCode, code) - t.notOk(headers.location) + t.strictEqual(statusCode, code) + t.strictEqual(headers.location, undefined) return createWritable(opaque) } ) - t.equal(body.length, 0) + t.strictEqual(body.length, 0) + await t.completed }) } }) -t.test('should not follow redirects when using Readable request bodies', async t => { - t.plan(3) +test('should not follow redirects when using Readable request bodies', async t => { + t = tspl(t, { plan: 3 }) const body = [] - const server = await startRedirectingServer(t) + const server = await startRedirectingServer() await stream( `http://${server}`, @@ -359,18 +361,18 @@ t.test('should not follow redirects when using Readable request bodies', async t maxRedirections: 10 }, ({ statusCode, headers, opaque }) => { - t.equal(statusCode, 302) - t.equal(headers.location, `http://${server}/302/1`) + t.strictEqual(statusCode, 302) + t.strictEqual(headers.location, `http://${server}/302/1`) return createWritable(opaque) } ) - t.equal(body.length, 0) + t.strictEqual(body.length, 0) }) -t.test('should handle errors', async t => { - t.plan(2) +test('should handle errors', async t => { + t = tspl(t, { plan: 2 }) const body = [] @@ -382,16 +384,16 @@ t.test('should handle errors', async t => { throw new Error('Did not throw') } catch (error) { t.match(error.code, /EADDRNOTAVAIL|ECONNREFUSED/) - t.equal(body.length, 0) + t.strictEqual(body.length, 0) } }) -t.test('removes authorization header on third party origin', async t => { - t.plan(1) +test('removes authorization header on third party origin', async t => { + t = tspl(t, { plan: 1 }) const body = [] - const [server1] = await startRedirectingWithAuthorization(t, 'secret') + const [server1] = await startRedirectingWithAuthorization('secret') await stream(`http://${server1}`, { maxRedirections: 10, opaque: body, @@ -400,15 +402,15 @@ t.test('removes authorization header on third party origin', async t => { } }, ({ statusCode, headers, opaque }) => createWritable(opaque)) - t.equal(body.length, 0) + t.strictEqual(body.length, 0) }) -t.test('removes cookie header on third party origin', async t => { - t.plan(1) +test('removes cookie header on third party origin', async t => { + t = tspl(t, { plan: 1 }) const body = [] - const [server1] = await startRedirectingWithCookie(t, 'a=b') + const [server1] = await startRedirectingWithCookie('a=b') await stream(`http://${server1}`, { maxRedirections: 10, opaque: body, @@ -417,7 +419,5 @@ t.test('removes cookie header on third party origin', async t => { } }, ({ statusCode, headers, opaque }) => createWritable(opaque)) - t.equal(body.length, 0) + t.strictEqual(body.length, 0) }) - -t.teardown(() => process.exit()) diff --git a/test/redirect-upgrade.js b/test/redirect-upgrade.js index dbe584065df..5e331797379 100644 --- a/test/redirect-upgrade.js +++ b/test/redirect-upgrade.js @@ -1,13 +1,14 @@ 'use strict' -const t = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test } = require('node:test') const { upgrade } = require('..') const { startServer } = require('./utils/redirecting-servers') -t.test('should upgrade the connection when no redirects are present', async t => { - t.plan(2) +test('should upgrade the connection when no redirects are present', async t => { + t = tspl(t, { plan: 2 }) - const server = await startServer(t, (req, res) => { + const server = await startServer((req, res) => { if (req.url === '/') { res.statusCode = 301 res.setHeader('Location', `http://${server}/end`) @@ -29,6 +30,8 @@ t.test('should upgrade the connection when no redirects are present', async t => socket.end() - t.equal(headers.connection, 'upgrade') - t.equal(headers.upgrade, 'foo/1') + t.strictEqual(headers.connection, 'upgrade') + t.strictEqual(headers.upgrade, 'foo/1') + + await t.completed }) diff --git a/test/utils/redirecting-servers.js b/test/utils/redirecting-servers.js index 0125fc55748..011979c3e1e 100644 --- a/test/utils/redirecting-servers.js +++ b/test/utils/redirecting-servers.js @@ -1,6 +1,7 @@ 'use strict' const { createServer } = require('node:http') +const { after } = require('node:test') const isNode20 = process.version.startsWith('v20.') @@ -15,7 +16,7 @@ function close (server) { } } -function startServer (t, handler) { +function startServer (handler) { return new Promise(resolve => { const server = createServer(handler) @@ -23,12 +24,12 @@ function startServer (t, handler) { resolve(`localhost:${server.address().port}`) }) - t.teardown(close(server)) + after(close(server)) }) } -async function startRedirectingServer (t) { - const server = await startServer(t, (req, res) => { +async function startRedirectingServer () { + const server = await startServer((req, res) => { // Parse the path and normalize arguments let [code, redirections, query] = req.url .slice(1) @@ -90,8 +91,8 @@ async function startRedirectingServer (t) { return server } -async function startRedirectingWithBodyServer (t) { - const server = await startServer(t, (req, res) => { +async function startRedirectingWithBodyServer () { + const server = await startServer((req, res) => { if (req.url === '/') { res.statusCode = 301 res.setHeader('Connection', 'close') @@ -107,8 +108,8 @@ async function startRedirectingWithBodyServer (t) { return server } -function startRedirectingWithoutLocationServer (t) { - return startServer(t, (req, res) => { +function startRedirectingWithoutLocationServer () { + return startServer((req, res) => { // Parse the path and normalize arguments let [code] = req.url .slice(1) @@ -125,8 +126,8 @@ function startRedirectingWithoutLocationServer (t) { }) } -async function startRedirectingChainServers (t) { - const server1 = await startServer(t, (req, res) => { +async function startRedirectingChainServers () { + const server1 = await startServer((req, res) => { if (req.url === '/') { res.statusCode = 301 res.setHeader('Connection', 'close') @@ -139,7 +140,7 @@ async function startRedirectingChainServers (t) { res.end(req.method) }) - const server2 = await startServer(t, (req, res) => { + const server2 = await startServer((req, res) => { res.statusCode = 301 res.setHeader('Connection', 'close') @@ -152,7 +153,7 @@ async function startRedirectingChainServers (t) { res.end('') }) - const server3 = await startServer(t, (req, res) => { + const server3 = await startServer((req, res) => { res.statusCode = 301 res.setHeader('Connection', 'close') @@ -168,8 +169,8 @@ async function startRedirectingChainServers (t) { return [server1, server2, server3] } -async function startRedirectingWithAuthorization (t, authorization) { - const server1 = await startServer(t, (req, res) => { +async function startRedirectingWithAuthorization (authorization) { + const server1 = await startServer((req, res) => { if (req.headers.authorization !== authorization) { res.statusCode = 403 res.setHeader('Connection', 'close') @@ -184,15 +185,15 @@ async function startRedirectingWithAuthorization (t, authorization) { res.end('') }) - const server2 = await startServer(t, (req, res) => { + const server2 = await startServer((req, res) => { res.end(req.headers.authorization || '') }) return [server1, server2] } -async function startRedirectingWithCookie (t, cookie) { - const server1 = await startServer(t, (req, res) => { +async function startRedirectingWithCookie (cookie) { + const server1 = await startServer((req, res) => { if (req.headers.cookie !== cookie) { res.statusCode = 403 res.setHeader('Connection', 'close') @@ -207,7 +208,7 @@ async function startRedirectingWithCookie (t, cookie) { res.end('') }) - const server2 = await startServer(t, (req, res) => { + const server2 = await startServer((req, res) => { res.end(req.headers.cookie || '') }) @@ -215,7 +216,7 @@ async function startRedirectingWithCookie (t, cookie) { } async function startRedirectingWithRelativePath (t) { - const server = await startServer(t, (req, res) => { + const server = await startServer((req, res) => { res.setHeader('Connection', 'close') if (req.url === '/') { @@ -236,7 +237,7 @@ async function startRedirectingWithRelativePath (t) { } async function startRedirectingWithQueryParams (t) { - const server = await startServer(t, (req, res) => { + const server = await startServer((req, res) => { if (req.url === '/?param1=first') { res.statusCode = 301 res.setHeader('Connection', 'close') From 43286a995fa67b71188cc63f419583ea06867327 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Mon, 12 Feb 2024 12:02:32 +0100 Subject: [PATCH 15/23] chore: migrate a batch of tests to node test runner (#2738) --- test/invalid-headers.js | 7 +- test/issue-2078.js | 13 ++- test/issue-803.js | 48 +++++---- test/issue-810.js | 178 +++++++++++++++++-------------- test/max-headers.js | 50 +++++---- test/no-strict-content-length.js | 105 ++++++++++-------- test/proxy.js | 27 ++--- test/readable.test.js | 22 ++-- test/request-crlf.js | 40 +++---- test/request-timeout2.js | 61 ++++++----- 10 files changed, 299 insertions(+), 252 deletions(-) diff --git a/test/invalid-headers.js b/test/invalid-headers.js index 0c011e97ac1..5d49fcbf23f 100644 --- a/test/invalid-headers.js +++ b/test/invalid-headers.js @@ -1,13 +1,14 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, errors } = require('..') test('invalid headers', (t) => { - t.plan(10) + t = tspl(t, { plan: 10 }) const client = new Client('http://localhost:3000') - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', diff --git a/test/issue-2078.js b/test/issue-2078.js index 335d7ab3820..40597919c24 100644 --- a/test/issue-2078.js +++ b/test/issue-2078.js @@ -1,24 +1,29 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { MockAgent, getGlobalDispatcher, setGlobalDispatcher, fetch } = require('..') test('MockPool.reply headers are an object, not an array - issue #2078', async (t) => { + t = tspl(t, { plan: 1 }) + const global = getGlobalDispatcher() const mockAgent = new MockAgent() const mockPool = mockAgent.get('http://localhost') - t.teardown(() => setGlobalDispatcher(global)) + after(() => setGlobalDispatcher(global)) setGlobalDispatcher(mockAgent) mockPool.intercept({ path: '/foo', method: 'GET' }).reply((options) => { - t.ok(!Array.isArray(options.headers)) + t.strictEqual(Array.isArray(options.headers), false) return { statusCode: 200 } }) - await t.resolves(fetch('http://localhost/foo')) + await fetch('http://localhost/foo') + + await t.completed }) diff --git a/test/issue-803.js b/test/issue-803.js index 35975103967..849bc1aba47 100644 --- a/test/issue-803.js +++ b/test/issue-803.js @@ -1,12 +1,14 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') +const { once } = require('node:events') const { Client } = require('..') const { createServer } = require('node:http') const EE = require('node:events') -test('https://github.com/nodejs/undici/issues/803', (t) => { - t.plan(2) +test('https://github.com/nodejs/undici/issues/803', async (t) => { + t = tspl(t, { plan: 2 }) const SIZE = 5900373096 @@ -23,25 +25,27 @@ test('https://github.com/nodejs/undici/issues/803', (t) => { res.end() }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) - - client.request({ - path: '/', - method: 'GET' - }, (err, data) => { - t.error(err) - - let pos = 0 - data.body.on('data', (buf) => { - pos += buf.length - }) - data.body.on('end', () => { - t.equal(pos, SIZE) - }) + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, data) => { + t.ifError(err) + + let pos = 0 + data.body.on('data', (buf) => { + pos += buf.length + }) + data.body.on('end', () => { + t.strictEqual(pos, SIZE) }) }) + await t.completed }) diff --git a/test/issue-810.js b/test/issue-810.js index e18656c5869..2a132cf30f3 100644 --- a/test/issue-810.js +++ b/test/issue-810.js @@ -1,11 +1,13 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') +const { once } = require('node:events') const { Client, errors } = require('..') const net = require('node:net') -test('https://github.com/mcollina/undici/issues/810', (t) => { - t.plan(3) +test('https://github.com/mcollina/undici/issues/810', async (t) => { + t = tspl(t, { plan: 3 }) let x = 0 const server = net.createServer(socket => { @@ -19,117 +21,127 @@ test('https://github.com/mcollina/undici/issues/810', (t) => { socket.write('\r\n') } }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'GET' - }, (err, data) => { - t.error(err) - data.body.resume().on('end', () => { - // t.fail() FIX: Should fail. - t.ok(true, 'pass') - }).on('error', err => ( - t.ok(err instanceof errors.HTTPParserError) - )) - }) - client.request({ - path: '/', - method: 'GET' - }, (err, data) => { + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, data) => { + t.ifError(err) + data.body.resume().on('end', () => { + // t.fail() FIX: Should fail. + t.ok(true, 'pass') + }).on('error', err => ( t.ok(err instanceof errors.HTTPParserError) - }) + )) + }) + client.request({ + path: '/', + method: 'GET' + }, (err, data) => { + t.ok(err instanceof errors.HTTPParserError) }) + await t.completed }) -test('https://github.com/mcollina/undici/issues/810 no pipelining', (t) => { - t.plan(2) +test('https://github.com/mcollina/undici/issues/810 no pipelining', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer(socket => { socket.write('HTTP/1.1 200 OK\r\n') socket.write('Content-Length: 1\r\n\r\n') socket.write('11111\r\n') }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - - client.request({ - path: '/', - method: 'GET' - }, (err, data) => { - t.error(err) - data.body.resume().on('end', () => { - // t.fail() FIX: Should fail. - t.ok(true, 'pass') - }) + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + + client.request({ + path: '/', + method: 'GET' + }, (err, data) => { + t.ifError(err) + data.body.resume().on('end', () => { + // t.fail() FIX: Should fail. + t.ok(true, 'pass') }) }) + await t.completed }) -test('https://github.com/mcollina/undici/issues/810 pipelining', (t) => { - t.plan(2) +test('https://github.com/mcollina/undici/issues/810 pipelining', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer(socket => { socket.write('HTTP/1.1 200 OK\r\n') socket.write('Content-Length: 1\r\n\r\n') socket.write('11111\r\n') }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { pipelining: true }) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'GET' - }, (err, data) => { - t.error(err) - data.body.resume().on('end', () => { - // t.fail() FIX: Should fail. - t.ok(true, 'pass') - }) + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + + const client = new Client(`http://localhost:${server.address().port}`, { pipelining: true }) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, data) => { + t.ifError(err) + data.body.resume().on('end', () => { + // t.fail() FIX: Should fail. + t.ok(true, 'pass') }) }) + await t.completed }) -test('https://github.com/mcollina/undici/issues/810 pipelining 2', (t) => { - t.plan(4) +test('https://github.com/mcollina/undici/issues/810 pipelining 2', async (t) => { + t = tspl(t, { plan: 4 }) const server = net.createServer(socket => { socket.write('HTTP/1.1 200 OK\r\n') socket.write('Content-Length: 1\r\n\r\n') socket.write('11111\r\n') }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { pipelining: true }) - t.teardown(client.destroy.bind(client)) - - client.request({ - path: '/', - method: 'GET' - }, (err, data) => { - t.error(err) - data.body.resume().on('end', () => { - // t.fail() FIX: Should fail. - t.ok(true, 'pass') - }) - }) + after(() => server.close()) - client.request({ - path: '/', - method: 'GET' - }, (err, data) => { - t.equal(err.code, 'HPE_INVALID_CONSTANT') - t.ok(err instanceof errors.HTTPParserError) + server.listen(0) + + await once(server, 'listening') + + const client = new Client(`http://localhost:${server.address().port}`, { pipelining: true }) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, data) => { + t.ifError(err) + data.body.resume().on('end', () => { + // t.fail() FIX: Should fail. + t.ok(true, 'pass') }) }) + + client.request({ + path: '/', + method: 'GET' + }, (err, data) => { + t.strictEqual(err.code, 'HPE_INVALID_CONSTANT') + t.ok(err instanceof errors.HTTPParserError) + }) + await t.completed }) diff --git a/test/max-headers.js b/test/max-headers.js index a7946e81098..0f1422a60b4 100644 --- a/test/max-headers.js +++ b/test/max-headers.js @@ -1,11 +1,13 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const { createServer } = require('node:http') +const { once } = require('node:events') -test('handle a lot of headers', (t) => { - t.plan(3) +test('handle a lot of headers', async (t) => { + t = tspl(t, { plan: 3 }) const headers = {} for (let n = 0; n < 64; ++n) { @@ -16,26 +18,28 @@ test('handle a lot of headers', (t) => { res.writeHead(200, headers) res.end() }) - t.teardown(server.close.bind(server)) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => server.close()) + server.listen(0) - client.request({ - path: '/', - method: 'GET' - }, (err, data) => { - t.error(err) - const headers2 = {} - for (let n = 0; n < 64; ++n) { - headers2[n] = data.headers[n] - } - t.strictSame(headers2, headers) - data.body - .resume() - .on('end', () => { - t.ok(true, 'pass') - }) - }) + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET' + }, (err, data) => { + t.ifError(err) + const headers2 = {} + for (let n = 0; n < 64; ++n) { + headers2[n] = data.headers[n] + } + t.deepStrictEqual(headers2, headers) + data.body + .resume() + .on('end', () => { + t.ok(true, 'pass') + }) }) + await t.completed }) diff --git a/test/no-strict-content-length.js b/test/no-strict-content-length.js index b16b82bc38e..d74f4677d56 100644 --- a/test/no-strict-content-length.js +++ b/test/no-strict-content-length.js @@ -1,15 +1,14 @@ 'use strict' -const tap = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after, describe } = require('node:test') const { Client } = require('..') const { createServer } = require('node:http') const { Readable } = require('node:stream') const sinon = require('sinon') const { wrapWithAsyncIterable } = require('./utils/async-iterators') -tap.test('strictContentLength: false', (t) => { - t.plan(7) - +describe('strictContentLength: false', (t) => { const emitWarningStub = sinon.stub(process, 'emitWarning') function assertEmitWarningCalledAndReset () { @@ -17,23 +16,23 @@ tap.test('strictContentLength: false', (t) => { emitWarningStub.resetHistory() } - t.teardown(() => { + after(() => { emitWarningStub.restore() }) - t.test('request invalid content-length', (t) => { - t.plan(8) + test('request invalid content-length', async (t) => { + t = tspl(t, { plan: 8 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { strictContentLength: false }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -44,7 +43,7 @@ tap.test('strictContentLength: false', (t) => { body: 'asd' }, (err, data) => { assertEmitWarningCalledAndReset() - t.error(err) + t.ifError(err) }) client.request({ @@ -56,7 +55,7 @@ tap.test('strictContentLength: false', (t) => { body: 'asdasdasdasdasdasda' }, (err, data) => { assertEmitWarningCalledAndReset() - t.error(err) + t.ifError(err) }) client.request({ @@ -68,7 +67,7 @@ tap.test('strictContentLength: false', (t) => { body: Buffer.alloc(9) }, (err, data) => { assertEmitWarningCalledAndReset() - t.error(err) + t.ifError(err) }) client.request({ @@ -80,7 +79,7 @@ tap.test('strictContentLength: false', (t) => { body: Buffer.alloc(11) }, (err, data) => { assertEmitWarningCalledAndReset() - t.error(err) + t.ifError(err) }) client.request({ @@ -90,7 +89,7 @@ tap.test('strictContentLength: false', (t) => { 'content-length': 10 } }, (err, data) => { - t.error(err) + t.ifError(err) }) client.request({ @@ -100,7 +99,7 @@ tap.test('strictContentLength: false', (t) => { 'content-length': 0 } }, (err, data) => { - t.error(err) + t.ifError(err) }) client.request({ @@ -116,7 +115,7 @@ tap.test('strictContentLength: false', (t) => { } }) }, (err, data) => { - t.error(err) + t.ifError(err) }) client.request({ @@ -132,24 +131,26 @@ tap.test('strictContentLength: false', (t) => { } }) }, (err, data) => { - t.error(err) + t.ifError(err) }) }) + + await t.completed }) - t.test('request streaming content-length less than body size', (t) => { - t.plan(1) + test('request streaming content-length less than body size', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { strictContentLength: false }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -167,24 +168,26 @@ tap.test('strictContentLength: false', (t) => { }) }, (err) => { assertEmitWarningCalledAndReset() - t.error(err) + t.ifError(err) }) }) + + await t.completed }) - t.test('request streaming content-length greater than body size', (t) => { - t.plan(1) + test('request streaming content-length greater than body size', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { strictContentLength: false }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -202,24 +205,26 @@ tap.test('strictContentLength: false', (t) => { }) }, (err) => { assertEmitWarningCalledAndReset() - t.error(err) + t.ifError(err) }) }) + + await t.completed }) - t.test('request streaming data when content-length=0', (t) => { - t.plan(1) + test('request streaming data when content-length=0', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { strictContentLength: false }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -237,24 +242,26 @@ tap.test('strictContentLength: false', (t) => { }) }, (err) => { assertEmitWarningCalledAndReset() - t.error(err) + t.ifError(err) }) }) + + await t.completed }) - t.test('request async iterating content-length less than body size', (t) => { - t.plan(1) + test('request async iterating content-length less than body size', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { strictContentLength: false }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -272,24 +279,26 @@ tap.test('strictContentLength: false', (t) => { })) }, (err) => { assertEmitWarningCalledAndReset() - t.error(err) + t.ifError(err) }) }) + + await t.completed }) - t.test('request async iterator content-length greater than body size', (t) => { - t.plan(1) + test('request async iterator content-length greater than body size', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { strictContentLength: false }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -307,24 +316,25 @@ tap.test('strictContentLength: false', (t) => { })) }, (err) => { assertEmitWarningCalledAndReset() - t.error(err) + t.ifError(err) }) }) + await t.completed }) - t.test('request async iterator data when content-length=0', (t) => { - t.plan(1) + test('request async iterator data when content-length=0', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { strictContentLength: false }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -342,8 +352,9 @@ tap.test('strictContentLength: false', (t) => { })) }, (err) => { assertEmitWarningCalledAndReset() - t.error(err) + t.ifError(err) }) }) + await t.completed }) }) diff --git a/test/proxy.js b/test/proxy.js index c910d7224d1..e57babc8bc5 100644 --- a/test/proxy.js +++ b/test/proxy.js @@ -1,12 +1,13 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test } = require('node:test') const { Client, Pool } = require('..') const { createServer } = require('node:http') const proxy = require('proxy') test('connect through proxy', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = await buildServer() const proxy = await buildProxy() @@ -15,7 +16,7 @@ test('connect through proxy', async (t) => { const proxyUrl = `http://localhost:${proxy.address().port}` server.on('request', (req, res) => { - t.equal(req.url, '/hello?foo=bar') + t.strictEqual(req.url, '/hello?foo=bar') res.setHeader('content-type', 'application/json') res.end(JSON.stringify({ hello: 'world' })) }) @@ -32,8 +33,8 @@ test('connect through proxy', async (t) => { for await (const chunk of response.body) { data += chunk } - t.equal(response.statusCode, 200) - t.same(JSON.parse(data), { hello: 'world' }) + t.strictEqual(response.statusCode, 200) + t.deepStrictEqual(JSON.parse(data), { hello: 'world' }) server.close() proxy.close() @@ -41,7 +42,7 @@ test('connect through proxy', async (t) => { }) test('connect through proxy with auth', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = await buildServer() const proxy = await buildProxy() @@ -54,7 +55,7 @@ test('connect through proxy with auth', async (t) => { } server.on('request', (req, res) => { - t.equal(req.url, '/hello?foo=bar') + t.strictEqual(req.url, '/hello?foo=bar') res.setHeader('content-type', 'application/json') res.end(JSON.stringify({ hello: 'world' })) }) @@ -74,8 +75,8 @@ test('connect through proxy with auth', async (t) => { for await (const chunk of response.body) { data += chunk } - t.equal(response.statusCode, 200) - t.same(JSON.parse(data), { hello: 'world' }) + t.strictEqual(response.statusCode, 200) + t.deepStrictEqual(JSON.parse(data), { hello: 'world' }) server.close() proxy.close() @@ -83,7 +84,7 @@ test('connect through proxy with auth', async (t) => { }) test('connect through proxy (with pool)', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = await buildServer() const proxy = await buildProxy() @@ -92,7 +93,7 @@ test('connect through proxy (with pool)', async (t) => { const proxyUrl = `http://localhost:${proxy.address().port}` server.on('request', (req, res) => { - t.equal(req.url, '/hello?foo=bar') + t.strictEqual(req.url, '/hello?foo=bar') res.setHeader('content-type', 'application/json') res.end(JSON.stringify({ hello: 'world' })) }) @@ -109,8 +110,8 @@ test('connect through proxy (with pool)', async (t) => { for await (const chunk of response.body) { data += chunk } - t.equal(response.statusCode, 200) - t.same(JSON.parse(data), { hello: 'world' }) + t.strictEqual(response.statusCode, 200) + t.deepStrictEqual(JSON.parse(data), { hello: 'world' }) server.close() proxy.close() diff --git a/test/readable.test.js b/test/readable.test.js index 535ecb66baa..3d6b5b1cea1 100644 --- a/test/readable.test.js +++ b/test/readable.test.js @@ -1,9 +1,12 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test } = require('node:test') const Readable = require('../lib/api/readable') test('avoid body reordering', async function (t) { + t = tspl(t, { plan: 1 }) + function resume () { } function abort () { @@ -19,28 +22,25 @@ test('avoid body reordering', async function (t) { const text = await r.text() - t.equal(text, 'helloworld') + t.strictEqual(text, 'helloworld') }) test('destroy timing text', async function (t) { - t.plan(1) + t = tspl(t, { plan: 1 }) function resume () { } function abort () { } - const _err = new Error('kaboom') + const r = new Readable({ resume, abort }) - r.destroy(_err) - try { - await r.text() - } catch (err) { - t.same(err, _err) - } + r.destroy(new Error('kaboom')) + + t.rejects(r.text(), new Error('kaboom')) }) test('destroy timing promise', async function (t) { - t.plan(1) + t = tspl(t, { plan: 1 }) function resume () { } diff --git a/test/request-crlf.js b/test/request-crlf.js index be33f767a4d..4e6921e2fb0 100644 --- a/test/request-crlf.js +++ b/test/request-crlf.js @@ -1,11 +1,13 @@ 'use strict' +const { tspl } = require('@matteo.collina/tspl') const { createServer } = require('node:http') -const { test } = require('tap') +const { test, after } = require('node:test') const { request, errors } = require('..') +const { once } = require('node:events') -test('should validate content-type CRLF Injection', (t) => { - t.plan(2) +test('should validate content-type CRLF Injection', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { t.fail('should not receive any request') @@ -13,20 +15,22 @@ test('should validate content-type CRLF Injection', (t) => { res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) - server.listen(0, async () => { - try { - await request(`http://localhost:${server.address().port}`, { - method: 'GET', - headers: { - 'content-type': 'application/json\r\n\r\nGET /foo2 HTTP/1.1' - } - }) - t.fail('request should fail') - } catch (e) { - t.ok(e instanceof errors.InvalidArgumentError) - t.equal(e.message, 'invalid content-type header') - } - }) + server.listen(0) + + await once(server, 'listening') + try { + await request(`http://localhost:${server.address().port}`, { + method: 'GET', + headers: { + 'content-type': 'application/json\r\n\r\nGET /foo2 HTTP/1.1' + } + }) + t.fail('request should fail') + } catch (e) { + t.ok(e instanceof errors.InvalidArgumentError) + t.strictEqual(e.message, 'invalid content-type header') + } + await t.completed }) diff --git a/test/request-timeout2.js b/test/request-timeout2.js index ff4f1ddfebc..a294b2fb9c1 100644 --- a/test/request-timeout2.js +++ b/test/request-timeout2.js @@ -1,12 +1,14 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') +const { once } = require('node:events') const { Client } = require('..') const { createServer } = require('node:http') const { Readable } = require('node:stream') -test('request timeout with slow readable body', (t) => { - t.plan(1) +test('request timeout with slow readable body', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer(async (req, res) => { let str = '' @@ -15,34 +17,37 @@ test('request timeout with slow readable body', (t) => { } res.end(str) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 50 }) - t.teardown(client.close.bind(client)) + server.listen(0) - const body = new Readable({ - read () { - if (this._reading) { - return - } - this._reading = true + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 50 }) + after(() => client.close()) - this.push('asd') - setTimeout(() => { - this.push('asd') - this.push(null) - }, 2e3) + const body = new Readable({ + read () { + if (this._reading) { + return } - }) - client.request({ - path: '/', - method: 'POST', - headersTimeout: 1e3, - body - }, async (err, response) => { - t.error(err) - await response.body.dump() - }) + this._reading = true + + this.push('asd') + setTimeout(() => { + this.push('asd') + this.push(null) + }, 2e3) + } + }) + client.request({ + path: '/', + method: 'POST', + headersTimeout: 1e3, + body + }, async (err, response) => { + t.ifError(err) + await response.body.dump() }) + + await t.completed }) From 07fe3609d266ddc2309c303d9d87c001bb534791 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Mon, 12 Feb 2024 12:08:16 +0100 Subject: [PATCH 16/23] chore: migrate a batch of tests to node test runner (#2741) --- test/content-length.js | 120 ++++++++++++++++++-------------- test/esm-wrapper.js | 2 +- test/fixed-queue.js | 21 +++--- test/promises.js | 121 ++++++++++++++++++-------------- test/proxy-agent.js | 121 ++++++++++++++++---------------- test/retry-handler.js | 129 ++++++++++++++++++++--------------- test/socket-back-pressure.js | 60 ++++++++-------- test/utils/esm-wrapper.mjs | 93 +++++++++++++------------ 8 files changed, 363 insertions(+), 304 deletions(-) diff --git a/test/content-length.js b/test/content-length.js index 6c124ed3530..847e2bca023 100644 --- a/test/content-length.js +++ b/test/content-length.js @@ -1,21 +1,22 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, errors } = require('..') const { createServer } = require('node:http') const { Readable } = require('node:stream') const { maybeWrapStream, consts } = require('./utils/async-iterators') -test('request invalid content-length', (t) => { - t.plan(7) +test('request invalid content-length', async (t) => { + t = tspl(t, { plan: 7 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -94,19 +95,21 @@ test('request invalid content-length', (t) => { t.ok(err instanceof errors.RequestContentLengthMismatchError) }) }) + + await t.completed }) function invalidContentLength (bodyType) { - test(`request streaming ${bodyType} invalid content-length`, (t) => { - t.plan(4) + test(`request streaming ${bodyType} invalid content-length`, async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.once('disconnect', () => { t.ok(true, 'pass') @@ -151,6 +154,7 @@ function invalidContentLength (bodyType) { t.ok(err instanceof errors.RequestContentLengthMismatchError) }) }) + await t.completed }) } @@ -158,16 +162,16 @@ invalidContentLength(consts.STREAM) invalidContentLength(consts.ASYNC_ITERATOR) function zeroContentLength (bodyType) { - test(`request ${bodyType} streaming data when content-length=0`, (t) => { - t.plan(1) + test(`request ${bodyType} streaming data when content-length=0`, async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -187,22 +191,23 @@ function zeroContentLength (bodyType) { t.ok(err instanceof errors.RequestContentLengthMismatchError) }) }) + await t.completed }) } zeroContentLength(consts.STREAM) zeroContentLength(consts.ASYNC_ITERATOR) -test('request streaming no body data when content-length=0', (t) => { - t.plan(2) +test('request streaming no body data when content-length=0', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -211,7 +216,7 @@ test('request streaming no body data when content-length=0', (t) => { 'content-length': 0 } }, (err, data) => { - t.error(err) + t.ifError(err) data.body .on('data', () => { t.fail() @@ -221,10 +226,12 @@ test('request streaming no body data when content-length=0', (t) => { }) }) }) + + await t.completed }) -test('response invalid content length with close', (t) => { - t.plan(3) +test('response invalid content length with close', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.writeHead(200, { @@ -232,42 +239,44 @@ test('response invalid content length with close', (t) => { }) res.end('123') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 0 }) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.on('disconnect', (origin, client, err) => { - t.equal(err.code, 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH') + t.strictEqual(err.code, 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH') }) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body .on('end', () => { t.fail() }) .on('error', (err) => { - t.equal(err.code, 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH') + t.strictEqual(err.code, 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH') }) .resume() }) }) + + await t.completed }) -test('request streaming with Readable.from(buf)', (t) => { +test('request streaming with Readable.from(buf)', async (t) => { const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -275,32 +284,34 @@ test('request streaming with Readable.from(buf)', (t) => { body: Readable.from(Buffer.from('hello')) }, (err, data) => { const chunks = [] - t.error(err) + t.ifError(err) data.body .on('data', (chunk) => { chunks.push(chunk) }) .on('end', () => { - t.equal(Buffer.concat(chunks).toString(), 'hello') + t.strictEqual(Buffer.concat(chunks).toString(), 'hello') t.ok(true, 'pass') t.end() }) }) }) + + await t.completed }) -test('request DELETE, content-length=0, with body', (t) => { - t.plan(5) +test('request DELETE, content-length=0, with body', async (t) => { + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { res.end() }) server.on('request', (req, res) => { - t.equal(req.headers['content-length'], undefined) + t.strictEqual(req.headers['content-length'], undefined) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -325,38 +336,41 @@ test('request DELETE, content-length=0, with body', (t) => { 'content-length': 0 } }, (err, resp) => { - t.equal(resp.headers['content-length'], '0') - t.error(err) + t.strictEqual(resp.headers['content-length'], '0') + t.ifError(err) }) client.on('disconnect', () => { t.ok(true, 'pass') }) }) + + await t.completed }) -test('content-length shouldSendContentLength=false', (t) => { - t.plan(15) +test('content-length shouldSendContentLength=false', async (t) => { + t = tspl(t, { plan: 15 }) + const server = createServer((req, res) => { res.end() }) server.on('request', (req, res) => { switch (req.url) { case '/put0': - t.equal(req.headers['content-length'], '0') + t.strictEqual(req.headers['content-length'], '0') break case '/head': - t.equal(req.headers['content-length'], undefined) + t.strictEqual(req.headers['content-length'], undefined) break case '/get': - t.equal(req.headers['content-length'], undefined) + t.strictEqual(req.headers['content-length'], undefined) break } }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.close()) client.request({ path: '/put0', @@ -365,8 +379,8 @@ test('content-length shouldSendContentLength=false', (t) => { 'content-length': 0 } }, (err, resp) => { - t.equal(resp.headers['content-length'], '0') - t.error(err) + t.strictEqual(resp.headers['content-length'], '0') + t.ifError(err) }) client.request({ @@ -376,8 +390,8 @@ test('content-length shouldSendContentLength=false', (t) => { 'content-length': 10 } }, (err, resp) => { - t.equal(resp.headers['content-length'], undefined) - t.error(err) + t.strictEqual(resp.headers['content-length'], undefined) + t.ifError(err) }) client.request({ @@ -387,7 +401,7 @@ test('content-length shouldSendContentLength=false', (t) => { 'content-length': 0 } }, (err) => { - t.error(err) + t.ifError(err) }) client.request({ @@ -403,7 +417,7 @@ test('content-length shouldSendContentLength=false', (t) => { } }) }, (err) => { - t.error(err) + t.ifError(err) }) client.request({ @@ -419,7 +433,7 @@ test('content-length shouldSendContentLength=false', (t) => { } }) }, (err) => { - t.error(err) + t.ifError(err) }) client.request({ @@ -435,11 +449,13 @@ test('content-length shouldSendContentLength=false', (t) => { } }) }, (err) => { - t.error(err) + t.ifError(err) }) client.on('disconnect', () => { t.ok(true, 'pass') }) }) + + await t.completed }) diff --git a/test/esm-wrapper.js b/test/esm-wrapper.js index 8adb3278719..241fb3ea876 100644 --- a/test/esm-wrapper.js +++ b/test/esm-wrapper.js @@ -5,7 +5,7 @@ await import('./utils/esm-wrapper.mjs') } catch (e) { if (e.message === 'Not supported') { - require('tap') // shows skipped + require('node:test') // shows skipped return } console.error(e.stack) diff --git a/test/fixed-queue.js b/test/fixed-queue.js index 812f421b280..cb878716e44 100644 --- a/test/fixed-queue.js +++ b/test/fixed-queue.js @@ -1,23 +1,24 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test } = require('node:test') const FixedQueue = require('../lib/node/fixed-queue') test('fixed queue 1', (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const queue = new FixedQueue() - t.equal(queue.head, queue.tail) + t.strictEqual(queue.head, queue.tail) t.ok(queue.isEmpty()) queue.push('a') t.ok(!queue.isEmpty()) - t.equal(queue.shift(), 'a') - t.equal(queue.shift(), null) + t.strictEqual(queue.shift(), 'a') + t.strictEqual(queue.shift(), null) }) test('fixed queue 2', (t) => { - t.plan(7 + 2047) + t = tspl(t, { plan: 7 + 2047 }) const queue = new FixedQueue() for (let i = 0; i < 2047; i++) { @@ -27,12 +28,12 @@ test('fixed queue 2', (t) => { queue.push('a') t.ok(!queue.head.isFull()) - t.not(queue.head, queue.tail) + t.notEqual(queue.head, queue.tail) for (let i = 0; i < 2047; i++) { - t.equal(queue.shift(), 'a') + t.strictEqual(queue.shift(), 'a') } - t.equal(queue.head, queue.tail) + t.strictEqual(queue.head, queue.tail) t.ok(!queue.isEmpty()) - t.equal(queue.shift(), 'a') + t.strictEqual(queue.shift(), 'a') t.ok(queue.isEmpty()) }) diff --git a/test/promises.js b/test/promises.js index 4188a125bd9..5d47adc3640 100644 --- a/test/promises.js +++ b/test/promises.js @@ -1,47 +1,50 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, Pool } = require('..') const { createServer } = require('node:http') const { readFileSync, createReadStream } = require('node:fs') const { wrapWithAsyncIterable } = require('./utils/async-iterators') -test('basic get, async await support', (t) => { - t.plan(5) +test('basic get, async await support', async (t) => { + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) try { const { statusCode, headers, body } = await client.request({ path: '/', method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) } catch (err) { t.fail(err) } }) + + await t.completed }) function postServer (t, expected) { return function (req, res) { - t.equal(req.url, '/') - t.equal(req.method, 'POST') + t.strictEqual(req.url, '/') + t.strictEqual(req.method, 'POST') req.setEncoding('utf8') let data = '' @@ -49,79 +52,83 @@ function postServer (t, expected) { req.on('data', function (d) { data += d }) req.on('end', () => { - t.equal(data, expected) + t.strictEqual(data, expected) res.end('hello') }) } } -test('basic POST with string, async await support', (t) => { - t.plan(5) +test('basic POST with string, async await support', async (t) => { + t = tspl(t, { plan: 5 }) const expected = readFileSync(__filename, 'utf8') const server = createServer(postServer(t, expected)) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) try { const { statusCode, body } = await client.request({ path: '/', method: 'POST', body: expected }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) } catch (err) { t.fail(err) } }) + + await t.completed }) -test('basic POST with Buffer, async await support', (t) => { - t.plan(5) +test('basic POST with Buffer, async await support', async (t) => { + t = tspl(t, { plan: 5 }) const expected = readFileSync(__filename) const server = createServer(postServer(t, expected.toString())) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) try { const { statusCode, body } = await client.request({ path: '/', method: 'POST', body: expected }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) } catch (err) { t.fail(err) } }) + + await t.completed }) -test('basic POST with stream, async await support', (t) => { - t.plan(5) +test('basic POST with stream, async await support', async (t) => { + t = tspl(t, { plan: 5 }) const expected = readFileSync(__filename, 'utf8') const server = createServer(postServer(t, expected)) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) try { const { statusCode, body } = await client.request({ @@ -132,31 +139,33 @@ test('basic POST with stream, async await support', (t) => { }, body: createReadStream(__filename) }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) } catch (err) { t.fail(err) } }) + + await t.completed }) -test('basic POST with async-iterator, async await support', (t) => { - t.plan(5) +test('basic POST with async-iterator, async await support', async (t) => { + t = tspl(t, { plan: 5 }) const expected = readFileSync(__filename, 'utf8') const server = createServer(postServer(t, expected)) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) try { const { statusCode, body } = await client.request({ @@ -167,23 +176,25 @@ test('basic POST with async-iterator, async await support', (t) => { }, body: wrapWithAsyncIterable(createReadStream(__filename)) }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) } catch (err) { t.fail(err) } }) + + await t.completed }) -test('20 times GET with pipelining 10, async await support', (t) => { +test('20 times GET with pipelining 10, async await support', async (t) => { const num = 20 - t.plan(2 * num + 1) + t = tspl(t, { plan: 2 * num + 1 }) const sleep = ms => new Promise((resolve, reject) => { setTimeout(resolve, ms) @@ -197,7 +208,7 @@ test('20 times GET with pipelining 10, async await support', (t) => { countGreaterThanOne = countGreaterThanOne || count > 1 res.end(req.url) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) // needed to check for a warning on the maxListeners on the socket function onWarning (warning) { @@ -206,7 +217,7 @@ test('20 times GET with pipelining 10, async await support', (t) => { } } process.on('warning', onWarning) - t.teardown(() => { + after(() => { process.removeListener('warning', onWarning) }) @@ -214,7 +225,7 @@ test('20 times GET with pipelining 10, async await support', (t) => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 10 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) for (let i = 0; i < num; i++) { makeRequest(i) @@ -228,18 +239,20 @@ test('20 times GET with pipelining 10, async await support', (t) => { } } }) + + await t.completed }) async function makeRequestAndExpectUrl (client, i, t) { try { const { statusCode, body } = await client.request({ path: '/' + i, method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('/' + i, Buffer.concat(bufs).toString('utf8')) + t.strictEqual('/' + i, Buffer.concat(bufs).toString('utf8')) }) } catch (err) { t.fail(err) @@ -247,34 +260,36 @@ async function makeRequestAndExpectUrl (client, i, t) { return true } -test('pool, async await support', (t) => { - t.plan(5) +test('pool, async await support', async (t) => { + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) try { const { statusCode, headers, body } = await client.request({ path: '/', method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) } catch (err) { t.fail(err) } }) + + await t.completed }) diff --git a/test/proxy-agent.js b/test/proxy-agent.js index 70e76756a54..87129d01472 100644 --- a/test/proxy-agent.js +++ b/test/proxy-agent.js @@ -1,6 +1,7 @@ 'use strict' -const { test, teardown } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { request, fetch, setGlobalDispatcher, getGlobalDispatcher } = require('..') const { InvalidArgumentError } = require('../lib/core/errors') const { readFileSync } = require('node:fs') @@ -12,13 +13,13 @@ const https = require('node:https') const proxy = require('proxy') test('should throw error when no uri is provided', (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) t.throws(() => new ProxyAgent(), InvalidArgumentError) t.throws(() => new ProxyAgent({}), InvalidArgumentError) }) test('using auth in combination with token should throw', (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) t.throws(() => new ProxyAgent({ auth: 'foo', token: 'Bearer bar', @@ -29,13 +30,13 @@ test('using auth in combination with token should throw', (t) => { }) test('should accept string and object as options', (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) t.doesNotThrow(() => new ProxyAgent('http://example.com')) t.doesNotThrow(() => new ProxyAgent({ uri: 'http://example.com' })) }) test('use proxy-agent to connect through proxy', async (t) => { - t.plan(6) + t = tspl(t, { plan: 6 }) const server = await buildServer() const proxy = await buildProxy() delete proxy.authenticate @@ -50,8 +51,8 @@ test('use proxy-agent to connect through proxy', async (t) => { }) server.on('request', (req, res) => { - t.equal(req.url, '/') - t.equal(req.headers.host, parsedOrigin.host, 'should not use proxyUrl as host') + t.strictEqual(req.url, '/') + t.strictEqual(req.headers.host, parsedOrigin.host, 'should not use proxyUrl as host') res.setHeader('content-type', 'application/json') res.end(JSON.stringify({ hello: 'world' })) }) @@ -63,9 +64,9 @@ test('use proxy-agent to connect through proxy', async (t) => { } = await request(serverUrl, { dispatcher: proxyAgent }) const json = await body.json() - t.equal(statusCode, 200) - t.same(json, { hello: 'world' }) - t.equal(headers.connection, 'keep-alive', 'should remain the connection open') + t.strictEqual(statusCode, 200) + t.deepStrictEqual(json, { hello: 'world' }) + t.strictEqual(headers.connection, 'keep-alive', 'should remain the connection open') server.close() proxy.close() @@ -73,7 +74,7 @@ test('use proxy-agent to connect through proxy', async (t) => { }) test('use proxy agent to connect through proxy using Pool', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = await buildServer() const proxy = await buildProxy() let resolveFirstConnect @@ -104,15 +105,15 @@ test('use proxy agent to connect through proxy using Pool', async (t) => { const proxyAgent = new ProxyAgent({ auth: Buffer.from('user:pass').toString('base64'), uri: proxyUrl, clientFactory }) const firstRequest = request(`${serverUrl}`, { dispatcher: proxyAgent }) const secondRequest = await request(`${serverUrl}`, { dispatcher: proxyAgent }) - t.equal((await firstRequest).statusCode, 200) - t.equal(secondRequest.statusCode, 200) + t.strictEqual((await firstRequest).statusCode, 200) + t.strictEqual(secondRequest.statusCode, 200) server.close() proxy.close() proxyAgent.close() }) test('use proxy-agent to connect through proxy using path with params', async (t) => { - t.plan(6) + t = tspl(t, { plan: 6 }) const server = await buildServer() const proxy = await buildProxy() @@ -125,8 +126,8 @@ test('use proxy-agent to connect through proxy using path with params', async (t t.ok(true, 'should call proxy') }) server.on('request', (req, res) => { - t.equal(req.url, '/hello?foo=bar') - t.equal(req.headers.host, parsedOrigin.host, 'should not use proxyUrl as host') + t.strictEqual(req.url, '/hello?foo=bar') + t.strictEqual(req.headers.host, parsedOrigin.host, 'should not use proxyUrl as host') res.setHeader('content-type', 'application/json') res.end(JSON.stringify({ hello: 'world' })) }) @@ -138,9 +139,9 @@ test('use proxy-agent to connect through proxy using path with params', async (t } = await request(serverUrl + '/hello?foo=bar', { dispatcher: proxyAgent }) const json = await body.json() - t.equal(statusCode, 200) - t.same(json, { hello: 'world' }) - t.equal(headers.connection, 'keep-alive', 'should remain the connection open') + t.strictEqual(statusCode, 200) + t.deepStrictEqual(json, { hello: 'world' }) + t.strictEqual(headers.connection, 'keep-alive', 'should remain the connection open') server.close() proxy.close() @@ -148,7 +149,7 @@ test('use proxy-agent to connect through proxy using path with params', async (t }) test('use proxy-agent with auth', async (t) => { - t.plan(7) + t = tspl(t, { plan: 7 }) const server = await buildServer() const proxy = await buildProxy() @@ -169,8 +170,8 @@ test('use proxy-agent with auth', async (t) => { }) server.on('request', (req, res) => { - t.equal(req.url, '/hello?foo=bar') - t.equal(req.headers.host, parsedOrigin.host, 'should not use proxyUrl as host') + t.strictEqual(req.url, '/hello?foo=bar') + t.strictEqual(req.headers.host, parsedOrigin.host, 'should not use proxyUrl as host') res.setHeader('content-type', 'application/json') res.end(JSON.stringify({ hello: 'world' })) }) @@ -182,9 +183,9 @@ test('use proxy-agent with auth', async (t) => { } = await request(serverUrl + '/hello?foo=bar', { dispatcher: proxyAgent }) const json = await body.json() - t.equal(statusCode, 200) - t.same(json, { hello: 'world' }) - t.equal(headers.connection, 'keep-alive', 'should remain the connection open') + t.strictEqual(statusCode, 200) + t.deepStrictEqual(json, { hello: 'world' }) + t.strictEqual(headers.connection, 'keep-alive', 'should remain the connection open') server.close() proxy.close() @@ -192,7 +193,7 @@ test('use proxy-agent with auth', async (t) => { }) test('use proxy-agent with token', async (t) => { - t.plan(7) + t = tspl(t, { plan: 7 }) const server = await buildServer() const proxy = await buildProxy() @@ -213,8 +214,8 @@ test('use proxy-agent with token', async (t) => { }) server.on('request', (req, res) => { - t.equal(req.url, '/hello?foo=bar') - t.equal(req.headers.host, parsedOrigin.host, 'should not use proxyUrl as host') + t.strictEqual(req.url, '/hello?foo=bar') + t.strictEqual(req.headers.host, parsedOrigin.host, 'should not use proxyUrl as host') res.setHeader('content-type', 'application/json') res.end(JSON.stringify({ hello: 'world' })) }) @@ -226,9 +227,9 @@ test('use proxy-agent with token', async (t) => { } = await request(serverUrl + '/hello?foo=bar', { dispatcher: proxyAgent }) const json = await body.json() - t.equal(statusCode, 200) - t.same(json, { hello: 'world' }) - t.equal(headers.connection, 'keep-alive', 'should remain the connection open') + t.strictEqual(statusCode, 200) + t.deepStrictEqual(json, { hello: 'world' }) + t.strictEqual(headers.connection, 'keep-alive', 'should remain the connection open') server.close() proxy.close() @@ -236,7 +237,7 @@ test('use proxy-agent with token', async (t) => { }) test('use proxy-agent with custom headers', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const server = await buildServer() const proxy = await buildProxy() @@ -250,11 +251,11 @@ test('use proxy-agent with custom headers', async (t) => { }) proxy.on('connect', (req) => { - t.equal(req.headers['user-agent'], 'Foobar/1.0.0') + t.strictEqual(req.headers['user-agent'], 'Foobar/1.0.0') }) server.on('request', (req, res) => { - t.equal(req.headers['user-agent'], 'BarBaz/1.0.0') + t.strictEqual(req.headers['user-agent'], 'BarBaz/1.0.0') res.end() }) @@ -269,7 +270,7 @@ test('use proxy-agent with custom headers', async (t) => { }) test('sending proxy-authorization in request headers should throw', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = await buildServer() const proxy = await buildProxy() @@ -326,7 +327,7 @@ test('sending proxy-authorization in request headers should throw', async (t) => }) test('use proxy-agent with setGlobalDispatcher', async (t) => { - t.plan(6) + t = tspl(t, { plan: 6 }) const defaultDispatcher = getGlobalDispatcher() const server = await buildServer() @@ -338,14 +339,14 @@ test('use proxy-agent with setGlobalDispatcher', async (t) => { const parsedOrigin = new URL(serverUrl) setGlobalDispatcher(proxyAgent) - t.teardown(() => setGlobalDispatcher(defaultDispatcher)) + after(() => setGlobalDispatcher(defaultDispatcher)) proxy.on('connect', () => { t.ok(true, 'should call proxy') }) server.on('request', (req, res) => { - t.equal(req.url, '/hello?foo=bar') - t.equal(req.headers.host, parsedOrigin.host, 'should not use proxyUrl as host') + t.strictEqual(req.url, '/hello?foo=bar') + t.strictEqual(req.headers.host, parsedOrigin.host, 'should not use proxyUrl as host') res.setHeader('content-type', 'application/json') res.end(JSON.stringify({ hello: 'world' })) }) @@ -357,9 +358,9 @@ test('use proxy-agent with setGlobalDispatcher', async (t) => { } = await request(serverUrl + '/hello?foo=bar') const json = await body.json() - t.equal(statusCode, 200) - t.same(json, { hello: 'world' }) - t.equal(headers.connection, 'keep-alive', 'should remain the connection open') + t.strictEqual(statusCode, 200) + t.deepStrictEqual(json, { hello: 'world' }) + t.strictEqual(headers.connection, 'keep-alive', 'should remain the connection open') server.close() proxy.close() @@ -367,7 +368,7 @@ test('use proxy-agent with setGlobalDispatcher', async (t) => { }) test('ProxyAgent correctly sends headers when using fetch - #1355, #1623', async (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const defaultDispatcher = getGlobalDispatcher() const server = await buildServer() @@ -379,7 +380,7 @@ test('ProxyAgent correctly sends headers when using fetch - #1355, #1623', async const proxyAgent = new ProxyAgent(proxyUrl) setGlobalDispatcher(proxyAgent) - t.teardown(() => setGlobalDispatcher(defaultDispatcher)) + after(() => setGlobalDispatcher(defaultDispatcher)) const expectedHeaders = { host: `localhost:${server.address().port}`, @@ -398,11 +399,11 @@ test('ProxyAgent correctly sends headers when using fetch - #1355, #1623', async } proxy.on('connect', (req, res) => { - t.same(req.headers, expectedProxyHeaders) + t.deepStrictEqual(req.headers, expectedProxyHeaders) }) server.on('request', (req, res) => { - t.same(req.headers, expectedHeaders) + t.deepStrictEqual(req.headers, expectedHeaders) res.end('goodbye') }) @@ -417,6 +418,8 @@ test('ProxyAgent correctly sends headers when using fetch - #1355, #1623', async }) test('should throw when proxy does not return 200', async (t) => { + t = tspl(t, { plan: 2 }) + const server = await buildServer() const proxy = await buildProxy() @@ -439,10 +442,11 @@ test('should throw when proxy does not return 200', async (t) => { server.close() proxy.close() proxyAgent.close() - t.end() + await t.completed }) test('pass ProxyAgent proxy status code error when using fetch - #2161', async (t) => { + t = tspl(t, { plan: 1 }) const server = await buildServer() const proxy = await buildProxy() @@ -457,17 +461,18 @@ test('pass ProxyAgent proxy status code error when using fetch - #2161', async ( try { await fetch(serverUrl, { dispatcher: proxyAgent }) } catch (e) { - t.hasProp(e, 'cause') + t.ok('cause' in e) } server.close() proxy.close() proxyAgent.close() - t.end() + + await t.completed }) test('Proxy via HTTP to HTTPS endpoint', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const server = await buildSSLServer() const proxy = await buildProxy() @@ -509,7 +514,7 @@ test('Proxy via HTTP to HTTPS endpoint', async (t) => { const data = await request(serverUrl, { dispatcher: proxyAgent }) const json = await data.body.json() - t.strictSame(json, { + t.deepStrictEqual(json, { host: `localhost:${server.address().port}`, connection: 'keep-alive' }) @@ -520,7 +525,7 @@ test('Proxy via HTTP to HTTPS endpoint', async (t) => { }) test('Proxy via HTTPS to HTTPS endpoint', async (t) => { - t.plan(5) + t = tspl(t, { plan: 5 }) const server = await buildSSLServer() const proxy = await buildSSLProxy() @@ -570,7 +575,7 @@ test('Proxy via HTTPS to HTTPS endpoint', async (t) => { const data = await request(serverUrl, { dispatcher: proxyAgent }) const json = await data.body.json() - t.strictSame(json, { + t.deepStrictEqual(json, { host: `localhost:${server.address().port}`, connection: 'keep-alive' }) @@ -581,7 +586,7 @@ test('Proxy via HTTPS to HTTPS endpoint', async (t) => { }) test('Proxy via HTTPS to HTTP endpoint', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = await buildServer() const proxy = await buildSSLProxy() @@ -619,7 +624,7 @@ test('Proxy via HTTPS to HTTP endpoint', async (t) => { const data = await request(serverUrl, { dispatcher: proxyAgent }) const json = await data.body.json() - t.strictSame(json, { + t.deepStrictEqual(json, { host: `localhost:${server.address().port}`, connection: 'keep-alive' }) @@ -630,7 +635,7 @@ test('Proxy via HTTPS to HTTP endpoint', async (t) => { }) test('Proxy via HTTP to HTTP endpoint', async (t) => { - t.plan(3) + t = tspl(t, { plan: 3 }) const server = await buildServer() const proxy = await buildProxy() @@ -661,7 +666,7 @@ test('Proxy via HTTP to HTTP endpoint', async (t) => { const data = await request(serverUrl, { dispatcher: proxyAgent }) const json = await data.body.json() - t.strictSame(json, { + t.deepStrictEqual(json, { host: `localhost:${server.address().port}`, connection: 'keep-alive' }) @@ -715,5 +720,3 @@ function buildSSLProxy () { server.listen(0, () => resolve(server)) }) } - -teardown(() => process.exit()) diff --git a/test/retry-handler.js b/test/retry-handler.js index b4000606f62..f6b83cd34dd 100644 --- a/test/retry-handler.js +++ b/test/retry-handler.js @@ -1,13 +1,16 @@ 'use strict' + +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { createServer } = require('node:http') const { once } = require('node:events') -const tap = require('tap') - const { RetryHandler, Client } = require('..') const { RequestHandler } = require('../lib/api/api-request') -tap.test('Should retry status code', t => { +test('Should retry status code', async t => { + t = tspl(t, { plan: 4 }) + let counter = 0 const chunks = [] const server = createServer() @@ -34,8 +37,6 @@ tap.test('Should retry status code', t => { } } - t.plan(4) - server.on('request', (req, res) => { switch (counter) { case 0: @@ -66,7 +67,7 @@ tap.test('Should retry status code', t => { t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { - t.equal(status, 200) + t.strictEqual(status, 200) return true }, onData (chunk) { @@ -74,8 +75,8 @@ tap.test('Should retry status code', t => { return true }, onComplete () { - t.equal(Buffer.concat(chunks).toString('utf-8'), 'hello world!') - t.equal(counter, 2) + t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') + t.strictEqual(counter, 2) }, onError () { t.fail() @@ -83,7 +84,7 @@ tap.test('Should retry status code', t => { } }) - t.teardown(async () => { + after(async () => { await client.close() server.close() @@ -101,9 +102,13 @@ tap.test('Should retry status code', t => { handler ) }) + + await t.completed }) -tap.test('Should use retry-after header for retries', t => { +test('Should use retry-after header for retries', async t => { + t = tspl(t, { plan: 4 }) + let counter = 0 const chunks = [] const server = createServer() @@ -116,8 +121,6 @@ tap.test('Should use retry-after header for retries', t => { } } - t.plan(4) - server.on('request', (req, res) => { switch (counter) { case 0: @@ -151,7 +154,7 @@ tap.test('Should use retry-after header for retries', t => { t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { - t.equal(status, 200) + t.strictEqual(status, 200) return true }, onData (chunk) { @@ -159,15 +162,15 @@ tap.test('Should use retry-after header for retries', t => { return true }, onComplete () { - t.equal(Buffer.concat(chunks).toString('utf-8'), 'hello world!') + t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, onError (err) { - t.error(err) + t.ifError(err) } } }) - t.teardown(async () => { + after(async () => { await client.close() server.close() @@ -185,9 +188,13 @@ tap.test('Should use retry-after header for retries', t => { handler ) }) + + await t.completed }) -tap.test('Should use retry-after header for retries (date)', t => { +test('Should use retry-after header for retries (date)', async t => { + t = tspl(t, { plan: 4 }) + let counter = 0 const chunks = [] const server = createServer() @@ -200,8 +207,6 @@ tap.test('Should use retry-after header for retries (date)', t => { } } - t.plan(4) - server.on('request', (req, res) => { switch (counter) { case 0: @@ -237,7 +242,7 @@ tap.test('Should use retry-after header for retries (date)', t => { t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { - t.equal(status, 200) + t.strictEqual(status, 200) return true }, onData (chunk) { @@ -245,15 +250,15 @@ tap.test('Should use retry-after header for retries (date)', t => { return true }, onComplete () { - t.equal(Buffer.concat(chunks).toString('utf-8'), 'hello world!') + t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, onError (err) { - t.error(err) + t.ifError(err) } } }) - t.teardown(async () => { + after(async () => { await client.close() server.close() @@ -271,9 +276,13 @@ tap.test('Should use retry-after header for retries (date)', t => { handler ) }) + + await t.completed }) -tap.test('Should retry with defaults', t => { +test('Should retry with defaults', async t => { + t = tspl(t, { plan: 3 }) + let counter = 0 const chunks = [] const server = createServer() @@ -306,8 +315,6 @@ tap.test('Should retry with defaults', t => { } }) - t.plan(3) - server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) const handler = new RetryHandler(dispatchOptions, { @@ -320,7 +327,7 @@ tap.test('Should retry with defaults', t => { t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { - t.equal(status, 200) + t.strictEqual(status, 200) return true }, onData (chunk) { @@ -328,15 +335,15 @@ tap.test('Should retry with defaults', t => { return true }, onComplete () { - t.equal(Buffer.concat(chunks).toString('utf-8'), 'hello world!') + t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, onError (err) { - t.error(err) + t.ifError(err) } } }) - t.teardown(async () => { + after(async () => { await client.close() server.close() @@ -354,9 +361,13 @@ tap.test('Should retry with defaults', t => { handler ) }) + + await t.completed }) -tap.test('Should handle 206 partial content', t => { +test('Should handle 206 partial content', async t => { + t = tspl(t, { plan: 8 }) + const chunks = [] let counter = 0 @@ -371,7 +382,7 @@ tap.test('Should handle 206 partial content', t => { res.destroy() }, 1e2) } else if (x === 1) { - t.same(req.headers.range, 'bytes=3-') + t.deepStrictEqual(req.headers.range, 'bytes=3-') res.setHeader('content-range', 'bytes 3-6/6') res.setHeader('etag', 'asd') res.statusCode = 206 @@ -401,8 +412,6 @@ tap.test('Should handle 206 partial content', t => { } } - t.plan(8) - server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) const handler = new RetryHandler(dispatchOptions, { @@ -420,7 +429,7 @@ tap.test('Should handle 206 partial content', t => { t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { - t.equal(status, 200) + t.strictEqual(status, 200) return true }, onData (chunk) { @@ -428,8 +437,8 @@ tap.test('Should handle 206 partial content', t => { return true }, onComplete () { - t.equal(Buffer.concat(chunks).toString('utf-8'), 'abcdef') - t.equal(counter, 1) + t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') + t.strictEqual(counter, 1) }, onError () { t.fail() @@ -448,16 +457,20 @@ tap.test('Should handle 206 partial content', t => { handler ) - t.teardown(async () => { + after(async () => { await client.close() server.close() await once(server, 'close') }) }) + + await t.completed }) -tap.test('Should handle 206 partial content - bad-etag', t => { +test('Should handle 206 partial content - bad-etag', async t => { + t = tspl(t, { plan: 6 }) + const chunks = [] // Took from: https://github.com/nxtedition/nxt-lib/blob/4b001ebc2f22cf735a398f35ff800dd553fe5933/test/undici/retry.js#L47 @@ -471,7 +484,7 @@ tap.test('Should handle 206 partial content - bad-etag', t => { res.destroy() }, 1e2) } else if (x === 1) { - t.same(req.headers.range, 'bytes=3-') + t.deepStrictEqual(req.headers.range, 'bytes=3-') res.setHeader('content-range', 'bytes 3-6/6') res.setHeader('etag', 'erwsd') res.statusCode = 206 @@ -488,8 +501,6 @@ tap.test('Should handle 206 partial content - bad-etag', t => { } } - t.plan(6) - server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) const handler = new RetryHandler( @@ -514,11 +525,11 @@ tap.test('Should handle 206 partial content - bad-etag', t => { return true }, onComplete () { - t.error('should not complete') + t.ifError('should not complete') }, onError (err) { - t.equal(Buffer.concat(chunks).toString('utf-8'), 'abc') - t.equal(err.code, 'UND_ERR_REQ_RETRY') + t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abc') + t.strictEqual(err.code, 'UND_ERR_REQ_RETRY') } } } @@ -535,16 +546,18 @@ tap.test('Should handle 206 partial content - bad-etag', t => { handler ) - t.teardown(async () => { + after(async () => { await client.close() server.close() await once(server, 'close') }) }) + + await t.completed }) -tap.test('retrying a request with a body', t => { +test('retrying a request with a body', async t => { let counter = 0 const server = createServer() const dispatchOptions = { @@ -571,7 +584,7 @@ tap.test('retrying a request with a body', t => { body: JSON.stringify({ hello: 'world' }) } - t.plan(1) + t = tspl(t, { plan: 1 }) server.on('request', (req, res) => { switch (counter) { @@ -596,11 +609,11 @@ tap.test('retrying a request with a body', t => { const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: new RequestHandler(dispatchOptions, (err, data) => { - t.error(err) + t.ifError(err) }) }) - t.teardown(async () => { + after(async () => { await client.close() server.close() @@ -619,17 +632,19 @@ tap.test('retrying a request with a body', t => { handler ) }) + + await t.completed }) -tap.test('should not error if request is not meant to be retried', t => { +test('should not error if request is not meant to be retried', async t => { + t = tspl(t, { plan: 3 }) + const server = createServer() server.on('request', (req, res) => { res.writeHead(400) res.end('Bad request') }) - t.plan(3) - const dispatchOptions = { retryOptions: { method: 'GET', @@ -653,7 +668,7 @@ tap.test('should not error if request is not meant to be retried', t => { t.ok(true, 'pass') }, onHeaders (status, _rawHeaders, resume, _statusMessage) { - t.equal(status, 400) + t.strictEqual(status, 400) return true }, onData (chunk) { @@ -661,7 +676,7 @@ tap.test('should not error if request is not meant to be retried', t => { return true }, onComplete () { - t.equal(Buffer.concat(chunks).toString('utf-8'), 'Bad request') + t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'Bad request') }, onError (err) { console.log({ err }) @@ -670,7 +685,7 @@ tap.test('should not error if request is not meant to be retried', t => { } }) - t.teardown(async () => { + after(async () => { await client.close() server.close() @@ -688,4 +703,6 @@ tap.test('should not error if request is not meant to be retried', t => { handler ) }) + + await t.completed }) diff --git a/test/socket-back-pressure.js b/test/socket-back-pressure.js index bdc2c74346f..043e815ed9a 100644 --- a/test/socket-back-pressure.js +++ b/test/socket-back-pressure.js @@ -1,12 +1,14 @@ 'use strict' +const { tspl } = require('@matteo.collina/tspl') +const { once } = require('node:events') const { Client } = require('..') const { createServer } = require('node:http') const { Readable } = require('node:stream') -const { test } = require('tap') +const { test, after } = require('node:test') -test('socket back-pressure', (t) => { - t.plan(3) +test('socket back-pressure', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer() let bytesWritten = 0 @@ -25,30 +27,32 @@ test('socket back-pressure', (t) => { server.on('request', (req, res) => { src.pipe(res) }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`, { - pipelining: 1 - }) - t.teardown(client.destroy.bind(client)) - - client.request({ path: '/', method: 'GET', opaque: 'asd' }, (err, data) => { - t.error(err) - data.body - .resume() - .once('data', () => { - data.body.pause() - // TODO: Try to avoid timeout. - setTimeout(() => { - t.ok(data.body._readableState.length < bytesWritten - data.body._readableState.highWaterMark) - src.push(null) - data.body.resume() - }, 1e3) - }) - .on('end', () => { - t.ok(true, 'pass') - }) - }) + after(() => server.close()) + + server.listen(0) + + await once(server, 'listening') + const client = new Client(`http://localhost:${server.address().port}`, { + pipelining: 1 + }) + after(() => client.close()) + + client.request({ path: '/', method: 'GET', opaque: 'asd' }, (err, data) => { + t.ifError(err) + data.body + .resume() + .once('data', () => { + data.body.pause() + // TODO: Try to avoid timeout. + setTimeout(() => { + t.ok(data.body._readableState.length < bytesWritten - data.body._readableState.highWaterMark) + src.push(null) + data.body.resume() + }, 1e3) + }) + .on('end', () => { + t.ok(true, 'pass') + }) }) + await t.completed }) diff --git a/test/utils/esm-wrapper.mjs b/test/utils/esm-wrapper.mjs index 0e8ac9ffb7a..104190c1afe 100644 --- a/test/utils/esm-wrapper.mjs +++ b/test/utils/esm-wrapper.mjs @@ -1,5 +1,7 @@ +import { tspl } from '@matteo.collina/tspl' import { createServer } from 'http' -import tap from 'tap' +import { test, after } from 'node:test' +import { once } from 'node:events' import { Agent, Client, @@ -14,55 +16,56 @@ import { stream } from '../../index.js' -const { test } = tap - -test('imported Client works with basic GET', (t) => { - t.plan(10) +test('imported Client works with basic GET', async (t) => { + t = tspl(t, { plan: 10 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) - t.equal(undefined, req.headers.foo) - t.equal('bar', req.headers.bar) - t.equal(undefined, req.headers['content-length']) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual(undefined, req.headers.foo) + t.strictEqual('bar', req.headers.bar) + t.strictEqual(undefined, req.headers['content-length']) res.setHeader('Content-Type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const reqHeaders = { foo: undefined, bar: 'bar' } - server.listen(0, () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) - - client.request({ - path: '/', - method: 'GET', - headers: reqHeaders - }, (err, data) => { - t.error(err) - const { statusCode, headers, body } = data - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') - const bufs = [] - body.on('data', (buf) => { - bufs.push(buf) - }) - body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) - }) + server.listen(0) + + await once(server, 'listening') + + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) + + client.request({ + path: '/', + method: 'GET', + headers: reqHeaders + }, (err, data) => { + t.ifError(err) + const { statusCode, headers, body } = data + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') + const bufs = [] + body.on('data', (buf) => { + bufs.push(buf) + }) + body.on('end', () => { + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) + await t.completed }) test('imported errors work with request args validation', (t) => { - t.plan(2) + t = tspl(t, { plan: 2 }) const client = new Client('http://localhost:5000') @@ -78,7 +81,7 @@ test('imported errors work with request args validation', (t) => { }) test('imported errors work with request args validation promise', (t) => { - t.plan(1) + t = tspl(t, { plan: 1 }) const client = new Client('http://localhost:5000') @@ -88,15 +91,15 @@ test('imported errors work with request args validation promise', (t) => { }) test('named exports', (t) => { - t.equal(typeof Client, 'function') - t.equal(typeof Pool, 'function') - t.equal(typeof Agent, 'function') - t.equal(typeof request, 'function') - t.equal(typeof stream, 'function') - t.equal(typeof pipeline, 'function') - t.equal(typeof connect, 'function') - t.equal(typeof upgrade, 'function') - t.equal(typeof setGlobalDispatcher, 'function') - t.equal(typeof getGlobalDispatcher, 'function') - t.end() + t = tspl(t, { plan: 10 }) + t.strictEqual(typeof Client, 'function') + t.strictEqual(typeof Pool, 'function') + t.strictEqual(typeof Agent, 'function') + t.strictEqual(typeof request, 'function') + t.strictEqual(typeof stream, 'function') + t.strictEqual(typeof pipeline, 'function') + t.strictEqual(typeof connect, 'function') + t.strictEqual(typeof upgrade, 'function') + t.strictEqual(typeof setGlobalDispatcher, 'function') + t.strictEqual(typeof getGlobalDispatcher, 'function') }) From 8218436c1cb2f3151021f06796a5cb040629f45e Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Mon, 12 Feb 2024 16:01:02 +0100 Subject: [PATCH 17/23] chore: migrate a batch of tests to node test runner (#2744) --- test/client-pipeline.js | 380 ++++++++++++++++++++-------------- test/client-pipelining.js | 226 +++++++++++--------- test/client-timeout.js | 57 ++--- test/client-upgrade.js | 163 ++++++++------- test/get-head-body.js | 65 +++--- test/http2-alpn.js | 19 +- test/http2.js | 423 ++++++++++++++++++++------------------ test/readable.test.js | 2 +- test/request.js | 181 ++++++++-------- 9 files changed, 838 insertions(+), 678 deletions(-) diff --git a/test/client-pipeline.js b/test/client-pipeline.js index cbc78b9270d..bc2cd1d3a95 100644 --- a/test/client-pipeline.js +++ b/test/client-pipeline.js @@ -1,6 +1,7 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, errors } = require('..') const EE = require('node:events') const { createServer } = require('node:http') @@ -12,30 +13,30 @@ const { PassThrough } = require('node:stream') -test('pipeline get', (t) => { - t.plan(17) +test('pipeline get', async (t) => { + t = tspl(t, { plan: 17 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) - t.equal(undefined, req.headers['content-length']) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual(undefined, req.headers['content-length']) res.setHeader('Content-Type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) { const bufs = [] const signal = new EE() client.pipeline({ signal, path: '/', method: 'GET' }, ({ statusCode, headers, body }) => { - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') + t.strictEqual(signal.listenerCount('abort'), 1) return body }) .end() @@ -43,19 +44,19 @@ test('pipeline get', (t) => { bufs.push(buf) }) .on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) .on('close', () => { - t.equal(signal.listenerCount('abort'), 0) + t.strictEqual(signal.listenerCount('abort'), 0) }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) } { const bufs = [] client.pipeline({ path: '/', method: 'GET' }, ({ statusCode, headers, body }) => { - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') return body }) .end() @@ -63,23 +64,25 @@ test('pipeline get', (t) => { bufs.push(buf) }) .on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) } }) + + await t.completed }) -test('pipeline echo', (t) => { - t.plan(2) +test('pipeline echo', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) let res = '' const buf1 = Buffer.alloc(1e3).toString() @@ -104,19 +107,21 @@ test('pipeline echo', (t) => { callback() }, final (callback) { - t.equal(res, buf1 + buf2) + t.strictEqual(res, buf1 + buf2) callback() } }), (err) => { - t.error(err) + t.ifError(err) } ) }) + + await t.completed }) -test('pipeline ignore request body', (t) => { - t.plan(2) +test('pipeline ignore request body', async (t) => { + t = tspl(t, { plan: 2 }) let done const server = createServer((req, res) => { @@ -124,11 +129,11 @@ test('pipeline ignore request body', (t) => { res.end() done() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) let res = '' const buf1 = Buffer.alloc(1e3).toString() @@ -153,71 +158,77 @@ test('pipeline ignore request body', (t) => { callback() }, final (callback) { - t.equal(res, 'asd') + t.strictEqual(res, 'asd') callback() } }), (err) => { - t.error(err) + t.ifError(err) } ) }) + + await t.completed }) -test('pipeline invalid handler', (t) => { - t.plan(1) +test('pipeline invalid handler', async (t) => { + t = tspl(t, { plan: 1 }) const client = new Client('http://localhost:5000') client.pipeline({}, null).on('error', (err) => { t.ok(/handler/.test(err)) }) + + await t.completed }) -test('pipeline invalid handler return after destroy should not error', (t) => { - t.plan(3) +test('pipeline invalid handler return after destroy should not error', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 3 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const dup = client.pipeline({ path: '/', method: 'GET' }, ({ body }) => { body.on('error', (err) => { - t.equal(err.message, 'asd') + t.strictEqual(err.message, 'asd') }) dup.destroy(new Error('asd')) return {} }) .on('error', (err) => { - t.equal(err.message, 'asd') + t.strictEqual(err.message, 'asd') }) .on('close', () => { t.ok(true, 'pass') }) .end() }) + + await t.completed }) -test('pipeline error body', (t) => { - t.plan(2) +test('pipeline error body', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const buf = Buffer.alloc(1e6).toString() pipeline( @@ -245,19 +256,21 @@ test('pipeline error body', (t) => { } ) }) + + await t.completed }) -test('pipeline destroy body', (t) => { - t.plan(2) +test('pipeline destroy body', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const buf = Buffer.alloc(1e6).toString() pipeline( @@ -285,19 +298,21 @@ test('pipeline destroy body', (t) => { } ) }) + + await t.completed }) -test('pipeline backpressure', (t) => { - t.plan(1) +test('pipeline backpressure', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const buf = Buffer.alloc(1e6).toString() const duplex = client.pipeline({ @@ -318,19 +333,21 @@ test('pipeline backpressure', (t) => { t.ok(true, 'pass') }) }) + + await t.completed }) -test('pipeline invalid handler return', (t) => { - t.plan(2) +test('pipeline invalid handler return', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -357,19 +374,21 @@ test('pipeline invalid handler return', (t) => { }) .end() }) + + await t.completed }) -test('pipeline throw handler', (t) => { - t.plan(1) +test('pipeline throw handler', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -380,23 +399,25 @@ test('pipeline throw handler', (t) => { throw new Error('asd') }) .on('error', (err) => { - t.equal(err.message, 'asd') + t.strictEqual(err.message, 'asd') }) .end() }) + + await t.completed }) -test('pipeline destroy and throw handler', (t) => { - t.plan(2) +test('pipeline destroy and throw handler', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const dup = client.pipeline({ path: '/', @@ -415,21 +436,23 @@ test('pipeline destroy and throw handler', (t) => { t.ok(true, 'pass') }) }) + + await t.completed }) -test('pipeline abort res', (t) => { - t.plan(2) +test('pipeline abort res', async (t) => { + t = tspl(t, { plan: 2 }) let _res const server = createServer((req, res) => { res.write('asd') _res = res }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -453,19 +476,21 @@ test('pipeline abort res', (t) => { }) .end() }) + + await t.completed }) -test('pipeline abort server res', (t) => { - t.plan(1) +test('pipeline abort server res', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.destroy() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -478,25 +503,27 @@ test('pipeline abort server res', (t) => { }) .end() }) + + await t.completed }) -test('pipeline abort duplex', (t) => { - t.plan(2) +test('pipeline abort duplex', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'PUT' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() client.pipeline({ @@ -509,19 +536,21 @@ test('pipeline abort duplex', (t) => { }) }) }) + + await t.completed }) -test('pipeline abort piped res', (t) => { - t.plan(1) +test('pipeline abort piped res', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.write('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -534,23 +563,25 @@ test('pipeline abort piped res', (t) => { return pipeline(body, pt, () => {}) }) .on('error', (err) => { - t.equal(err.code, 'UND_ERR_ABORTED') + t.strictEqual(err.code, 'UND_ERR_ABORTED') }) .end() }) + + await t.completed }) -test('pipeline abort piped res 2', (t) => { - t.plan(2) +test('pipeline abort piped res 2', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.write('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -571,19 +602,21 @@ test('pipeline abort piped res 2', (t) => { }) .end() }) + + await t.completed }) -test('pipeline abort piped res 3', (t) => { - t.plan(2) +test('pipeline abort piped res 3', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.write('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -591,7 +624,7 @@ test('pipeline abort piped res 3', (t) => { }, ({ body }) => { const pt = new PassThrough() body.on('error', (err) => { - t.equal(err.message, 'asd') + t.strictEqual(err.message, 'asd') }) setImmediate(() => { pt.destroy(new Error('asd')) @@ -600,25 +633,27 @@ test('pipeline abort piped res 3', (t) => { return pt }) .on('error', (err) => { - t.equal(err.message, 'asd') + t.strictEqual(err.message, 'asd') }) .end() }) + + await t.completed }) -test('pipeline abort server res after headers', (t) => { - t.plan(1) +test('pipeline abort server res after headers', async (t) => { + t = tspl(t, { plan: 1 }) let _res const server = createServer((req, res) => { res.write('asd') _res = res }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -632,21 +667,23 @@ test('pipeline abort server res after headers', (t) => { }) .end() }) + + await t.completed }) -test('pipeline w/ write abort server res after headers', (t) => { - t.plan(1) +test('pipeline w/ write abort server res after headers', async (t) => { + t = tspl(t, { plan: 1 }) let _res const server = createServer((req, res) => { req.pipe(res) _res = res }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -661,21 +698,23 @@ test('pipeline w/ write abort server res after headers', (t) => { .resume() .write('asd') }) + + await t.completed }) -test('destroy in push', (t) => { - t.plan(3) +test('destroy in push', async (t) => { + t = tspl(t, { plan: 3 }) let _res const server = createServer((req, res) => { res.write('asd') _res = res }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.pipeline({ path: '/', method: 'GET' }, ({ body }) => { body.once('data', () => { @@ -698,15 +737,17 @@ test('destroy in push', (t) => { buf = chunk.toString() _res.end() }).on('end', () => { - t.equal('asd', buf) + t.strictEqual('asd', buf) }) return body }).resume().end() }) + + await t.completed }) -test('pipeline args validation', (t) => { - t.plan(2) +test('pipeline args validation', async (t) => { + t = tspl(t, { plan: 2 }) const client = new Client('http://localhost:5000') @@ -715,19 +756,21 @@ test('pipeline args validation', (t) => { t.ok(/opts/.test(err.message)) t.ok(err instanceof errors.InvalidArgumentError) }) + + await t.completed }) -test('pipeline factory throw not unhandled', (t) => { - t.plan(1) +test('pipeline factory throw not unhandled', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.write('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -740,19 +783,21 @@ test('pipeline factory throw not unhandled', (t) => { }) .end() }) + + await t.completed }) -test('pipeline destroy before dispatch', (t) => { - t.plan(1) +test('pipeline destroy before dispatch', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client .pipeline({ path: '/', method: 'GET' }, ({ body }) => { @@ -764,10 +809,12 @@ test('pipeline destroy before dispatch', (t) => { .end() .destroy() }) + + await t.completed }) -test('pipeline legacy stream', (t) => { - t.plan(1) +test('pipeline legacy stream', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.write(Buffer.alloc(16e3)) @@ -775,11 +822,11 @@ test('pipeline legacy stream', (t) => { res.end(Buffer.alloc(16e3)) }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client .pipeline({ path: '/', method: 'GET' }, ({ body }) => { @@ -793,19 +840,21 @@ test('pipeline legacy stream', (t) => { }) .end() }) + + await t.completed }) -test('pipeline objectMode', (t) => { - t.plan(1) +test('pipeline objectMode', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end(JSON.stringify({ asd: 1 })) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client .pipeline({ path: '/', method: 'GET', objectMode: true }, ({ body }) => { @@ -817,26 +866,28 @@ test('pipeline objectMode', (t) => { }), () => {}) }) .on('data', data => { - t.strictSame(data, { asd: 1 }) + t.deepStrictEqual(data, { asd: 1 }) }) .end() }) + + await t.completed }) -test('pipeline invalid opts', (t) => { - t.plan(2) +test('pipeline invalid opts', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.end(JSON.stringify({ asd: 1 })) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.close((err) => { - t.error(err) + t.ifError(err) }) client .pipeline({ path: '/', method: 'GET', objectMode: true }, ({ body }) => { @@ -846,19 +897,21 @@ test('pipeline invalid opts', (t) => { t.ok(err) }) }) + + await t.completed }) -test('pipeline CONNECT throw', (t) => { - t.plan(1) +test('pipeline CONNECT throw', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -872,19 +925,21 @@ test('pipeline CONNECT throw', (t) => { t.fail() }) }) + + await t.completed }) -test('pipeline body without destroy', (t) => { - t.plan(1) +test('pipeline body without destroy', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.pipeline({ path: '/', @@ -900,20 +955,22 @@ test('pipeline body without destroy', (t) => { }) .resume() }) + + await t.completed }) -test('pipeline ignore 1xx', (t) => { - t.plan(1) +test('pipeline ignore 1xx', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.writeProcessing() res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) let buf = '' client.pipeline({ @@ -924,24 +981,27 @@ test('pipeline ignore 1xx', (t) => { buf += chunk }) .on('end', () => { - t.equal(buf, 'hello') + t.strictEqual(buf, 'hello') }) .end() }) + + await t.completed }) -test('pipeline ignore 1xx and use onInfo', (t) => { - t.plan(3) + +test('pipeline ignore 1xx and use onInfo', async (t) => { + t = tspl(t, { plan: 3 }) const infos = [] const server = createServer((req, res) => { res.writeProcessing() res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) let buf = '' client.pipeline({ @@ -955,16 +1015,18 @@ test('pipeline ignore 1xx and use onInfo', (t) => { buf += chunk }) .on('end', () => { - t.equal(buf, 'hello') - t.equal(infos.length, 1) - t.equal(infos[0].statusCode, 102) + t.strictEqual(buf, 'hello') + t.strictEqual(infos.length, 1) + t.strictEqual(infos[0].statusCode, 102) }) .end() }) + + await t.completed }) -test('pipeline backpressure', (t) => { - t.plan(1) +test('pipeline backpressure', async (t) => { + t = tspl(t, { plan: 1 }) const expected = Buffer.alloc(1e6).toString() @@ -972,11 +1034,11 @@ test('pipeline backpressure', (t) => { res.writeProcessing() res.end(expected) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) let buf = '' client.pipeline({ @@ -996,13 +1058,15 @@ test('pipeline backpressure', (t) => { buf += chunk }) .on('end', () => { - t.equal(buf, expected) + t.strictEqual(buf, expected) }) }) + + await t.completed }) -test('pipeline abort after headers', (t) => { - t.plan(1) +test('pipeline abort after headers', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.writeProcessing() @@ -1011,11 +1075,11 @@ test('pipeline abort after headers', (t) => { res.write('asd') }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const signal = new EE() client.pipeline({ @@ -1033,4 +1097,6 @@ test('pipeline abort after headers', (t) => { t.ok(err instanceof errors.RequestAbortedError) }) }) + + await t.completed }) diff --git a/test/client-pipelining.js b/test/client-pipelining.js index 25441407f43..475b826c62d 100644 --- a/test/client-pipelining.js +++ b/test/client-pipelining.js @@ -1,6 +1,7 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const { createServer } = require('node:http') const { finished, Readable } = require('node:stream') @@ -9,9 +10,9 @@ const EE = require('node:events') const { kBusy, kRunning, kSize } = require('../lib/core/symbols') const { maybeWrapStream, consts } = require('./utils/async-iterators') -test('20 times GET with pipelining 10', (t) => { +test('20 times GET with pipelining 10', async (t) => { const num = 20 - t.plan(3 * num + 1) + t = tspl(t, { plan: 3 * num + 1 }) let count = 0 let countGreaterThanOne = false @@ -22,7 +23,7 @@ test('20 times GET with pipelining 10', (t) => { res.end(req.url) }, 10) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) // needed to check for a warning on the maxListeners on the socket function onWarning (warning) { @@ -31,7 +32,7 @@ test('20 times GET with pipelining 10', (t) => { } } process.on('warning', onWarning) - t.teardown(() => { + after(() => { process.removeListener('warning', onWarning) }) @@ -39,7 +40,7 @@ test('20 times GET with pipelining 10', (t) => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 10 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) for (let i = 0; i < num; i++) { makeRequest(i) @@ -55,28 +56,30 @@ test('20 times GET with pipelining 10', (t) => { }) } }) + + await t.completed }) function makeRequestAndExpectUrl (client, i, t, cb) { return client.request({ path: '/' + i, method: 'GET' }, (err, { statusCode, headers, body }) => { cb() - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('/' + i, Buffer.concat(bufs).toString('utf8')) + t.strictEqual('/' + i, Buffer.concat(bufs).toString('utf8')) }) }) } -test('A client should enqueue as much as twice its pipelining factor', (t) => { +test('A client should enqueue as much as twice its pipelining factor', async (t) => { const num = 10 let sent = 0 // x * 6 + 1 t.ok + 5 drain - t.plan(num * 6 + 1 + 5 + 2) + t = tspl(t, { plan: num * 6 + 1 + 5 + 2 }) let count = 0 let countGreaterThanOne = false @@ -88,22 +91,22 @@ test('A client should enqueue as much as twice its pipelining factor', (t) => { res.end(req.url) }, 10) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) for (; sent < 2;) { - t.notOk(client[kSize] > client.pipelining, 'client is not full') + t.ok(client[kSize] <= client.pipelining, 'client is not full') makeRequest() t.ok(client[kSize] <= client.pipelining, 'we can send more requests') } t.ok(client[kBusy], 'client is busy') - t.notOk(client[kSize] > client.pipelining, 'client is full') + t.ok(client[kSize] <= client.pipelining, 'client is full') makeRequest() t.ok(client[kBusy], 'we must stop now') t.ok(client[kBusy], 'client is busy') @@ -117,7 +120,7 @@ test('A client should enqueue as much as twice its pipelining factor', (t) => { t.ok(countGreaterThanOne, 'seen more than one parallel request') const start = sent for (; sent < start + 2 && sent < num;) { - t.notOk(client[kSize] > client.pipelining, 'client is not full') + t.ok(client[kSize] <= client.pipelining, 'client is not full') t.ok(makeRequest()) } } @@ -126,54 +129,58 @@ test('A client should enqueue as much as twice its pipelining factor', (t) => { return client[kSize] <= client.pipelining } }) + + await t.completed }) -test('pipeline 1 is 1 active request', (t) => { - t.plan(9) +test('pipeline 1 is 1 active request', async (t) => { + t = tspl(t, { plan: 9 }) let res2 const server = createServer((req, res) => { res.write('asd') res2 = res }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 1 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.equal(client[kSize], 1) - t.error(err) - t.notOk(client.request({ + t.strictEqual(client[kSize], 1) + t.ifError(err) + t.strictEqual(client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) finished(data.body, (err) => { t.ok(err) client.close((err) => { - t.error(err) + t.ifError(err) }) }) data.body.destroy() res2.end() - })) + }), undefined) data.body.resume() res2.end() }) t.ok(client[kSize] <= client.pipelining) t.ok(client[kBusy]) - t.equal(client[kSize], 1) + t.strictEqual(client[kSize], 1) }) + + await t.completed }) -test('pipelined chunked POST stream', (t) => { - t.plan(4 + 8 + 8) +test('pipelined chunked POST stream', async (t) => { + t = tspl(t, { plan: 4 + 8 + 8 }) let a = 0 let b = 0 @@ -187,20 +194,20 @@ test('pipelined chunked POST stream', (t) => { res.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, { body }) => { body.resume() - t.error(err) + t.ifError(err) }) client.request({ @@ -213,7 +220,7 @@ test('pipelined chunked POST stream', (t) => { }) }, (err, { body }) => { body.resume() - t.error(err) + t.ifError(err) }) client.request({ @@ -221,7 +228,7 @@ test('pipelined chunked POST stream', (t) => { method: 'GET' }, (err, { body }) => { body.resume() - t.error(err) + t.ifError(err) }) client.request({ @@ -234,13 +241,15 @@ test('pipelined chunked POST stream', (t) => { }) }, (err, { body }) => { body.resume() - t.error(err) + t.ifError(err) }) }) + + await t.completed }) -test('pipelined chunked POST iterator', (t) => { - t.plan(4 + 8 + 8) +test('pipelined chunked POST iterator', async (t) => { + t = tspl(t, { plan: 4 + 8 + 8 }) let a = 0 let b = 0 @@ -254,20 +263,20 @@ test('pipelined chunked POST iterator', (t) => { res.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, { body }) => { body.resume() - t.error(err) + t.ifError(err) }) client.request({ @@ -280,7 +289,7 @@ test('pipelined chunked POST iterator', (t) => { })() }, (err, { body }) => { body.resume() - t.error(err) + t.ifError(err) }) client.request({ @@ -288,7 +297,7 @@ test('pipelined chunked POST iterator', (t) => { method: 'GET' }, (err, { body }) => { body.resume() - t.error(err) + t.ifError(err) }) client.request({ @@ -301,14 +310,16 @@ test('pipelined chunked POST iterator', (t) => { })() }, (err, { body }) => { body.resume() - t.error(err) + t.ifError(err) }) }) + + await t.completed }) function errordInflightPost (bodyType) { - test(`errored POST body lets inflight complete ${bodyType}`, (t) => { - t.plan(6) + test(`errored POST body lets inflight complete ${bodyType}`, async (t) => { + t = tspl(t, { plan: 6 }) let serverRes const server = createServer() @@ -316,19 +327,19 @@ function errordInflightPost (bodyType) { serverRes = res res.write('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .once('data', () => { @@ -347,10 +358,10 @@ function errordInflightPost (bodyType) { }), bodyType) }, (err, data) => { t.ok(err) - t.equal(data.opaque, 'asd') + t.strictEqual(data.opaque, 'asd') }) client.close((err) => { - t.error(err) + t.ifError(err) }) serverRes.end() }) @@ -359,14 +370,15 @@ function errordInflightPost (bodyType) { }) }) }) + await t.completed }) } errordInflightPost(consts.STREAM) errordInflightPost(consts.ASYNC_ITERATOR) -test('pipelining non-idempotent', (t) => { - t.plan(4) +test('pipelining non-idempotent', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer() server.on('request', (req, res) => { @@ -374,20 +386,20 @@ test('pipelining non-idempotent', (t) => { res.end('asd') }, 10) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) let ended = false client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { @@ -401,16 +413,18 @@ test('pipelining non-idempotent', (t) => { method: 'GET', idempotent: false }, (err, data) => { - t.error(err) - t.equal(ended, true) + t.ifError(err) + t.strictEqual(ended, true) data.body.resume() }) }) + + await t.completed }) function pipeliningNonIdempotentWithBody (bodyType) { - test(`pipelining non-idempotent w body ${bodyType}`, (t) => { - t.plan(4) + test(`pipelining non-idempotent w body ${bodyType}`, async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer() server.on('request', (req, res) => { @@ -418,13 +432,13 @@ function pipeliningNonIdempotentWithBody (bodyType) { res.end('asd') }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) let ended = false let reading = false @@ -445,7 +459,7 @@ function pipeliningNonIdempotentWithBody (bodyType) { } }), bodyType) }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { @@ -458,11 +472,13 @@ function pipeliningNonIdempotentWithBody (bodyType) { method: 'GET', idempotent: false }, (err, data) => { - t.error(err) - t.equal(ended, true) + t.ifError(err) + t.strictEqual(ended, true) data.body.resume() }) }) + + await t.completed }) } @@ -470,25 +486,25 @@ pipeliningNonIdempotentWithBody(consts.STREAM) pipeliningNonIdempotentWithBody(consts.ASYNC_ITERATOR) function pipeliningHeadBusy (bodyType) { - test(`pipelining HEAD busy ${bodyType}`, (t) => { - t.plan(7) + test(`pipelining HEAD busy ${bodyType}`, async (t) => { + t = tspl(t, { plan: 7 }) const server = createServer() server.on('request', (req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 10 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client[kConnect](() => { let ended = false client.once('disconnect', () => { - t.equal(ended, true) + t.strictEqual(ended, true) }) { @@ -500,7 +516,7 @@ function pipeliningHeadBusy (bodyType) { method: 'GET', body: maybeWrapStream(body, bodyType) }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { @@ -508,7 +524,7 @@ function pipeliningHeadBusy (bodyType) { }) }) body.push(null) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) } { @@ -520,7 +536,7 @@ function pipeliningHeadBusy (bodyType) { method: 'HEAD', body: maybeWrapStream(body, bodyType) }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { @@ -529,18 +545,20 @@ function pipeliningHeadBusy (bodyType) { }) }) body.push(null) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) } }) }) + + await t.completed }) } pipeliningHeadBusy(consts.STREAM) pipeliningHeadBusy(consts.ASYNC_ITERATOR) -test('pipelining empty pipeline before reset', (t) => { - t.plan(8) +test('pipelining empty pipeline before reset', async (t) => { + t = tspl(t, { plan: 8 }) let c = 0 const server = createServer() @@ -553,39 +571,39 @@ test('pipelining empty pipeline before reset', (t) => { }, 100) } }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 10 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client[kConnect](() => { let ended = false client.once('disconnect', () => { - t.equal(ended, true) + t.strictEqual(ended, true) }) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { t.ok(true, 'pass') }) }) - t.equal(client[kBusy], false) + t.strictEqual(client[kBusy], false) client.request({ path: '/', method: 'HEAD', body: 'asd' }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { @@ -593,27 +611,29 @@ test('pipelining empty pipeline before reset', (t) => { t.ok(true, 'pass') }) }) - t.equal(client[kBusy], true) - t.equal(client[kRunning], 2) + t.strictEqual(client[kBusy], true) + t.strictEqual(client[kRunning], 2) }) }) + + await t.completed }) function pipeliningIdempotentBusy (bodyType) { - test(`pipelining idempotent busy ${bodyType}`, (t) => { - t.plan(12) + test(`pipelining idempotent busy ${bodyType}`, async (t) => { + t = tspl(t, { plan: 12 }) const server = createServer() server.on('request', (req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 10 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) { const body = new Readable({ @@ -624,7 +644,7 @@ function pipeliningIdempotentBusy (bodyType) { method: 'GET', body: maybeWrapStream(body, bodyType) }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { @@ -632,7 +652,7 @@ function pipeliningIdempotentBusy (bodyType) { }) }) body.push(null) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) } client[kConnect](() => { @@ -645,7 +665,7 @@ function pipeliningIdempotentBusy (bodyType) { method: 'GET', body: maybeWrapStream(body, bodyType) }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { @@ -653,7 +673,7 @@ function pipeliningIdempotentBusy (bodyType) { }) }) body.push(null) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) } { @@ -669,9 +689,9 @@ function pipeliningIdempotentBusy (bodyType) { }, (err, data) => { t.ok(err) }) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) signal.emit('abort') - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) } { @@ -684,7 +704,7 @@ function pipeliningIdempotentBusy (bodyType) { idempotent: false, body: maybeWrapStream(body, bodyType) }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { @@ -692,18 +712,20 @@ function pipeliningIdempotentBusy (bodyType) { }) }) body.push(null) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) } }) }) + + await t.completed }) } pipeliningIdempotentBusy(consts.STREAM) pipeliningIdempotentBusy(consts.ASYNC_ITERATOR) -test('pipelining blocked', (t) => { - t.plan(6) +test('pipelining blocked', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer() @@ -717,19 +739,19 @@ test('pipelining blocked', (t) => { res.end('asd') }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 10 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', blocking: true }, (err, data) => { - t.error(err) + t.ifError(err) blocking = false data.body .resume() @@ -741,7 +763,7 @@ test('pipelining blocked', (t) => { path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { @@ -749,4 +771,6 @@ test('pipelining blocked', (t) => { }) }) }) + + await t.completed }) diff --git a/test/client-timeout.js b/test/client-timeout.js index dd5b1da6505..4964774d0bc 100644 --- a/test/client-timeout.js +++ b/test/client-timeout.js @@ -1,25 +1,26 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, errors } = require('..') const { createServer } = require('node:http') const { Readable } = require('node:stream') const FakeTimers = require('@sinonjs/fake-timers') const timers = require('../lib/timers') -test('refresh timeout on pause', (t) => { - t.plan(1) +test('refresh timeout on pause', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.flushHeaders() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 500 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.dispatch({ path: '/', @@ -44,30 +45,32 @@ test('refresh timeout on pause', (t) => { } }) }) + + await t.completed }) -test('start headers timeout after request body', (t) => { - t.plan(2) +test('start headers timeout after request body', async (t) => { + t = tspl(t, { plan: 2 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) const server = createServer((req, res) => { }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0, headersTimeout: 100 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const body = new Readable({ read () {} }) client.dispatch({ @@ -100,30 +103,32 @@ test('start headers timeout after request body', (t) => { } }) }) + + await t.completed }) -test('start headers timeout after async iterator request body', (t) => { - t.plan(1) +test('start headers timeout after async iterator request body', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) const server = createServer((req, res) => { }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0, headersTimeout: 100 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) let res const body = (async function * () { await new Promise((resolve) => { res = resolve }) @@ -157,21 +162,23 @@ test('start headers timeout after async iterator request body', (t) => { } }) }) + + await t.completed }) -test('parser resume with no body timeout', (t) => { - t.plan(1) +test('parser resume with no body timeout', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.dispatch({ path: '/', @@ -190,8 +197,10 @@ test('parser resume with no body timeout', (t) => { t.ok(true, 'pass') }, onError (err) { - t.error(err) + t.ifError(err) } }) }) + + await t.completed }) diff --git a/test/client-upgrade.js b/test/client-upgrade.js index c33ab183363..5cf5e553ba7 100644 --- a/test/client-upgrade.js +++ b/test/client-upgrade.js @@ -1,14 +1,15 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, errors } = require('..') const net = require('node:net') const http = require('node:http') const EE = require('node:events') const { kBusy } = require('../lib/core/symbols') -test('basic upgrade', (t) => { - t.plan(6) +test('basic upgrade', async (t) => { + t = tspl(t, { plan: 6 }) const server = net.createServer((c) => { c.on('data', (d) => { @@ -25,11 +26,11 @@ test('basic upgrade', (t) => { c.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const signal = new EE() client.upgrade({ @@ -38,9 +39,9 @@ test('basic upgrade', (t) => { method: 'GET', protocol: 'Websocket' }, (err, data) => { - t.error(err) + t.ifError(err) - t.equal(signal.listenerCount('abort'), 0) + t.strictEqual(signal.listenerCount('abort'), 0) const { headers, socket } = data @@ -50,22 +51,24 @@ test('basic upgrade', (t) => { }) socket.on('close', () => { - t.equal(recvData.toString(), 'Body') + t.strictEqual(recvData.toString(), 'Body') }) - t.same(headers, { + t.deepStrictEqual(headers, { hello: 'world', connection: 'upgrade', upgrade: 'websocket' }) socket.end() }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) }) + + await t.completed }) -test('basic upgrade promise', (t) => { - t.plan(2) +test('basic upgrade promise', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer((c) => { c.on('data', (d) => { @@ -81,11 +84,11 @@ test('basic upgrade promise', (t) => { c.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const { headers, socket } = await client.upgrade({ path: '/', @@ -99,20 +102,22 @@ test('basic upgrade promise', (t) => { }) socket.on('close', () => { - t.equal(recvData.toString(), 'Body') + t.strictEqual(recvData.toString(), 'Body') }) - t.same(headers, { + t.deepStrictEqual(headers, { hello: 'world', connection: 'upgrade', upgrade: 'websocket' }) socket.end() }) + + await t.completed }) -test('upgrade error', (t) => { - t.plan(1) +test('upgrade error', async (t) => { + t = tspl(t, { plan: 1 }) const server = net.createServer((c) => { c.on('data', (d) => { @@ -127,11 +132,11 @@ test('upgrade error', (t) => { // Ignore error. }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) try { await client.upgrade({ @@ -143,16 +148,18 @@ test('upgrade error', (t) => { t.ok(err) } }) + + await t.completed }) -test('upgrade invalid opts', (t) => { - t.plan(6) +test('upgrade invalid opts', async (t) => { + t = tspl(t, { plan: 6 }) const client = new Client('http://localhost:5432') client.upgrade(null, err => { t.ok(err instanceof errors.InvalidArgumentError) - t.equal(err.message, 'invalid opts') + t.strictEqual(err.message, 'invalid opts') }) try { @@ -160,7 +167,7 @@ test('upgrade invalid opts', (t) => { t.fail() } catch (err) { t.ok(err instanceof errors.InvalidArgumentError) - t.equal(err.message, 'invalid opts') + t.strictEqual(err.message, 'invalid opts') } try { @@ -168,12 +175,12 @@ test('upgrade invalid opts', (t) => { t.fail() } catch (err) { t.ok(err instanceof errors.InvalidArgumentError) - t.equal(err.message, 'invalid callback') + t.strictEqual(err.message, 'invalid callback') } }) -test('basic upgrade2', (t) => { - t.plan(3) +test('basic upgrade2', async (t) => { + t = tspl(t, { plan: 3 }) const server = http.createServer() server.on('upgrade', (req, c, head) => { @@ -185,18 +192,18 @@ test('basic upgrade2', (t) => { c.write('Body') c.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.upgrade({ path: '/', method: 'GET', protocol: 'Websocket' }, (err, data) => { - t.error(err) + t.ifError(err) const { headers, socket } = data @@ -206,10 +213,10 @@ test('basic upgrade2', (t) => { }) socket.on('close', () => { - t.equal(recvData.toString(), 'Body') + t.strictEqual(recvData.toString(), 'Body') }) - t.same(headers, { + t.deepStrictEqual(headers, { hello: 'world', connection: 'upgrade', upgrade: 'websocket' @@ -217,10 +224,12 @@ test('basic upgrade2', (t) => { socket.end() }) }) + + await t.completed }) -test('upgrade wait for empty pipeline', (t) => { - t.plan(7) +test('upgrade wait for empty pipeline', async (t) => { + t = tspl(t, { plan: 7 }) let canConnect = false const server = http.createServer((req, res) => { @@ -228,7 +237,7 @@ test('upgrade wait for empty pipeline', (t) => { canConnect = true }) server.on('upgrade', (req, c, firstBodyChunk) => { - t.equal(canConnect, true) + t.strictEqual(canConnect, true) c.write('HTTP/1.1 101\r\n') c.write('hello: world\r\n') c.write('connection: upgrade\r\n') @@ -237,55 +246,57 @@ test('upgrade wait for empty pipeline', (t) => { c.write('Body') c.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err) => { - t.error(err) + t.ifError(err) }) client.once('connect', () => { process.nextTick(() => { - t.equal(client[kBusy], false) + t.strictEqual(client[kBusy], false) client.upgrade({ path: '/' }, (err, { socket }) => { - t.error(err) + t.ifError(err) let recvData = '' socket.on('data', (d) => { recvData += d }) socket.on('end', () => { - t.equal(recvData.toString(), 'Body') + t.strictEqual(recvData.toString(), 'Body') }) socket.write('Body') socket.end() }) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) client.request({ path: '/', method: 'GET' }, (err) => { - t.error(err) + t.ifError(err) }) }) }) }) + + await t.completed }) -test('upgrade aborted', (t) => { - t.plan(6) +test('upgrade aborted', async (t) => { + t = tspl(t, { plan: 6 }) const server = http.createServer((req, res) => { t.fail() @@ -293,13 +304,13 @@ test('upgrade aborted', (t) => { server.on('upgrade', (req, c, firstBodyChunk) => { t.fail() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 3 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const signal = new EE() client.upgrade({ @@ -307,22 +318,24 @@ test('upgrade aborted', (t) => { signal, opaque: 'asd' }, (err, { opaque }) => { - t.equal(opaque, 'asd') + t.strictEqual(opaque, 'asd') t.ok(err instanceof errors.RequestAbortedError) - t.equal(signal.listenerCount('abort'), 0) + t.strictEqual(signal.listenerCount('abort'), 0) }) - t.equal(client[kBusy], true) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(client[kBusy], true) + t.strictEqual(signal.listenerCount('abort'), 1) signal.emit('abort') client.close(() => { t.ok(true, 'pass') }) }) + + await t.completed }) -test('basic aborted after res', (t) => { - t.plan(1) +test('basic aborted after res', async (t) => { + t = tspl(t, { plan: 1 }) const signal = new EE() const server = http.createServer() @@ -339,11 +352,11 @@ test('basic aborted after res', (t) => { }) signal.emit('abort') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.upgrade({ path: '/', @@ -354,10 +367,12 @@ test('basic aborted after res', (t) => { t.ok(err instanceof errors.RequestAbortedError) }) }) + + await t.completed }) -test('basic upgrade error', (t) => { - t.plan(2) +test('basic upgrade error', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer((c) => { c.on('data', (d) => { @@ -372,11 +387,11 @@ test('basic upgrade error', (t) => { }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const _err = new Error() client.upgrade({ @@ -384,30 +399,32 @@ test('basic upgrade error', (t) => { method: 'GET', protocol: 'Websocket' }, (err, data) => { - t.error(err) + t.ifError(err) data.socket.on('error', (err) => { - t.equal(err, _err) + t.strictEqual(err, _err) }) throw _err }) }) + + await t.completed }) -test('upgrade disconnect', (t) => { - t.plan(3) +test('upgrade disconnect', async (t) => { + t = tspl(t, { plan: 3 }) const server = net.createServer(connection => { connection.destroy() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.on('disconnect', (origin, [self], error) => { - t.equal(client, self) + t.strictEqual(client, self) t.ok(error instanceof Error) }) @@ -420,19 +437,21 @@ test('upgrade disconnect', (t) => { t.ok(error instanceof Error) }) }) + + await t.completed }) -test('upgrade invalid signal', (t) => { - t.plan(2) +test('upgrade invalid signal', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer(() => { t.fail() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.on('disconnect', () => { t.fail() @@ -445,8 +464,10 @@ test('upgrade invalid signal', (t) => { signal: 'error', opaque: 'asd' }, (err, { opaque }) => { - t.equal(opaque, 'asd') + t.strictEqual(opaque, 'asd') t.ok(err instanceof errors.InvalidArgumentError) }) }) + + await t.completed }) diff --git a/test/get-head-body.js b/test/get-head-body.js index 74420a174cd..4e58bc0f5a5 100644 --- a/test/get-head-body.js +++ b/test/get-head-body.js @@ -1,6 +1,7 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const { createServer } = require('node:http') const { Readable } = require('node:stream') @@ -8,17 +9,17 @@ const { kConnect } = require('../lib/core/symbols') const { kBusy } = require('../lib/core/symbols') const { wrapWithAsyncIterable } = require('./utils/async-iterators') -test('GET and HEAD with body should reset connection', (t) => { - t.plan(8 + 2) +test('GET and HEAD with body should reset connection', async (t) => { + t = tspl(t, { plan: 8 + 2 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.on('disconnect', () => { t.ok(true, 'pass') @@ -29,7 +30,7 @@ test('GET and HEAD with body should reset connection', (t) => { body: 'asd', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) @@ -42,7 +43,7 @@ test('GET and HEAD with body should reset connection', (t) => { body: emptyBody, method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) @@ -55,7 +56,7 @@ test('GET and HEAD with body should reset connection', (t) => { }), method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) @@ -69,7 +70,7 @@ test('GET and HEAD with body should reset connection', (t) => { }), method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) @@ -78,7 +79,7 @@ test('GET and HEAD with body should reset connection', (t) => { body: [], method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) @@ -91,7 +92,7 @@ test('GET and HEAD with body should reset connection', (t) => { })), method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) @@ -105,44 +106,48 @@ test('GET and HEAD with body should reset connection', (t) => { })), method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) }) + + await t.completed }) // TODO: Avoid external dependency. -// test('GET with body should work when target parses body as request', (t) => { -// t.plan(4) +// test('GET with body should work when target parses body as request', async (t) => { +// t = tspl(t, { plan: 4 }) // // This URL will send double responses when receiving a // // GET request with body. // const client = new Client('http://feeds.bbci.co.uk') -// t.teardown(client.close.bind(client)) +// after(() => client.close()) // client.request({ method: 'GET', path: '/news/rss.xml', body: 'asd' }, (err, data) => { -// t.error(err) -// t.equal(data.statusCode, 200) +// t.ifError(err) +// t.strictEqual(data.statusCode, 200) // data.body.resume() // }) // client.request({ method: 'GET', path: '/news/rss.xml', body: 'asd' }, (err, data) => { -// t.error(err) -// t.equal(data.statusCode, 200) +// t.ifError(err) +// t.strictEqual(data.statusCode, 200) // data.body.resume() // }) + +// await t.completed // }) -test('HEAD should reset connection', (t) => { - t.plan(8) +test('HEAD should reset connection', async (t) => { + t = tspl(t, { plan: 8 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.once('disconnect', () => { t.ok(true, 'pass') @@ -152,16 +157,16 @@ test('HEAD should reset connection', (t) => { path: '/', method: 'HEAD' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) client.request({ path: '/', method: 'HEAD' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() client.once('disconnect', () => { client[kConnect](() => { @@ -169,16 +174,18 @@ test('HEAD should reset connection', (t) => { path: '/', method: 'HEAD' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() data.body.on('end', () => { t.ok(true, 'pass') }) }) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) }) }) }) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) }) + + await t.completed }) diff --git a/test/http2-alpn.js b/test/http2-alpn.js index 04b8cb6abd8..590f65e128e 100644 --- a/test/http2-alpn.js +++ b/test/http2-alpn.js @@ -1,11 +1,12 @@ 'use strict' +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const https = require('node:https') const { once } = require('node:events') const { createSecureServer } = require('node:http2') const { readFileSync } = require('node:fs') const { join } = require('node:path') -const { test } = require('tap') const { Client } = require('..') @@ -15,7 +16,7 @@ const cert = readFileSync(join(__dirname, 'fixtures', 'cert.pem'), 'utf8') const ca = readFileSync(join(__dirname, 'fixtures', 'ca.pem'), 'utf8') test('Should upgrade to HTTP/2 when HTTPS/1 is available for GET', async (t) => { - t.plan(10) + t = tspl(t, { plan: 10 }) const body = [] const httpsBody = [] @@ -47,7 +48,7 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for GET', async (t) => await once(server, 'listening') // close the server on teardown - t.teardown(server.close.bind(server)) + after(() => server.close()) // set the port const port = server.address().port @@ -62,7 +63,7 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for GET', async (t) => }) // close the client on teardown - t.teardown(client.close.bind(client)) + after(() => client.close()) // make an undici request using where it wants http/2 const response = await client.request({ @@ -110,7 +111,7 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for GET', async (t) => reject(err) }) - t.teardown(httpsRequest.destroy.bind(httpsRequest)) + after(() => httpsRequest.destroy()) }) t.equal(httpsResponse.statusCode, 200) @@ -124,7 +125,7 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for GET', async (t) => }) test('Should upgrade to HTTP/2 when HTTPS/1 is available for POST', async (t) => { - t.plan(15) + t = tspl(t, { plan: 15 }) const requestChunks = [] const responseBody = [] @@ -194,7 +195,7 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for POST', async (t) => await once(server, 'listening') // close the server on teardown - t.teardown(server.close.bind(server)) + after(() => server.close()) // set the port const port = server.address().port @@ -209,7 +210,7 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for POST', async (t) => }) // close the client on teardown - t.teardown(client.close.bind(client)) + after(() => client.close()) // make an undici request using where it wants http/2 const response = await client.request({ @@ -265,7 +266,7 @@ test('Should upgrade to HTTP/2 when HTTPS/1 is available for POST', async (t) => httpsRequest.write(Buffer.from(body)) - t.teardown(httpsRequest.destroy.bind(httpsRequest)) + after(() => httpsRequest.destroy()) }) t.equal(httpsResponse.statusCode, 201) diff --git a/test/http2.js b/test/http2.js index 538c6677788..3319ffddb1e 100644 --- a/test/http2.js +++ b/test/http2.js @@ -1,27 +1,26 @@ 'use strict' +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { createSecureServer } = require('node:http2') const { createReadStream, readFileSync } = require('node:fs') const { once } = require('node:events') const { Blob } = require('node:buffer') const { Writable, pipeline, PassThrough, Readable } = require('node:stream') -const { test, plan } = require('tap') const pem = require('https-pem') const { Client, Agent } = require('..') const isGreaterThanv20 = process.versions.node.split('.').map(Number)[0] >= 20 -plan(25) - test('Should support H2 connection', async t => { const body = [] const server = createSecureServer(pem) server.on('stream', (stream, headers, _flags, rawHeaders) => { - t.equal(headers['x-my-header'], 'foo') - t.equal(headers[':method'], 'GET') + t.strictEqual(headers['x-my-header'], 'foo') + t.strictEqual(headers[':method'], 'GET') stream.respond({ 'content-type': 'text/plain; charset=utf-8', 'x-custom-h2': 'hello', @@ -40,9 +39,9 @@ test('Should support H2 connection', async t => { allowH2: true }) - t.plan(6) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + t = tspl(t, { plan: 6 }) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -57,23 +56,23 @@ test('Should support H2 connection', async t => { }) await once(response.body, 'end') - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'hello') - t.equal(Buffer.concat(body).toString('utf8'), 'hello h2!') + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'hello') + t.strictEqual(Buffer.concat(body).toString('utf8'), 'hello h2!') }) test('Should support H2 connection(multiple requests)', async t => { const server = createSecureServer(pem) server.on('stream', async (stream, headers, _flags, rawHeaders) => { - t.equal(headers['x-my-header'], 'foo') - t.equal(headers[':method'], 'POST') + t.strictEqual(headers['x-my-header'], 'foo') + t.strictEqual(headers[':method'], 'POST') const reqData = [] stream.on('data', chunk => reqData.push(chunk.toString())) await once(stream, 'end') const reqBody = reqData.join('') - t.equal(reqBody.length > 0, true) + t.strictEqual(reqBody.length > 0, true) stream.respond({ 'content-type': 'text/plain; charset=utf-8', 'x-custom-h2': 'hello', @@ -92,9 +91,9 @@ test('Should support H2 connection(multiple requests)', async t => { allowH2: true }) - t.plan(21) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + t = tspl(t, { plan: 21 }) + after(() => server.close()) + after(() => client.close()) for (let i = 0; i < 3; i++) { const sendBody = `seq ${i}` @@ -114,10 +113,10 @@ test('Should support H2 connection(multiple requests)', async t => { }) await once(response.body, 'end') - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'hello') - t.equal(Buffer.concat(body).toString('utf8'), `hello h2! ${sendBody}`) + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'hello') + t.strictEqual(Buffer.concat(body).toString('utf8'), `hello h2! ${sendBody}`) } }) @@ -126,9 +125,9 @@ test('Should support H2 connection (headers as array)', async t => { const server = createSecureServer(pem) server.on('stream', (stream, headers) => { - t.equal(headers['x-my-header'], 'foo') - t.equal(headers['x-my-drink'], 'coffee,tea') - t.equal(headers[':method'], 'GET') + t.strictEqual(headers['x-my-header'], 'foo') + t.strictEqual(headers['x-my-drink'], 'coffee,tea') + t.strictEqual(headers[':method'], 'GET') stream.respond({ 'content-type': 'text/plain; charset=utf-8', 'x-custom-h2': 'hello', @@ -147,9 +146,9 @@ test('Should support H2 connection (headers as array)', async t => { allowH2: true }) - t.plan(7) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + t = tspl(t, { plan: 7 }) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -162,21 +161,21 @@ test('Should support H2 connection (headers as array)', async t => { }) await once(response.body, 'end') - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'hello') - t.equal(Buffer.concat(body).toString('utf8'), 'hello h2!') + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'hello') + t.strictEqual(Buffer.concat(body).toString('utf8'), 'hello h2!') }) test('Should support H2 connection(POST Buffer)', async t => { const server = createSecureServer({ ...pem, allowHTTP1: false }) server.on('stream', async (stream, headers, _flags, rawHeaders) => { - t.equal(headers[':method'], 'POST') + t.strictEqual(headers[':method'], 'POST') const reqData = [] stream.on('data', chunk => reqData.push(chunk.toString())) await once(stream, 'end') - t.equal(reqData.join(''), 'hello!') + t.strictEqual(reqData.join(''), 'hello!') stream.respond({ 'content-type': 'text/plain; charset=utf-8', 'x-custom-h2': 'hello', @@ -195,9 +194,9 @@ test('Should support H2 connection(POST Buffer)', async t => { allowH2: true }) - t.plan(6) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + t = tspl(t, { plan: 6 }) + after(() => server.close()) + after(() => client.close()) const sendBody = 'hello!' const body = [] @@ -212,10 +211,10 @@ test('Should support H2 connection(POST Buffer)', async t => { }) await once(response.body, 'end') - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'hello') - t.equal(Buffer.concat(body).toString('utf8'), 'hello h2!') + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'hello') + t.strictEqual(Buffer.concat(body).toString('utf8'), 'hello h2!') }) test('Should support H2 GOAWAY (server-side)', async t => { @@ -223,8 +222,8 @@ test('Should support H2 GOAWAY (server-side)', async t => { const server = createSecureServer(pem) server.on('stream', (stream, headers) => { - t.equal(headers['x-my-header'], 'foo') - t.equal(headers[':method'], 'GET') + t.strictEqual(headers['x-my-header'], 'foo') + t.strictEqual(headers[':method'], 'GET') stream.respond({ 'content-type': 'text/plain; charset=utf-8', 'x-custom-h2': 'hello', @@ -249,9 +248,9 @@ test('Should support H2 GOAWAY (server-side)', async t => { allowH2: true }) - t.plan(9) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + t = tspl(t, { plan: 9 }) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -266,19 +265,21 @@ test('Should support H2 GOAWAY (server-side)', async t => { }) await once(response.body, 'end') - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'hello') - t.equal(Buffer.concat(body).toString('utf8'), 'hello h2!') + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'hello') + t.strictEqual(Buffer.concat(body).toString('utf8'), 'hello h2!') const [url, disconnectClient, err] = await once(client, 'disconnect') t.ok(url instanceof URL) - t.same(disconnectClient, [client]) - t.equal(err.message, 'HTTP/2: "GOAWAY" frame received with code 204') + t.deepStrictEqual(disconnectClient, [client]) + t.strictEqual(err.message, 'HTTP/2: "GOAWAY" frame received with code 204') }) test('Should throw if bad allowH2 has been passed', async t => { + t = tspl(t, { plan: 1 }) + try { // eslint-disable-next-line new Client('https://localhost:1000', { @@ -286,11 +287,13 @@ test('Should throw if bad allowH2 has been passed', async t => { }) t.fail() } catch (error) { - t.equal(error.message, 'allowH2 must be a valid boolean value') + t.strictEqual(error.message, 'allowH2 must be a valid boolean value') } }) test('Should throw if bad maxConcurrentStreams has been passed', async t => { + t = tspl(t, { plan: 2 }) + try { // eslint-disable-next-line new Client('https://localhost:1000', { @@ -299,7 +302,7 @@ test('Should throw if bad maxConcurrentStreams has been passed', async t => { }) t.fail() } catch (error) { - t.equal( + t.strictEqual( error.message, 'maxConcurrentStreams must be a positive integer, greater than 0' ) @@ -313,17 +316,21 @@ test('Should throw if bad maxConcurrentStreams has been passed', async t => { }) t.fail() } catch (error) { - t.equal( + t.strictEqual( error.message, 'maxConcurrentStreams must be a positive integer, greater than 0' ) } + + await t.completed }) test( 'Request should fail if allowH2 is false and server advertises h1 only', { skip: isGreaterThanv20 }, async t => { + t = tspl(t, { plan: 1 }) + const server = createSecureServer( { ...pem, @@ -345,8 +352,8 @@ test( } }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -356,7 +363,7 @@ test( } }) - t.equal(response.statusCode, 403) + t.strictEqual(response.statusCode, 403) } ) @@ -385,9 +392,9 @@ test( } }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) - t.plan(2) + after(() => server.close()) + after(() => client.close()) + t = tspl(t, { plan: 2 }) try { await client.request({ @@ -398,11 +405,11 @@ test( } }) } catch (error) { - t.equal( + t.strictEqual( error.message, 'Client network socket disconnected before secure TLS connection was established' ) - t.equal(error.code, 'ECONNRESET') + t.strictEqual(error.code, 'ECONNRESET') } } ) @@ -413,9 +420,9 @@ test('Should handle h2 continue', async t => { const responseBody = [] server.on('checkContinue', (request, response) => { - t.equal(request.headers.expect, '100-continue') - t.equal(request.headers['x-my-header'], 'foo') - t.equal(request.headers[':method'], 'POST') + t.strictEqual(request.headers.expect, '100-continue') + t.strictEqual(request.headers['x-my-header'], 'foo') + t.strictEqual(request.headers[':method'], 'POST') response.writeContinue() request.on('data', chunk => requestBody.push(chunk)) @@ -427,7 +434,7 @@ test('Should handle h2 continue', async t => { response.end('hello h2!') }) - t.plan(7) + t = tspl(t, { plan: 7 }) server.listen(0) await once(server, 'listening') @@ -440,8 +447,8 @@ test('Should handle h2 continue', async t => { allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -458,13 +465,13 @@ test('Should handle h2 continue', async t => { await once(response.body, 'end') - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'foo') - t.equal(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'foo') + t.strictEqual(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') }) -test('Dispatcher#Stream', t => { +test('Dispatcher#Stream', async t => { const server = createSecureServer(pem) const expectedBody = 'hello from client!' const bufs = [] @@ -480,7 +487,7 @@ test('Dispatcher#Stream', t => { stream.end('hello h2!') }) - t.plan(4) + t = tspl(t, { plan: 4 }) server.listen(0, async () => { const client = new Client(`https://localhost:${server.address().port}`, { @@ -490,14 +497,14 @@ test('Dispatcher#Stream', t => { allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) await client.stream( { path: '/', opaque: { bufs }, method: 'POST', body: expectedBody }, ({ statusCode, headers, opaque: { bufs } }) => { - t.equal(statusCode, 200) - t.equal(headers['x-custom'], 'custom-header') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['x-custom'], 'custom-header') return new Writable({ write (chunk, _encoding, cb) { @@ -508,12 +515,14 @@ test('Dispatcher#Stream', t => { } ) - t.equal(Buffer.concat(bufs).toString('utf-8'), 'hello h2!') - t.equal(requestBody, expectedBody) + t.strictEqual(Buffer.concat(bufs).toString('utf-8'), 'hello h2!') + t.strictEqual(requestBody, expectedBody) }) + + await t.completed }) -test('Dispatcher#Pipeline', t => { +test('Dispatcher#Pipeline', async t => { const server = createSecureServer(pem) const expectedBody = 'hello from client!' const bufs = [] @@ -529,7 +538,7 @@ test('Dispatcher#Pipeline', t => { stream.end('hello h2!') }) - t.plan(5) + t = tspl(t, { plan: 5 }) server.listen(0, () => { const client = new Client(`https://localhost:${server.address().port}`, { @@ -539,8 +548,8 @@ test('Dispatcher#Pipeline', t => { allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) pipeline( new Readable({ @@ -552,8 +561,8 @@ test('Dispatcher#Pipeline', t => { client.pipeline( { path: '/', method: 'POST', body: expectedBody }, ({ statusCode, headers, body }) => { - t.equal(statusCode, 200) - t.equal(headers['x-custom'], 'custom-header') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['x-custom'], 'custom-header') return pipeline(body, new PassThrough(), () => {}) } @@ -565,15 +574,17 @@ test('Dispatcher#Pipeline', t => { } }), err => { - t.error(err) - t.equal(Buffer.concat(bufs).toString('utf-8'), 'hello h2!') - t.equal(requestBody, expectedBody) + t.ifError(err) + t.strictEqual(Buffer.concat(bufs).toString('utf-8'), 'hello h2!') + t.strictEqual(requestBody, expectedBody) } ) }) + + await t.completed }) -test('Dispatcher#Connect', t => { +test('Dispatcher#Connect', async t => { const server = createSecureServer(pem) const expectedBody = 'hello from client!' let requestBody = '' @@ -588,7 +599,7 @@ test('Dispatcher#Connect', t => { stream.end('hello h2!') }) - t.plan(6) + t = tspl(t, { plan: 6 }) server.listen(0, () => { const client = new Client(`https://localhost:${server.address().port}`, { @@ -598,19 +609,19 @@ test('Dispatcher#Connect', t => { allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) let result = '' client.connect({ path: '/' }, (err, { socket }) => { - t.error(err) + t.ifError(err) socket.on('data', chunk => { result += chunk }) socket.on('response', headers => { - t.equal(headers[':status'], 200) - t.equal(headers['x-custom'], 'custom-header') - t.notOk(socket.closed) + t.strictEqual(headers[':status'], 200) + t.strictEqual(headers['x-custom'], 'custom-header') + t.strictEqual(socket.closed, false) }) // We need to handle the error event although @@ -620,22 +631,24 @@ test('Dispatcher#Connect', t => { socket.on('error', () => {}) socket.once('end', () => { - t.equal(requestBody, expectedBody) - t.equal(result, 'hello h2!') + t.strictEqual(requestBody, expectedBody) + t.strictEqual(result, 'hello h2!') }) socket.end(expectedBody) }) }) + + await t.completed }) -test('Dispatcher#Upgrade', t => { +test('Dispatcher#Upgrade', async t => { const server = createSecureServer(pem) server.on('stream', async (stream, headers) => { stream.end() }) - t.plan(1) + t = tspl(t, { plan: 1 }) server.listen(0, async () => { const client = new Client(`https://localhost:${server.address().port}`, { @@ -645,15 +658,17 @@ test('Dispatcher#Upgrade', t => { allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) try { await client.upgrade({ path: '/' }) } catch (error) { - t.equal(error.message, 'Upgrade not supported for H2') + t.strictEqual(error.message, 'Upgrade not supported for H2') } }) + + await t.completed }) test('Dispatcher#destroy', async t => { @@ -674,8 +689,8 @@ test('Dispatcher#destroy', async t => { allowH2: true }) - t.plan(4) - t.teardown(server.close.bind(server)) + t = tspl(t, { plan: 4 }) + after(() => server.close()) promises.push( client.request({ @@ -721,10 +736,10 @@ test('Dispatcher#destroy', async t => { const results = await Promise.allSettled(promises) - t.equal(results[0].status, 'rejected') - t.equal(results[1].status, 'rejected') - t.equal(results[2].status, 'rejected') - t.equal(results[3].status, 'rejected') + t.strictEqual(results[0].status, 'rejected') + t.strictEqual(results[1].status, 'rejected') + t.strictEqual(results[2].status, 'rejected') + t.strictEqual(results[3].status, 'rejected') }) test('Should handle h2 request without body', async t => { @@ -734,9 +749,9 @@ test('Should handle h2 request without body', async t => { const responseBody = [] server.on('stream', async (stream, headers) => { - t.equal(headers[':method'], 'POST') - t.equal(headers[':path'], '/') - t.equal(headers[':scheme'], 'https') + t.strictEqual(headers[':method'], 'POST') + t.strictEqual(headers[':path'], '/') + t.strictEqual(headers[':scheme'], 'https') stream.respond({ 'content-type': 'text/plain; charset=utf-8', @@ -751,7 +766,7 @@ test('Should handle h2 request without body', async t => { stream.end('hello h2!') }) - t.plan(9) + t = tspl(t, { plan: 9 }) server.listen(0) await once(server, 'listening') @@ -763,8 +778,8 @@ test('Should handle h2 request without body', async t => { allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -778,15 +793,15 @@ test('Should handle h2 request without body', async t => { responseBody.push(chunk) } - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'foo') - t.equal(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') - t.equal(requestChunks.length, 0) - t.equal(Buffer.concat(requestChunks).toString('utf-8'), expectedBody) + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'foo') + t.strictEqual(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') + t.strictEqual(requestChunks.length, 0) + t.strictEqual(Buffer.concat(requestChunks).toString('utf-8'), expectedBody) }) -test('Should handle h2 request with body (string or buffer) - dispatch', t => { +test('Should handle h2 request with body (string or buffer) - dispatch', async t => { const server = createSecureServer(pem) const expectedBody = 'hello from client!' const response = [] @@ -804,7 +819,7 @@ test('Should handle h2 request with body (string or buffer) - dispatch', t => { stream.end('hello h2!') }) - t.plan(7) + t = tspl(t, { plan: 7 }) server.listen(0, () => { const client = new Client(`https://localhost:${server.address().port}`, { @@ -814,8 +829,8 @@ test('Should handle h2 request with body (string or buffer) - dispatch', t => { allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) client.dispatch( { @@ -832,22 +847,22 @@ test('Should handle h2 request with body (string or buffer) - dispatch', t => { t.ok(true, 'pass') }, onError (err) { - t.error(err) + t.ifError(err) }, onHeaders (statusCode, headers) { - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain; charset=utf-8') - t.equal(headers['x-custom-h2'], 'foo') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(headers['x-custom-h2'], 'foo') }, onData (chunk) { response.push(chunk) }, onBodySent (body) { - t.equal(body.toString('utf-8'), expectedBody) + t.strictEqual(body.toString('utf-8'), expectedBody) }, onComplete () { - t.equal(Buffer.concat(response).toString('utf-8'), 'hello h2!') - t.equal( + t.strictEqual(Buffer.concat(response).toString('utf-8'), 'hello h2!') + t.strictEqual( Buffer.concat(requestBody).toString('utf-8'), 'hello from client!' ) @@ -855,6 +870,8 @@ test('Should handle h2 request with body (string or buffer) - dispatch', t => { } ) }) + + await t.completed }) test('Should handle h2 request with body (stream)', async t => { @@ -865,9 +882,9 @@ test('Should handle h2 request with body (stream)', async t => { const responseBody = [] server.on('stream', async (stream, headers) => { - t.equal(headers[':method'], 'PUT') - t.equal(headers[':path'], '/') - t.equal(headers[':scheme'], 'https') + t.strictEqual(headers[':method'], 'PUT') + t.strictEqual(headers[':path'], '/') + t.strictEqual(headers[':scheme'], 'https') stream.respond({ 'content-type': 'text/plain; charset=utf-8', @@ -882,7 +899,7 @@ test('Should handle h2 request with body (stream)', async t => { stream.end('hello h2!') }) - t.plan(8) + t = tspl(t, { plan: 8 }) server.listen(0) await once(server, 'listening') @@ -894,8 +911,8 @@ test('Should handle h2 request with body (stream)', async t => { allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -910,11 +927,11 @@ test('Should handle h2 request with body (stream)', async t => { responseBody.push(chunk) } - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'foo') - t.equal(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') - t.equal(Buffer.concat(requestChunks).toString('utf-8'), expectedBody) + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'foo') + t.strictEqual(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') + t.strictEqual(Buffer.concat(requestChunks).toString('utf-8'), expectedBody) }) test('Should handle h2 request with body (iterable)', async t => { @@ -934,9 +951,9 @@ test('Should handle h2 request with body (iterable)', async t => { } server.on('stream', async (stream, headers) => { - t.equal(headers[':method'], 'POST') - t.equal(headers[':path'], '/') - t.equal(headers[':scheme'], 'https') + t.strictEqual(headers[':method'], 'POST') + t.strictEqual(headers[':path'], '/') + t.strictEqual(headers[':scheme'], 'https') stream.on('data', chunk => requestChunks.push(chunk)) @@ -949,7 +966,7 @@ test('Should handle h2 request with body (iterable)', async t => { stream.end('hello h2!') }) - t.plan(8) + t = tspl(t, { plan: 8 }) server.listen(0) await once(server, 'listening') @@ -961,8 +978,8 @@ test('Should handle h2 request with body (iterable)', async t => { allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -979,11 +996,11 @@ test('Should handle h2 request with body (iterable)', async t => { await once(response.body, 'end') - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'foo') - t.equal(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') - t.equal(Buffer.concat(requestChunks).toString('utf-8'), expectedBody) + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'foo') + t.strictEqual(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') + t.strictEqual(Buffer.concat(requestChunks).toString('utf-8'), expectedBody) }) test('Should handle h2 request with body (Blob)', { skip: !Blob }, async t => { @@ -996,9 +1013,9 @@ test('Should handle h2 request with body (Blob)', { skip: !Blob }, async t => { }) server.on('stream', async (stream, headers) => { - t.equal(headers[':method'], 'POST') - t.equal(headers[':path'], '/') - t.equal(headers[':scheme'], 'https') + t.strictEqual(headers[':method'], 'POST') + t.strictEqual(headers[':path'], '/') + t.strictEqual(headers[':scheme'], 'https') stream.on('data', chunk => requestChunks.push(chunk)) @@ -1011,7 +1028,7 @@ test('Should handle h2 request with body (Blob)', { skip: !Blob }, async t => { stream.end('hello h2!') }) - t.plan(8) + t = tspl(t, { plan: 8 }) server.listen(0) await once(server, 'listening') @@ -1023,8 +1040,8 @@ test('Should handle h2 request with body (Blob)', { skip: !Blob }, async t => { allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -1041,11 +1058,11 @@ test('Should handle h2 request with body (Blob)', { skip: !Blob }, async t => { await once(response.body, 'end') - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'foo') - t.equal(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') - t.equal(Buffer.concat(requestChunks).toString('utf-8'), expectedBody) + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'foo') + t.strictEqual(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') + t.strictEqual(Buffer.concat(requestChunks).toString('utf-8'), expectedBody) }) test( @@ -1062,9 +1079,9 @@ test( buf.copy(new Uint8Array(body)) server.on('stream', async (stream, headers) => { - t.equal(headers[':method'], 'POST') - t.equal(headers[':path'], '/') - t.equal(headers[':scheme'], 'https') + t.strictEqual(headers[':method'], 'POST') + t.strictEqual(headers[':path'], '/') + t.strictEqual(headers[':scheme'], 'https') stream.on('data', chunk => requestChunks.push(chunk)) @@ -1077,7 +1094,7 @@ test( stream.end('hello h2!') }) - t.plan(8) + t = tspl(t, { plan: 8 }) server.listen(0) await once(server, 'listening') @@ -1089,8 +1106,8 @@ test( allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -1107,11 +1124,11 @@ test( await once(response.body, 'end') - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'foo') - t.equal(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') - t.equal(Buffer.concat(requestChunks).toString('utf-8'), expectedBody) + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'foo') + t.strictEqual(Buffer.concat(responseBody).toString('utf-8'), 'hello h2!') + t.strictEqual(Buffer.concat(requestChunks).toString('utf-8'), expectedBody) } ) @@ -1120,8 +1137,8 @@ test('Agent should support H2 connection', async t => { const server = createSecureServer(pem) server.on('stream', (stream, headers) => { - t.equal(headers['x-my-header'], 'foo') - t.equal(headers[':method'], 'GET') + t.strictEqual(headers['x-my-header'], 'foo') + t.strictEqual(headers[':method'], 'GET') stream.respond({ 'content-type': 'text/plain; charset=utf-8', 'x-custom-h2': 'hello', @@ -1140,9 +1157,9 @@ test('Agent should support H2 connection', async t => { allowH2: true }) - t.plan(6) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + t = tspl(t, { plan: 6 }) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ origin: `https://localhost:${server.address().port}`, @@ -1158,18 +1175,20 @@ test('Agent should support H2 connection', async t => { }) await once(response.body, 'end') - t.equal(response.statusCode, 200) - t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') - t.equal(response.headers['x-custom-h2'], 'hello') - t.equal(Buffer.concat(body).toString('utf8'), 'hello h2!') + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'hello') + t.strictEqual(Buffer.concat(body).toString('utf8'), 'hello h2!') }) test( 'Should provide pseudo-headers in proper order', async t => { + t = tspl(t, { plan: 2 }) + const server = createSecureServer(pem) server.on('stream', (stream, _headers, _flags, rawHeaders) => { - t.same(rawHeaders, [ + t.deepStrictEqual(rawHeaders, [ ':authority', `localhost:${server.address().port}`, ':method', @@ -1197,15 +1216,17 @@ test( allowH2: true }) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', method: 'GET' }) - t.equal(response.statusCode, 200) + t.strictEqual(response.statusCode, 200) + + await t.complete } ) @@ -1229,9 +1250,9 @@ test('The h2 pseudo-headers is not included in the headers', async t => { allowH2: true }) - t.plan(2) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + t = tspl(t, { plan: 2 }) + after(() => server.close()) + after(() => client.close()) const response = await client.request({ path: '/', @@ -1240,8 +1261,8 @@ test('The h2 pseudo-headers is not included in the headers', async t => { await response.body.text() - t.equal(response.statusCode, 200) - t.equal(response.headers[':status'], undefined) + t.strictEqual(response.statusCode, 200) + t.strictEqual(response.headers[':status'], undefined) }) test('Should throw informational error on half-closed streams (remote)', async t => { @@ -1261,15 +1282,15 @@ test('Should throw informational error on half-closed streams (remote)', async t allowH2: true }) - t.plan(2) - t.teardown(server.close.bind(server)) - t.teardown(client.close.bind(client)) + t = tspl(t, { plan: 2 }) + after(() => server.close()) + after(() => client.close()) await client.request({ path: '/', method: 'GET' }).catch(err => { - t.equal(err.message, 'HTTP/2: stream half-closed (remote)') - t.equal(err.code, 'UND_ERR_INFO') + t.strictEqual(err.message, 'HTTP/2: stream half-closed (remote)') + t.strictEqual(err.code, 'UND_ERR_INFO') }) }) diff --git a/test/readable.test.js b/test/readable.test.js index 3d6b5b1cea1..8e73301ea57 100644 --- a/test/readable.test.js +++ b/test/readable.test.js @@ -36,7 +36,7 @@ test('destroy timing text', async function (t) { const r = new Readable({ resume, abort }) r.destroy(new Error('kaboom')) - t.rejects(r.text(), new Error('kaboom')) + await t.rejects(r.text(), new Error('kaboom')) }) test('destroy timing promise', async function (t) { diff --git a/test/request.js b/test/request.js index bbfab5b3f5c..628bed0d415 100644 --- a/test/request.js +++ b/test/request.js @@ -1,10 +1,13 @@ 'use strict' +const { tspl } = require('@matteo.collina/tspl') const { createServer } = require('node:http') -const { test } = require('tap') +const { test, after, describe } = require('node:test') const { request, errors } = require('..') test('no-slash/one-slash pathname should be included in req.path', async (t) => { + t = tspl(t, { plan: 24 }) + const pathServer = createServer((req, res) => { t.fail('it shouldn\'t be called') res.statusCode = 200 @@ -12,15 +15,17 @@ test('no-slash/one-slash pathname should be included in req.path', async (t) => }) const requestedServer = createServer((req, res) => { - t.equal(`/localhost:${pathServer.address().port}`, req.url) - t.equal('GET', req.method) - t.equal(`localhost:${requestedServer.address().port}`, req.headers.host) + t.strictEqual(`/localhost:${pathServer.address().port}`, req.url) + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${requestedServer.address().port}`, req.headers.host) res.statusCode = 200 res.end('hello') }) - t.teardown(requestedServer.close.bind(requestedServer)) - t.teardown(pathServer.close.bind(pathServer)) + after(() => { + requestedServer.close() + pathServer.close() + }) await Promise.all([ requestedServer.listen(0), @@ -32,39 +37,41 @@ test('no-slash/one-slash pathname should be included in req.path', async (t) => origin: `http://localhost:${requestedServer.address().port}`, pathname: `localhost:${pathServer.address().port}` }) - t.equal(noSlashPathname.statusCode, 200) + t.strictEqual(noSlashPathname.statusCode, 200) const noSlashPath = await request({ method: 'GET', origin: `http://localhost:${requestedServer.address().port}`, path: `localhost:${pathServer.address().port}` }) - t.equal(noSlashPath.statusCode, 200) + t.strictEqual(noSlashPath.statusCode, 200) const noSlashPath2Arg = await request( `http://localhost:${requestedServer.address().port}`, { path: `localhost:${pathServer.address().port}` } ) - t.equal(noSlashPath2Arg.statusCode, 200) + t.strictEqual(noSlashPath2Arg.statusCode, 200) const oneSlashPathname = await request({ method: 'GET', origin: `http://localhost:${requestedServer.address().port}`, pathname: `/localhost:${pathServer.address().port}` }) - t.equal(oneSlashPathname.statusCode, 200) + t.strictEqual(oneSlashPathname.statusCode, 200) const oneSlashPath = await request({ method: 'GET', origin: `http://localhost:${requestedServer.address().port}`, path: `/localhost:${pathServer.address().port}` }) - t.equal(oneSlashPath.statusCode, 200) + t.strictEqual(oneSlashPath.statusCode, 200) const oneSlashPath2Arg = await request( `http://localhost:${requestedServer.address().port}`, { path: `/localhost:${pathServer.address().port}` } ) - t.equal(oneSlashPath2Arg.statusCode, 200) + t.strictEqual(oneSlashPath2Arg.statusCode, 200) t.end() }) test('protocol-relative URL as pathname should be included in req.path', async (t) => { + t = tspl(t, { plan: 12 }) + const pathServer = createServer((req, res) => { t.fail('it shouldn\'t be called') res.statusCode = 200 @@ -72,15 +79,17 @@ test('protocol-relative URL as pathname should be included in req.path', async ( }) const requestedServer = createServer((req, res) => { - t.equal(`//localhost:${pathServer.address().port}`, req.url) - t.equal('GET', req.method) - t.equal(`localhost:${requestedServer.address().port}`, req.headers.host) + t.strictEqual(`//localhost:${pathServer.address().port}`, req.url) + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${requestedServer.address().port}`, req.headers.host) res.statusCode = 200 res.end('hello') }) - t.teardown(requestedServer.close.bind(requestedServer)) - t.teardown(pathServer.close.bind(pathServer)) + after(() => { + requestedServer.close() + pathServer.close() + }) await Promise.all([ requestedServer.listen(0), @@ -92,22 +101,24 @@ test('protocol-relative URL as pathname should be included in req.path', async ( origin: `http://localhost:${requestedServer.address().port}`, pathname: `//localhost:${pathServer.address().port}` }) - t.equal(noSlashPathname.statusCode, 200) + t.strictEqual(noSlashPathname.statusCode, 200) const noSlashPath = await request({ method: 'GET', origin: `http://localhost:${requestedServer.address().port}`, path: `//localhost:${pathServer.address().port}` }) - t.equal(noSlashPath.statusCode, 200) + t.strictEqual(noSlashPath.statusCode, 200) const noSlashPath2Arg = await request( `http://localhost:${requestedServer.address().port}`, { path: `//localhost:${pathServer.address().port}` } ) - t.equal(noSlashPath2Arg.statusCode, 200) + t.strictEqual(noSlashPath2Arg.statusCode, 200) t.end() }) test('Absolute URL as pathname should be included in req.path', async (t) => { + t = tspl(t, { plan: 12 }) + const pathServer = createServer((req, res) => { t.fail('it shouldn\'t be called') res.statusCode = 200 @@ -115,15 +126,17 @@ test('Absolute URL as pathname should be included in req.path', async (t) => { }) const requestedServer = createServer((req, res) => { - t.equal(`/http://localhost:${pathServer.address().port}`, req.url) - t.equal('GET', req.method) - t.equal(`localhost:${requestedServer.address().port}`, req.headers.host) + t.strictEqual(`/http://localhost:${pathServer.address().port}`, req.url) + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${requestedServer.address().port}`, req.headers.host) res.statusCode = 200 res.end('hello') }) - t.teardown(requestedServer.close.bind(requestedServer)) - t.teardown(pathServer.close.bind(pathServer)) + after(() => { + requestedServer.close() + pathServer.close() + }) await Promise.all([ requestedServer.listen(0), @@ -135,46 +148,46 @@ test('Absolute URL as pathname should be included in req.path', async (t) => { origin: `http://localhost:${requestedServer.address().port}`, pathname: `http://localhost:${pathServer.address().port}` }) - t.equal(noSlashPathname.statusCode, 200) + t.strictEqual(noSlashPathname.statusCode, 200) const noSlashPath = await request({ method: 'GET', origin: `http://localhost:${requestedServer.address().port}`, path: `http://localhost:${pathServer.address().port}` }) - t.equal(noSlashPath.statusCode, 200) + t.strictEqual(noSlashPath.statusCode, 200) const noSlashPath2Arg = await request( `http://localhost:${requestedServer.address().port}`, { path: `http://localhost:${pathServer.address().port}` } ) - t.equal(noSlashPath2Arg.statusCode, 200) + t.strictEqual(noSlashPath2Arg.statusCode, 200) t.end() }) -test('DispatchOptions#reset', scope => { - scope.plan(4) +describe('DispatchOptions#reset', () => { + test('Should throw if invalid reset option', async t => { + t = tspl(t, { plan: 1 }) - scope.test('Should throw if invalid reset option', t => { - t.plan(1) - - t.rejects(request({ + await t.rejects(request({ method: 'GET', origin: 'http://somehost.xyz', reset: 0 - }), 'invalid reset') + }), /invalid reset/) + + await t.completed }) - scope.test('Should include "connection:close" if reset true', async t => { + test('Should include "connection:close" if reset true', async t => { + t = tspl(t, { plan: 3 }) + const server = createServer((req, res) => { - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) - t.equal(req.headers.connection, 'close') + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual(req.headers.connection, 'close') res.statusCode = 200 res.end('hello') }) - t.plan(3) - - t.teardown(server.close.bind(server)) + after(() => server.close()) await new Promise((resolve, reject) => { server.listen(0, (err) => { @@ -190,18 +203,18 @@ test('DispatchOptions#reset', scope => { }) }) - scope.test('Should include "connection:keep-alive" if reset false', async t => { + test('Should include "connection:keep-alive" if reset false', async t => { + t = tspl(t, { plan: 3 }) + const server = createServer((req, res) => { - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) - t.equal(req.headers.connection, 'keep-alive') + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual(req.headers.connection, 'keep-alive') res.statusCode = 200 res.end('hello') }) - t.plan(3) - - t.teardown(server.close.bind(server)) + after(() => server.close()) await new Promise((resolve, reject) => { server.listen(0, (err) => { @@ -217,18 +230,18 @@ test('DispatchOptions#reset', scope => { }) }) - scope.test('Should react to manual set of "connection:close" header', async t => { + test('Should react to manual set of "connection:close" header', async t => { + t = tspl(t, { plan: 3 }) + const server = createServer((req, res) => { - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) - t.equal(req.headers.connection, 'close') + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual(req.headers.connection, 'close') res.statusCode = 200 res.end('hello') }) - t.plan(3) - - t.teardown(server.close.bind(server)) + after(() => server.close()) await new Promise((resolve, reject) => { server.listen(0, (err) => { @@ -247,14 +260,14 @@ test('DispatchOptions#reset', scope => { }) }) -test('Should include headers from iterable objects', scope => { - scope.plan(4) +describe('Should include headers from iterable objects', scope => { + test('Should include headers built with Headers global object', async t => { + t = tspl(t, { plan: 3 }) - scope.test('Should include headers built with Headers global object', async t => { const server = createServer((req, res) => { - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) - t.equal(req.headers.hello, 'world') + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual(req.headers.hello, 'world') res.statusCode = 200 res.end('hello') }) @@ -262,9 +275,7 @@ test('Should include headers from iterable objects', scope => { const headers = new Headers() headers.set('hello', 'world') - t.plan(3) - - t.teardown(server.close.bind(server)) + after(() => server.close()) await new Promise((resolve, reject) => { server.listen(0, (err) => { @@ -281,11 +292,13 @@ test('Should include headers from iterable objects', scope => { }) }) - scope.test('Should include headers built with Map', async t => { + test('Should include headers built with Map', async t => { + t = tspl(t, { plan: 3 }) + const server = createServer((req, res) => { - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) - t.equal(req.headers.hello, 'world') + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual(req.headers.hello, 'world') res.statusCode = 200 res.end('hello') }) @@ -293,9 +306,7 @@ test('Should include headers from iterable objects', scope => { const headers = new Map() headers.set('hello', 'world') - t.plan(3) - - t.teardown(server.close.bind(server)) + after(() => server.close()) await new Promise((resolve, reject) => { server.listen(0, (err) => { @@ -312,11 +323,13 @@ test('Should include headers from iterable objects', scope => { }) }) - scope.test('Should include headers built with custom iterable object', async t => { + test('Should include headers built with custom iterable object', async t => { + t = tspl(t, { plan: 3 }) + const server = createServer((req, res) => { - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) - t.equal(req.headers.hello, 'world') + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual(req.headers.hello, 'world') res.statusCode = 200 res.end('hello') }) @@ -327,9 +340,7 @@ test('Should include headers from iterable objects', scope => { } } - t.plan(3) - - t.teardown(server.close.bind(server)) + after(() => server.close()) await new Promise((resolve, reject) => { server.listen(0, (err) => { @@ -346,7 +357,9 @@ test('Should include headers from iterable objects', scope => { }) }) - scope.test('Should throw error if headers iterable object does not yield key-value pairs', async t => { + test('Should throw error if headers iterable object does not yield key-value pairs', async t => { + t = tspl(t, { plan: 2 }) + const server = createServer((req, res) => { res.end('hello') }) @@ -357,9 +370,7 @@ test('Should include headers from iterable objects', scope => { } } - t.plan(2) - - t.teardown(server.close.bind(server)) + after(() => server.close()) await new Promise((resolve, reject) => { server.listen(0, (err) => { @@ -374,8 +385,8 @@ test('Should include headers from iterable objects', scope => { reset: true, headers }).catch((err) => { - t.type(err, errors.InvalidArgumentError) - t.equal(err.message, 'headers must be in key-value pair format') + t.ok(err instanceof errors.InvalidArgumentError) + t.strictEqual(err.message, 'headers must be in key-value pair format') }) }) }) From ae9587193403bccac4fdfe9ebc882c5240538cf3 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Mon, 12 Feb 2024 16:02:45 +0100 Subject: [PATCH 18/23] chore: migrate a batch of tests to node test runner (#2742) --- test/client-errors.js | 15 +- test/client-stream.js | 435 ++++++++++++++++++++---------------- test/connect-abort.js | 13 +- test/http-req-destroy.js | 23 +- test/https.js | 47 ++-- test/max-response-size.js | 57 ++--- test/parser-issues.js | 51 +++-- test/pipeline-pipelining.js | 45 ++-- test/socket-timeout.js | 45 ++-- test/stream-compat.js | 31 +-- test/trailers.js | 31 +-- 11 files changed, 446 insertions(+), 347 deletions(-) diff --git a/test/client-errors.js b/test/client-errors.js index 21732ac075a..0c935d7cdac 100644 --- a/test/client-errors.js +++ b/test/client-errors.js @@ -1,28 +1,31 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const net = require('node:net') // TODO: move to test/node-test/client-connect.js -test('parser error', (t) => { - t.plan(2) +test('parser error', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer() server.once('connection', (socket) => { socket.write('asd\n\r213123') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err) => { t.ok(err) client.close((err) => { - t.error(err) + t.ifError(err) }) }) }) + + await t.completed }) diff --git a/test/client-stream.js b/test/client-stream.js index 69843acf0df..8df8c690aea 100644 --- a/test/client-stream.js +++ b/test/client-stream.js @@ -1,26 +1,27 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, errors } = require('..') const { createServer } = require('node:http') const { PassThrough, Writable, Readable } = require('node:stream') const EE = require('node:events') -test('stream get', (t) => { - t.plan(9) +test('stream get', async (t) => { + t = tspl(t, { plan: 9 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const signal = new EE() client.stream({ @@ -29,81 +30,85 @@ test('stream get', (t) => { method: 'GET', opaque: new PassThrough() }, ({ statusCode, headers, opaque: pt }) => { - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] pt.on('data', (buf) => { bufs.push(buf) }) pt.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) return pt }, (err) => { - t.equal(signal.listenerCount('abort'), 0) - t.error(err) + t.strictEqual(signal.listenerCount('abort'), 0) + t.ifError(err) }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) }) + + await t.completed }) -test('stream promise get', (t) => { - t.plan(6) +test('stream promise get', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) await client.stream({ path: '/', method: 'GET', opaque: new PassThrough() }, ({ statusCode, headers, opaque: pt }) => { - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] pt.on('data', (buf) => { bufs.push(buf) }) pt.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) return pt }) }) + + await t.completed }) -test('stream GET destroy res', (t) => { - t.plan(14) +test('stream GET destroy res', async (t) => { + t = tspl(t, { plan: 14 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.stream({ path: '/', method: 'GET' }, ({ statusCode, headers }) => { - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const pt = new PassThrough() .on('error', (err) => { @@ -122,26 +127,28 @@ test('stream GET destroy res', (t) => { path: '/', method: 'GET' }, ({ statusCode, headers }) => { - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') let ret = '' const pt = new PassThrough() pt.on('data', chunk => { ret += chunk }).on('end', () => { - t.equal(ret, 'hello') + t.strictEqual(ret, 'hello') }) return pt }, (err) => { - t.error(err) + t.ifError(err) }) }) + + await t.completed }) -test('stream GET remote destroy', (t) => { - t.plan(4) +test('stream GET remote destroy', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.write('asd') @@ -149,11 +156,11 @@ test('stream GET remote destroy', (t) => { res.destroy() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.stream({ path: '/', @@ -181,10 +188,12 @@ test('stream GET remote destroy', (t) => { t.ok(err) }) }) + + await t.completed }) -test('stream response resume back pressure and non standard error', (t) => { - t.plan(5) +test('stream response resume back pressure and non standard error', async (t) => { + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { res.write(Buffer.alloc(1e3)) @@ -193,11 +202,11 @@ test('stream response resume back pressure and non standard error', (t) => { res.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const pt = new PassThrough() client.stream({ @@ -207,12 +216,12 @@ test('stream response resume back pressure and non standard error', (t) => { pt.on('data', () => { pt.emit('error', new Error('kaboom')) }).once('error', (err) => { - t.equal(err.message, 'kaboom') + t.strictEqual(err.message, 'kaboom') }) return pt }, (err) => { t.ok(err) - t.equal(pt.destroyed, true) + t.strictEqual(pt.destroyed, true) }) client.once('disconnect', (err) => { @@ -227,36 +236,40 @@ test('stream response resume back pressure and non standard error', (t) => { pt.resume() return pt }, (err) => { - t.error(err) + t.ifError(err) }) }) + + await t.completed }) -test('stream waits only for writable side', (t) => { - t.plan(2) +test('stream waits only for writable side', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.end(Buffer.alloc(1e3)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const pt = new PassThrough({ autoDestroy: false }) client.stream({ path: '/', method: 'GET' }, () => pt, (err) => { - t.error(err) - t.equal(pt.destroyed, false) + t.ifError(err) + t.strictEqual(pt.destroyed, false) }) }) + + await t.completed }) -test('stream args validation', (t) => { - t.plan(3) +test('stream args validation', async (t) => { + t = tspl(t, { plan: 3 }) const client = new Client('http://localhost:5000') client.stream({ @@ -277,8 +290,8 @@ test('stream args validation', (t) => { } }) -test('stream args validation promise', (t) => { - t.plan(2) +test('stream args validation promise', async (t) => { + t = tspl(t, { plan: 2 }) const client = new Client('http://localhost:5000') client.stream({ @@ -291,21 +304,23 @@ test('stream args validation promise', (t) => { client.stream(null, null).catch((err) => { t.ok(err instanceof errors.InvalidArgumentError) }) + + await t.completed }) -test('stream destroy if not readable', (t) => { - t.plan(2) +test('stream destroy if not readable', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const pt = new PassThrough() pt.readable = false server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(client.destroy.bind(client)) client.stream({ path: '/', @@ -313,23 +328,25 @@ test('stream destroy if not readable', (t) => { }, () => { return pt }, (err) => { - t.error(err) - t.equal(pt.destroyed, true) + t.ifError(err) + t.strictEqual(pt.destroyed, true) }) }) + + await t.completed }) -test('stream server side destroy', (t) => { - t.plan(1) +test('stream server side destroy', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.destroy() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(client.destroy.bind(client)) client.stream({ path: '/', @@ -340,19 +357,21 @@ test('stream server side destroy', (t) => { t.ok(err instanceof errors.SocketError) }) }) + + await t.completed }) -test('stream invalid return', (t) => { - t.plan(1) +test('stream invalid return', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.write('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(client.destroy.bind(client)) client.stream({ path: '/', @@ -363,19 +382,21 @@ test('stream invalid return', (t) => { t.ok(err instanceof errors.InvalidReturnValueError) }) }) + + await t.completed }) -test('stream body without destroy', (t) => { - t.plan(1) +test('stream body without destroy', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(client.destroy.bind(client)) client.stream({ path: '/', @@ -386,22 +407,24 @@ test('stream body without destroy', (t) => { pt.resume() return pt }, (err) => { - t.error(err) + t.ifError(err) }) }) + + await t.completed }) -test('stream factory abort', (t) => { - t.plan(3) +test('stream factory abort', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(client.destroy.bind(client)) const signal = new EE() client.stream({ @@ -412,24 +435,26 @@ test('stream factory abort', (t) => { signal.emit('abort') return new PassThrough() }, (err) => { - t.equal(signal.listenerCount('abort'), 0) + t.strictEqual(signal.listenerCount('abort'), 0) t.ok(err instanceof errors.RequestAbortedError) }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) }) + + await t.completed }) -test('stream factory throw', (t) => { - t.plan(3) +test('stream factory throw', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(client.destroy.bind(client)) client.stream({ path: '/', @@ -437,7 +462,7 @@ test('stream factory throw', (t) => { }, () => { throw new Error('asd') }, (err) => { - t.equal(err.message, 'asd') + t.strictEqual(err.message, 'asd') }) client.stream({ path: '/', @@ -445,7 +470,7 @@ test('stream factory throw', (t) => { }, () => { throw new Error('asd') }, (err) => { - t.equal(err.message, 'asd') + t.strictEqual(err.message, 'asd') }) client.stream({ path: '/', @@ -453,22 +478,24 @@ test('stream factory throw', (t) => { }, () => { return new PassThrough() }, (err) => { - t.error(err) + t.ifError(err) }) }) + + await t.completed }) -test('stream CONNECT throw', (t) => { - t.plan(1) +test('stream CONNECT throw', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(client.destroy.bind(client)) client.stream({ path: '/', @@ -478,19 +505,21 @@ test('stream CONNECT throw', (t) => { t.ok(err instanceof errors.InvalidArgumentError) }) }) + + await t.completed }) -test('stream abort after complete', (t) => { - t.plan(1) +test('stream abort after complete', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(client.destroy.bind(client)) const pt = new PassThrough() const signal = new EE() @@ -501,23 +530,25 @@ test('stream abort after complete', (t) => { }, () => { return pt }, (err) => { - t.error(err) + t.ifError(err) signal.emit('abort') }) }) + + await t.completed }) -test('stream abort before dispatch', (t) => { - t.plan(1) +test('stream abort before dispatch', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(client.destroy.bind(client)) const pt = new PassThrough() const signal = new EE() @@ -532,44 +563,48 @@ test('stream abort before dispatch', (t) => { }) signal.emit('abort') }) + + await t.completed }) -test('trailers', (t) => { - t.plan(2) +test('trailers', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.writeHead(200, { Trailer: 'Content-MD5' }) res.addTrailers({ 'Content-MD5': 'test' }) res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.stream({ path: '/', method: 'GET' }, () => new PassThrough(), (err, data) => { - t.error(err) - t.strictSame(data.trailers, { 'content-md5': 'test' }) + t.ifError(err) + t.deepStrictEqual(data.trailers, { 'content-md5': 'test' }) }) }) + + await t.completed }) -test('stream ignore 1xx', (t) => { - t.plan(2) +test('stream ignore 1xx', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.writeProcessing() res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) let buf = '' client.stream({ @@ -581,25 +616,27 @@ test('stream ignore 1xx', (t) => { callback() } }), (err, data) => { - t.error(err) - t.equal(buf, 'hello') + t.ifError(err) + t.strictEqual(buf, 'hello') }) }) + + await t.completed }) -test('stream ignore 1xx and use onInfo', (t) => { - t.plan(4) +test('stream ignore 1xx and use onInfo', async (t) => { + t = tspl(t, { plan: 4 }) const infos = [] const server = createServer((req, res) => { res.writeProcessing() res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) let buf = '' client.stream({ @@ -614,16 +651,18 @@ test('stream ignore 1xx and use onInfo', (t) => { callback() } }), (err, data) => { - t.error(err) - t.equal(buf, 'hello') - t.equal(infos.length, 1) - t.equal(infos[0].statusCode, 102) + t.ifError(err) + t.strictEqual(buf, 'hello') + t.strictEqual(infos.length, 1) + t.strictEqual(infos[0].statusCode, 102) }) }) + + await t.completed }) -test('stream backpressure', (t) => { - t.plan(2) +test('stream backpressure', async (t) => { + t = tspl(t, { plan: 2 }) const expected = Buffer.alloc(1e6).toString() @@ -631,11 +670,11 @@ test('stream backpressure', (t) => { res.writeProcessing() res.end(expected) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) let buf = '' client.stream({ @@ -648,49 +687,53 @@ test('stream backpressure', (t) => { process.nextTick(callback) } }), (err, data) => { - t.error(err) - t.equal(buf, expected) + t.ifError(err) + t.strictEqual(buf, expected) }) }) + + await t.completed }) -test('stream body destroyed on invalid callback', (t) => { - t.plan(1) +test('stream body destroyed on invalid callback', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(client.destroy.bind(client)) const body = new Readable({ - read () {} + read () { } }) try { client.stream({ path: '/', method: 'GET', body - }, () => {}, null) + }, () => { }, null) } catch (err) { - t.equal(body.destroyed, true) + t.strictEqual(body.destroyed, true) } }) + + await t.completed }) -test('stream needDrain', (t) => { - t.plan(3) +test('stream needDrain', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.end(Buffer.alloc(4096)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(() => { + after(() => { client.destroy() }) @@ -715,8 +758,8 @@ test('stream needDrain', (t) => { path: '/', method: 'GET' }, () => { - t.equal(dst._writableState.needDrain, true) - t.equal(dst.writableNeedDrain, true) + t.strictEqual(dst._writableState.needDrain, true) + t.strictEqual(dst.writableNeedDrain, true) setImmediate(() => { dst.write = (...args) => { @@ -732,19 +775,21 @@ test('stream needDrain', (t) => { t.ok(true, 'pass') }) }) + + await t.completed }) -test('stream legacy needDrain', (t) => { - t.plan(3) +test('stream legacy needDrain', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.end(Buffer.alloc(4096)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(() => { + after(() => { client.destroy() }) @@ -768,8 +813,8 @@ test('stream legacy needDrain', (t) => { path: '/', method: 'GET' }, () => { - t.equal(dst._writableState.needDrain, true) - t.equal(dst.writableNeedDrain, undefined) + t.strictEqual(dst._writableState.needDrain, true) + t.strictEqual(dst.writableNeedDrain, undefined) setImmediate(() => { dst.write = (...args) => { @@ -785,63 +830,67 @@ test('stream legacy needDrain', (t) => { t.ok(true, 'pass') }) }) + await t.completed +}) - test('stream throwOnError', (t) => { - t.plan(2) +test('stream throwOnError', async (t) => { + t = tspl(t, { plan: 3 }) - const errStatusCode = 500 - const errMessage = 'Internal Server Error' + const errStatusCode = 500 + const errMessage = 'Internal Server Error' - const server = createServer((req, res) => { - res.writeHead(errStatusCode, { 'Content-Type': 'text/plain' }) - res.end(errMessage) - }) - t.teardown(server.close.bind(server)) + const server = createServer((req, res) => { + res.writeHead(errStatusCode, { 'Content-Type': 'text/plain' }) + res.end(errMessage) + }) + after(() => server.close()) - server.listen(0, async () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) - client.stream({ - path: '/', - method: 'GET', - throwOnError: true, - opaque: new PassThrough() - }, ({ opaque: pt }) => { - pt.on('data', () => { - t.fail() - }) - return pt - }, (e) => { - t.equal(e.status, errStatusCode) - t.equal(e.body, errMessage) - t.end() + client.stream({ + path: '/', + method: 'GET', + throwOnError: true, + opaque: new PassThrough() + }, ({ opaque: pt }) => { + pt.on('data', () => { + t.fail() }) + return pt + }, (e) => { + t.strictEqual(e.status, errStatusCode) + t.strictEqual(e.body, errMessage) + t.ok(true, 'end') }) }) - test('steam throwOnError=true, error on stream', (t) => { - t.plan(1) + await t.completed +}) - const server = createServer((req, res) => { - res.end('asd') - }) - t.teardown(server.close.bind(server)) +test('steam throwOnError=true, error on stream', async (t) => { + t = tspl(t, { plan: 1 }) + + const server = createServer((req, res) => { + res.end('asd') + }) + after(() => server.close()) - server.listen(0, async () => { - const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + after(() => client.close()) - client.stream({ - path: '/', - method: 'GET', - throwOnError: true, - opaque: new PassThrough() - }, () => { - throw new Error('asd') - }, (e) => { - t.equal(e.message, 'asd') - }) + client.stream({ + path: '/', + method: 'GET', + throwOnError: true, + opaque: new PassThrough() + }, () => { + throw new Error('asd') + }, (e) => { + t.strictEqual(e.message, 'asd') }) }) + await t.completed }) diff --git a/test/connect-abort.js b/test/connect-abort.js index 91ed1b2a258..bf75fd8bd6a 100644 --- a/test/connect-abort.js +++ b/test/connect-abort.js @@ -1,18 +1,19 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test } = require('node:test') const { Client } = require('..') const { PassThrough } = require('node:stream') -test(t => { - t.plan(2) +test('connect-abort', async t => { + t = tspl(t, { plan: 2 }) const client = new Client('http://localhost:1234', { connect: (_, cb) => { client.destroy() cb(null, new PassThrough({ destroy (err, cb) { - t.same(err?.name, 'ClientDestroyedError') + t.strictEqual(err.name, 'ClientDestroyedError') cb(null) } })) @@ -23,6 +24,8 @@ test(t => { path: '/', method: 'GET' }, (err, data) => { - t.same(err?.name, 'ClientDestroyedError') + t.strictEqual(err.name, 'ClientDestroyedError') }) + + await t.completed }) diff --git a/test/http-req-destroy.js b/test/http-req-destroy.js index d0d83b6d848..ea7624c611d 100644 --- a/test/http-req-destroy.js +++ b/test/http-req-destroy.js @@ -1,24 +1,25 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const undici = require('..') const { createServer } = require('node:http') const { Readable } = require('node:stream') const { maybeWrapStream, consts } = require('./utils/async-iterators') function doNotKillReqSocket (bodyType) { - test(`do not kill req socket ${bodyType}`, (t) => { - t.plan(3) + test(`do not kill req socket ${bodyType}`, async (t) => { + t = tspl(t, { plan: 3 }) const server1 = createServer((req, res) => { const client = new undici.Client(`http://localhost:${server2.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'POST', body: req }, (err, response) => { - t.error(err) + t.ifError(err) setTimeout(() => { response.body.on('data', buf => { res.write(buf) @@ -29,18 +30,18 @@ function doNotKillReqSocket (bodyType) { }, 100) }) }) - t.teardown(server1.close.bind(server1)) + after(() => server1.close()) const server2 = createServer((req, res) => { setTimeout(() => { req.pipe(res) }, 100) }) - t.teardown(server2.close.bind(server2)) + after(() => server2.close()) server1.listen(0, () => { const client = new undici.Client(`http://localhost:${server1.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const r = new Readable({ read () {} }) r.push('hello') @@ -49,19 +50,21 @@ function doNotKillReqSocket (bodyType) { method: 'POST', body: maybeWrapStream(r, bodyType) }, (err, response) => { - t.error(err) + t.ifError(err) const bufs = [] response.body.on('data', (buf) => { bufs.push(buf) r.push(null) }) response.body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) server2.listen(0) + + await t.completed }) } diff --git a/test/https.js b/test/https.js index 5d9ab3d8e22..418fb969f45 100644 --- a/test/https.js +++ b/test/https.js @@ -1,20 +1,21 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const { createServer } = require('node:https') const pem = require('https-pem') -test('https get with tls opts', (t) => { - t.plan(6) +test('https get with tls opts', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer(pem, (req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`https://localhost:${server.address().port}`, { @@ -22,33 +23,35 @@ test('https get with tls opts', (t) => { rejectUnauthorized: false } }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('https get with tls opts ip', (t) => { - t.plan(6) +test('https get with tls opts ip', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer(pem, (req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`https://127.0.0.1:${server.address().port}`, { @@ -56,19 +59,21 @@ test('https get with tls opts ip', (t) => { rejectUnauthorized: false } }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) diff --git a/test/max-response-size.js b/test/max-response-size.js index adf75c6fee2..1e0d904469a 100644 --- a/test/max-response-size.js +++ b/test/max-response-size.js @@ -1,17 +1,16 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after, describe } = require('node:test') const { Client, errors } = require('..') const { createServer } = require('node:http') -test('max response size', (t) => { - t.plan(4) - - t.test('default max default size should allow all responses', (t) => { - t.plan(3) +describe('max response size', async (t) => { + test('default max default size should allow all responses', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer() - t.teardown(server.close.bind(server)) + after(() => server.close()) server.on('request', (req, res) => { res.end('hello') @@ -19,27 +18,29 @@ test('max response size', (t) => { server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { maxResponseSize: -1 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, { statusCode, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) - t.test('max response size set to zero should allow only empty responses', (t) => { - t.plan(3) + test('max response size set to zero should allow only empty responses', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer() - t.teardown(server.close.bind(server)) + after(() => server.close()) server.on('request', (req, res) => { res.end() @@ -47,27 +48,29 @@ test('max response size', (t) => { server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { maxResponseSize: 0 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, { statusCode, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) - t.test('should throw an error if the response is too big', (t) => { - t.plan(3) + test('should throw an error if the response is too big', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer() - t.teardown(server.close.bind(server)) + after(() => server.close()) server.on('request', (req, res) => { res.end('hello') @@ -78,20 +81,22 @@ test('max response size', (t) => { maxResponseSize: 1 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, { body }) => { - t.error(err) + t.ifError(err) body.on('error', (err) => { t.ok(err) t.ok(err instanceof errors.ResponseExceededMaxSizeError) }) }) }) + + await t.completed }) - t.test('invalid max response size should throw an error', (t) => { - t.plan(2) + test('invalid max response size should throw an error', async (t) => { + t = tspl(t, { plan: 2 }) t.throws(() => { // eslint-disable-next-line no-new @@ -102,4 +107,6 @@ test('max response size', (t) => { new Client('http://localhost:3000', { maxResponseSize: -2 }) }, 'maxResponseSize must be greater than or equal to -1') }) + + await t.completed }) diff --git a/test/parser-issues.js b/test/parser-issues.js index 3602ae1ba5e..2d9f04628de 100644 --- a/test/parser-issues.js +++ b/test/parser-issues.js @@ -1,9 +1,12 @@ +'use strict' + +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const net = require('node:net') -const { test } = require('tap') const { Client, errors } = require('..') -test('https://github.com/mcollina/undici/issues/268', (t) => { - t.plan(2) +test('https://github.com/mcollina/undici/issues/268', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer(socket => { socket.write('HTTP/1.1 200 OK\r\n') @@ -17,18 +20,18 @@ test('https://github.com/mcollina/undici/issues/268', (t) => { }, 500) }, 500) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ method: 'GET', path: '/nxt/_changes?feed=continuous&heartbeat=5000', headersTimeout: 1e3 }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() setTimeout(() => { @@ -37,19 +40,21 @@ test('https://github.com/mcollina/undici/issues/268', (t) => { }, 2e3) }) }) + + await t.completed }) -test('parser fail', (t) => { - t.plan(2) +test('parser fail', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer(socket => { socket.write('HTT/1.1 200 OK\r\n') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ method: 'GET', @@ -59,10 +64,12 @@ test('parser fail', (t) => { t.ok(err instanceof errors.HTTPParserError) }) }) + + await t.completed }) -test('split header field', (t) => { - t.plan(2) +test('split header field', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer(socket => { socket.write('HTTP/1.1 200 OK\r\nA') @@ -70,25 +77,27 @@ test('split header field', (t) => { socket.write('SD: asd,asd\r\n\r\n\r\n') }, 100) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ method: 'GET', path: '/' }, (err, data) => { - t.error(err) + t.ifError(err) t.equal(data.headers.asd, 'asd,asd') data.body.destroy().on('error', () => {}) }) }) + + await t.completed }) -test('split header value', (t) => { - t.plan(2) +test('split header value', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer(socket => { socket.write('HTTP/1.1 200 OK\r\nASD: asd') @@ -96,19 +105,21 @@ test('split header value', (t) => { socket.write(',asd\r\n\r\n\r\n') }, 100) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ method: 'GET', path: '/' }, (err, data) => { - t.error(err) + t.ifError(err) t.equal(data.headers.asd, 'asd,asd') data.body.destroy().on('error', () => {}) }) }) + + await t.completed }) diff --git a/test/pipeline-pipelining.js b/test/pipeline-pipelining.js index d3f7143cba4..b244925786a 100644 --- a/test/pipeline-pipelining.js +++ b/test/pipeline-pipelining.js @@ -1,25 +1,26 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const { createServer } = require('node:http') const { kConnect } = require('../lib/core/symbols') const { kBusy, kPending, kRunning } = require('../lib/core/symbols') -test('pipeline pipelining', (t) => { - t.plan(10) +test('pipeline pipelining', async (t) => { + t = tspl(t, { plan: 10 }) const server = createServer((req, res) => { - t.strictSame(req.headers['transfer-encoding'], undefined) + t.deepStrictEqual(req.headers['transfer-encoding'], undefined) res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client[kConnect](() => { t.equal(client[kRunning], 0) @@ -28,25 +29,27 @@ test('pipeline pipelining', (t) => { path: '/' }, ({ body }) => body).end().resume() t.equal(client[kBusy], true) - t.strictSame(client[kRunning], 0) - t.strictSame(client[kPending], 1) + t.deepStrictEqual(client[kRunning], 0) + t.deepStrictEqual(client[kPending], 1) client.pipeline({ method: 'GET', path: '/' }, ({ body }) => body).end().resume() t.equal(client[kBusy], true) - t.strictSame(client[kRunning], 0) - t.strictSame(client[kPending], 2) + t.deepStrictEqual(client[kRunning], 0) + t.deepStrictEqual(client[kPending], 2) process.nextTick(() => { t.equal(client[kRunning], 2) }) }) }) + + await t.completed }) -test('pipeline pipelining retry', (t) => { - t.plan(13) +test('pipeline pipelining retry', async (t) => { + t = tspl(t, { plan: 13 }) let count = 0 const server = createServer((req, res) => { @@ -57,12 +60,12 @@ test('pipeline pipelining retry', (t) => { } }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 3 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.once('disconnect', () => { t.ok(true, 'pass') @@ -77,24 +80,24 @@ test('pipeline pipelining retry', (t) => { t.ok(err) }) t.equal(client[kBusy], true) - t.strictSame(client[kRunning], 0) - t.strictSame(client[kPending], 1) + t.deepStrictEqual(client[kRunning], 0) + t.deepStrictEqual(client[kPending], 1) client.pipeline({ method: 'GET', path: '/' }, ({ body }) => body).end().resume() t.equal(client[kBusy], true) - t.strictSame(client[kRunning], 0) - t.strictSame(client[kPending], 2) + t.deepStrictEqual(client[kRunning], 0) + t.deepStrictEqual(client[kPending], 2) client.pipeline({ method: 'GET', path: '/' }, ({ body }) => body).end().resume() t.equal(client[kBusy], true) - t.strictSame(client[kRunning], 0) - t.strictSame(client[kPending], 3) + t.deepStrictEqual(client[kRunning], 0) + t.deepStrictEqual(client[kPending], 3) process.nextTick(() => { t.equal(client[kRunning], 3) @@ -105,4 +108,6 @@ test('pipeline pipelining retry', (t) => { }) }) }) + + await t.completed }) diff --git a/test/socket-timeout.js b/test/socket-timeout.js index a0facda8369..83617e94f7e 100644 --- a/test/socket-timeout.js +++ b/test/socket-timeout.js @@ -1,13 +1,14 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, errors } = require('..') const timers = require('../lib/timers') const { createServer } = require('node:http') const FakeTimers = require('@sinonjs/fake-timers') -test('timeout with pipelining 1', (t) => { - t.plan(9) +test('timeout with pipelining 1', async (t) => { + t = tspl(t, { plan: 9 }) const server = createServer() @@ -15,13 +16,13 @@ test('timeout with pipelining 1', (t) => { t.ok(true, 'first request received, we are letting this timeout on the client') server.once('request', (req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { @@ -29,7 +30,7 @@ test('timeout with pipelining 1', (t) => { headersTimeout: 500, bodyTimeout: 500 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -37,37 +38,39 @@ test('timeout with pipelining 1', (t) => { opaque: 'asd' }, (err, data) => { t.ok(err instanceof errors.HeadersTimeoutError) // we are expecting an error - t.equal(data.opaque, 'asd') + t.strictEqual(data.opaque, 'asd') }) client.request({ path: '/', method: 'GET' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('Disable socket timeout', (t) => { - t.plan(2) +test('Disable socket timeout', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer() const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + after(clock.uninstall.bind(clock)) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -77,24 +80,26 @@ test('Disable socket timeout', (t) => { }, 31e3) clock.tick(32e3) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0, headersTimeout: 0 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, result) => { - t.error(err) + t.ifError(err) const bufs = [] result.body.on('data', (buf) => { bufs.push(buf) }) result.body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) diff --git a/test/stream-compat.js b/test/stream-compat.js index 02d521a9d65..5f219fe42e3 100644 --- a/test/stream-compat.js +++ b/test/stream-compat.js @@ -1,21 +1,22 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const { createServer } = require('node:http') const { Readable } = require('node:stream') const EE = require('node:events') -test('stream body without destroy', (t) => { - t.plan(2) +test('stream body without destroy', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const signal = new EE() const body = new Readable({ read () {} }) @@ -33,19 +34,21 @@ test('stream body without destroy', (t) => { }) signal.emit('abort') }) + + await t.completed }) -test('IncomingMessage', (t) => { - t.plan(2) +test('IncomingMessage', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const proxyClient = new Client(`http://localhost:${server.address().port}`) - t.teardown(proxyClient.destroy.bind(proxyClient)) + after(() => proxyClient.destroy()) const proxy = createServer((req, res) => { proxyClient.request({ @@ -53,23 +56,25 @@ test('IncomingMessage', (t) => { method: 'PUT', body: req }, (err, data) => { - t.error(err) + t.ifError(err) data.body.pipe(res) }) }) - t.teardown(proxy.close.bind(proxy)) + after(() => proxy.close()) proxy.listen(0, () => { const client = new Client(`http://localhost:${proxy.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'PUT', body: 'hello world' }, (err, data) => { - t.error(err) + t.ifError(err) }) }) }) + + await t.completed }) diff --git a/test/trailers.js b/test/trailers.js index e56542568ab..8f616e87eba 100644 --- a/test/trailers.js +++ b/test/trailers.js @@ -1,11 +1,12 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client } = require('..') const { createServer } = require('node:http') -test('response trailers missing is OK', (t) => { - t.plan(1) +test('response trailers missing is OK', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.writeHead(200, { @@ -13,23 +14,24 @@ test('response trailers missing is OK', (t) => { }) res.end('response') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - + after(() => client.destroy()) const { body } = await client.request({ path: '/', method: 'GET', body: 'asd' }) - t.equal(await body.text(), 'response') + t.strictEqual(await body.text(), 'response') }) + + await t.completed }) -test('response trailers missing w trailers is OK', (t) => { - t.plan(2) +test('response trailers missing w trailers is OK', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.writeHead(200, { @@ -40,18 +42,19 @@ test('response trailers missing w trailers is OK', (t) => { }) res.end('response') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) - + after(() => client.destroy()) const { body, trailers } = await client.request({ path: '/', method: 'GET', body: 'asd' }) - t.equal(await body.text(), 'response') - t.same(trailers, { asd: 'foo' }) + t.strictEqual(await body.text(), 'response') + t.deepStrictEqual(trailers, { asd: 'foo' }) }) + + await t.completed }) From e17a1639be68d5a1edba08cb1f5a0e53d3c16c12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 22:51:32 +0000 Subject: [PATCH 19/23] build(deps-dev): bump cronometro from 2.0.2 to 3.0.1 (#2749) Bumps [cronometro](https://github.com/ShogunPanda/cronometro) from 2.0.2 to 3.0.1. - [Release notes](https://github.com/ShogunPanda/cronometro/releases) - [Changelog](https://github.com/ShogunPanda/cronometro/blob/main/CHANGELOG.md) - [Commits](https://github.com/ShogunPanda/cronometro/compare/v2.0.2...v3.0.1) --- updated-dependencies: - dependency-name: cronometro dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index acbb493382d..92227f2799e 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "axios": "^1.6.5", "borp": "^0.9.1", "concurrently": "^8.0.1", - "cronometro": "^2.0.2", + "cronometro": "^3.0.1", "dns-packet": "^5.4.0", "docsify-cli": "^4.4.3", "form-data": "^4.0.0", From c60acb50353e13ab2d14f4be82071028590a085c Mon Sep 17 00:00:00 2001 From: tsctx <91457664+tsctx@users.noreply.github.com> Date: Tue, 13 Feb 2024 17:20:34 +0900 Subject: [PATCH 20/23] perf: always use the same prototype Iterator (#2743) * perf: always use the same prototype Iterator * add iteratorMixin * rename state to object * fixup * perf: use class make faster * fixup * fixup * fixup * fixup * fixup * add test * fix test name * simplify --- lib/fetch/formdata.js | 62 +-------------- lib/fetch/headers.js | 62 +-------------- lib/fetch/util.js | 171 ++++++++++++++++++++++++++++++++---------- lib/fetch/webidl.js | 2 +- test/fetch/headers.js | 15 ++++ 5 files changed, 152 insertions(+), 160 deletions(-) diff --git a/lib/fetch/formdata.js b/lib/fetch/formdata.js index add64aa9226..80df2b8f399 100644 --- a/lib/fetch/formdata.js +++ b/lib/fetch/formdata.js @@ -1,6 +1,6 @@ 'use strict' -const { isBlobLike, makeIterator } = require('./util') +const { isBlobLike, iteratorMixin } = require('./util') const { kState } = require('./symbols') const { kEnumerableProperty } = require('../core/util') const { File: UndiciFile, FileLike, isFileLike } = require('./file') @@ -154,62 +154,9 @@ class FormData { this[kState].push(entry) } } - - entries () { - webidl.brandCheck(this, FormData) - - return makeIterator( - () => this[kState], - 'FormData', - 'key+value', - 'name', 'value' - ) - } - - keys () { - webidl.brandCheck(this, FormData) - - return makeIterator( - () => this[kState], - 'FormData', - 'key', - 'name', 'value' - ) - } - - values () { - webidl.brandCheck(this, FormData) - - return makeIterator( - () => this[kState], - 'FormData', - 'value', - 'name', 'value' - ) - } - - /** - * @param {(value: string, key: string, self: FormData) => void} callbackFn - * @param {unknown} thisArg - */ - forEach (callbackFn, thisArg = globalThis) { - webidl.brandCheck(this, FormData) - - webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.forEach' }) - - if (typeof callbackFn !== 'function') { - throw new TypeError( - "Failed to execute 'forEach' on 'FormData': parameter 1 is not of type 'Function'." - ) - } - - for (const [key, value] of this) { - callbackFn.call(thisArg, value, key, this) - } - } } -FormData.prototype[Symbol.iterator] = FormData.prototype.entries +iteratorMixin('FormData', FormData, kState, 'name', 'value') Object.defineProperties(FormData.prototype, { append: kEnumerableProperty, @@ -218,11 +165,6 @@ Object.defineProperties(FormData.prototype, { getAll: kEnumerableProperty, has: kEnumerableProperty, set: kEnumerableProperty, - entries: kEnumerableProperty, - keys: kEnumerableProperty, - values: kEnumerableProperty, - forEach: kEnumerableProperty, - [Symbol.iterator]: { enumerable: false }, [Symbol.toStringTag]: { value: 'FormData', configurable: true diff --git a/lib/fetch/headers.js b/lib/fetch/headers.js index 504942edc6e..43860c5d98a 100644 --- a/lib/fetch/headers.js +++ b/lib/fetch/headers.js @@ -6,7 +6,7 @@ const { kHeadersList, kConstruct } = require('../core/symbols') const { kGuard } = require('./symbols') const { kEnumerableProperty } = require('../core/util') const { - makeIterator, + iteratorMixin, isValidHeaderName, isValidHeaderValue } = require('./util') @@ -504,59 +504,6 @@ class Headers { return headers } - keys () { - webidl.brandCheck(this, Headers) - - return makeIterator( - () => this[kHeadersSortedMap], - 'Headers', - 'key', - 0, 1 - ) - } - - values () { - webidl.brandCheck(this, Headers) - - return makeIterator( - () => this[kHeadersSortedMap], - 'Headers', - 'value', - 0, 1 - ) - } - - entries () { - webidl.brandCheck(this, Headers) - - return makeIterator( - () => this[kHeadersSortedMap], - 'Headers', - 'key+value', - 0, 1 - ) - } - - /** - * @param {(value: string, key: string, self: Headers) => void} callbackFn - * @param {unknown} thisArg - */ - forEach (callbackFn, thisArg = globalThis) { - webidl.brandCheck(this, Headers) - - webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.forEach' }) - - if (typeof callbackFn !== 'function') { - throw new TypeError( - "Failed to execute 'forEach' on 'Headers': parameter 1 is not of type 'Function'." - ) - } - - for (const [key, value] of this) { - callbackFn.call(thisArg, value, key, this) - } - } - [Symbol.for('nodejs.util.inspect.custom')] () { webidl.brandCheck(this, Headers) @@ -564,7 +511,7 @@ class Headers { } } -Headers.prototype[Symbol.iterator] = Headers.prototype.entries +iteratorMixin('Headers', Headers, kHeadersSortedMap, 0, 1) Object.defineProperties(Headers.prototype, { append: kEnumerableProperty, @@ -573,11 +520,6 @@ Object.defineProperties(Headers.prototype, { has: kEnumerableProperty, set: kEnumerableProperty, getSetCookie: kEnumerableProperty, - keys: kEnumerableProperty, - values: kEnumerableProperty, - entries: kEnumerableProperty, - forEach: kEnumerableProperty, - [Symbol.iterator]: { enumerable: false }, [Symbol.toStringTag]: { value: 'Headers', configurable: true diff --git a/lib/fetch/util.js b/lib/fetch/util.js index c5a6b46b170..82e96ec9acd 100644 --- a/lib/fetch/util.js +++ b/lib/fetch/util.js @@ -6,9 +6,10 @@ const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet const { getGlobalOrigin } = require('./global') const { collectASequenceOfCodePoints, collectAnHTTPQuotedString, removeChars, parseMIMEType } = require('./dataURL') const { performance } = require('node:perf_hooks') -const { isBlobLike, toUSVString, ReadableStreamFrom, isValidHTTPToken } = require('../core/util') +const { isBlobLike, ReadableStreamFrom, isValidHTTPToken } = require('../core/util') const assert = require('node:assert') const { isUint8Array } = require('util/types') +const { webidl } = require('./webidl') // https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable /** @type {import('crypto')|undefined} */ @@ -739,35 +740,40 @@ const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbo /** * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object - * @param {() => unknown} iterator * @param {string} name name of the instance - * @param {'key'|'value'|'key+value'} kind + * @param {symbol} kInternalIterator * @param {string | number} [keyIndex] * @param {string | number} [valueIndex] */ -function makeIterator (iterator, name, kind, keyIndex = 0, valueIndex = 1) { - const object = { - index: 0, - kind, - target: iterator - } - // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%. - const iteratorObject = Object.create(esIteratorPrototype) +function createIterator (name, kInternalIterator, keyIndex = 0, valueIndex = 1) { + class FastIterableIterator { + /** @type {any} */ + #target + /** @type {'key' | 'value' | 'key+value'} */ + #kind + /** @type {number} */ + #index + + /** + * @see https://webidl.spec.whatwg.org/#dfn-default-iterator-object + * @param {unknown} target + * @param {'key' | 'value' | 'key+value'} kind + */ + constructor (target, kind) { + this.#target = target + this.#kind = kind + this.#index = 0 + } - Object.defineProperty(iteratorObject, 'next', { - value: function next () { + next () { // 1. Let interface be the interface for which the iterator prototype object exists. - // 2. Let thisValue be the this value. - // 3. Let object be ? ToObject(thisValue). - // 4. If object is a platform object, then perform a security // check, passing: - // 5. If object is not a default iterator object for interface, // then throw a TypeError. - if (Object.getPrototypeOf(this) !== iteratorObject) { + if (typeof this !== 'object' || this === null || !(#target in this)) { throw new TypeError( `'next' called on an object that does not implement interface ${name} Iterator.` ) @@ -776,8 +782,8 @@ function makeIterator (iterator, name, kind, keyIndex = 0, valueIndex = 1) { // 6. Let index be object’s index. // 7. Let kind be object’s kind. // 8. Let values be object’s target's value pairs to iterate over. - const { index, kind, target } = object - const values = target() + const index = this.#index + const values = this.#target[kInternalIterator] // 9. Let len be the length of values. const len = values.length @@ -785,17 +791,25 @@ function makeIterator (iterator, name, kind, keyIndex = 0, valueIndex = 1) { // 10. If index is greater than or equal to len, then return // CreateIterResultObject(undefined, true). if (index >= len) { - return { value: undefined, done: true } + return { + value: undefined, + done: true + } } + // 11. Let pair be the entry in values at index index. const { [keyIndex]: key, [valueIndex]: value } = values[index] + // 12. Set object’s index to index + 1. - object.index = index + 1 + this.#index = index + 1 + // 13. Return the iterator result for pair and kind. + // https://webidl.spec.whatwg.org/#iterator-result + // 1. Let result be a value determined by the value of kind: let result - switch (kind) { + switch (this.#kind) { case 'key': // 1. Let idlKey be pair’s key. // 2. Let key be the result of converting idlKey to an @@ -824,29 +838,108 @@ function makeIterator (iterator, name, kind, keyIndex = 0, valueIndex = 1) { result = [key, value] break } + // 2. Return CreateIterResultObject(result, false). return { value: result, done: false } + } + } + + // https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + // @ts-ignore + delete FastIterableIterator.prototype.constructor + + Object.setPrototypeOf(FastIterableIterator.prototype, esIteratorPrototype) + + Object.defineProperties(FastIterableIterator.prototype, { + [Symbol.toStringTag]: { + writable: false, + enumerable: false, + configurable: true, + value: `${name} Iterator` }, - writable: true, - enumerable: true, - configurable: true + next: { writable: true, enumerable: true, configurable: true } }) - // The class string of an iterator prototype object for a given interface is the - // result of concatenating the identifier of the interface and the string " Iterator". - Object.defineProperty(iteratorObject, Symbol.toStringTag, { - value: `${name} Iterator`, - writable: false, - enumerable: false, - configurable: true - }) + /** + * @param {unknown} target + * @param {'key' | 'value' | 'key+value'} kind + * @returns {IterableIterator} + */ + return function (target, kind) { + return new FastIterableIterator(target, kind) + } +} - // esIteratorPrototype needs to be the prototype of iteratorObject - // which is the prototype of an empty object. Yes, it's confusing. - return Object.create(iteratorObject) +/** + * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + * @param {string} name name of the instance + * @param {any} object class + * @param {symbol} kInternalIterator + * @param {string | number} [keyIndex] + * @param {string | number} [valueIndex] + */ +function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueIndex = 1) { + const makeIterator = createIterator(name, kInternalIterator, keyIndex, valueIndex) + + const properties = { + keys: { + writable: true, + enumerable: true, + configurable: true, + value: function keys () { + webidl.brandCheck(this, object) + return makeIterator(this, 'key') + } + }, + values: { + writable: true, + enumerable: true, + configurable: true, + value: function values () { + webidl.brandCheck(this, object) + return makeIterator(this, 'value') + } + }, + entries: { + writable: true, + enumerable: true, + configurable: true, + value: function entries () { + webidl.brandCheck(this, object) + return makeIterator(this, 'key+value') + } + }, + forEach: { + writable: true, + enumerable: true, + configurable: true, + value: function forEach (callbackfn, thisArg = globalThis) { + webidl.brandCheck(this, object) + webidl.argumentLengthCheck(arguments, 1, { header: `${name}.forEach` }) + if (typeof callbackfn !== 'function') { + throw new TypeError( + `Failed to execute 'forEach' on '${name}': parameter 1 is not of type 'Function'.` + ) + } + for (const { 0: key, 1: value } of makeIterator(this, 'key+value')) { + callbackfn.call(thisArg, value, key, this) + } + } + } + } + + return Object.defineProperties(object.prototype, { + ...properties, + [Symbol.iterator]: { + writable: true, + enumerable: false, + configurable: true, + value: properties.entries.value + } + }) } /** @@ -1340,7 +1433,6 @@ module.exports = { isCancelled, createDeferredPromise, ReadableStreamFrom, - toUSVString, tryUpgradeRequestToAPotentiallyTrustworthyURL, clampAndCoarsenConnectionTimingInfo, coarsenedSharedCurrentTime, @@ -1365,7 +1457,8 @@ module.exports = { sameOrigin, normalizeMethod, serializeJavascriptValueToJSONString, - makeIterator, + iteratorMixin, + createIterator, isValidHeaderName, isValidHeaderValue, isErrorLike, diff --git a/lib/fetch/webidl.js b/lib/fetch/webidl.js index d639b8b7668..a93a25505fc 100644 --- a/lib/fetch/webidl.js +++ b/lib/fetch/webidl.js @@ -1,7 +1,7 @@ 'use strict' const { types } = require('node:util') -const { toUSVString } = require('./util') +const { toUSVString } = require('../core/util') /** @type {import('../../types/webidl').Webidl} */ const webidl = {} diff --git a/test/fetch/headers.js b/test/fetch/headers.js index b61d8b612d2..fcdf4b7a820 100644 --- a/test/fetch/headers.js +++ b/test/fetch/headers.js @@ -472,6 +472,21 @@ test('Headers as Iterable', async (t) => { deepStrictEqual([...headers], expected) }) + + await t.test('always use the same prototype Iterator', (t) => { + const HeadersIteratorNext = Function.call.bind(new Headers()[Symbol.iterator]().next) + + const init = [ + ['a', '1'], + ['b', '2'] + ] + + const headers = new Headers(init) + const iterator = headers[Symbol.iterator]() + assert.deepStrictEqual(HeadersIteratorNext(iterator), { value: init[0], done: false }) + assert.deepStrictEqual(HeadersIteratorNext(iterator), { value: init[1], done: false }) + assert.deepStrictEqual(HeadersIteratorNext(iterator), { value: undefined, done: true }) + }) }) test('arg validation', () => { From 5f02182d5b962d8793f9a324bc0ab1036b354340 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Tue, 13 Feb 2024 10:31:15 +0100 Subject: [PATCH 21/23] chore: migrate a batch of tests to node test runner no. 9, remove tap (#2746) * chore: migrate a batch of tests to node test runner * add connect-timeout.js * remove tap --- .taprc | 7 - package.json | 7 +- test/client-request.js | 411 ++++++++------- test/client.js | 1033 ++++++++++++++++++++----------------- test/close-and-destroy.js | 181 ++++--- test/connect-timeout.js | 27 +- test/gc.js | 41 +- test/issue-2590.js | 10 +- test/pool.js | 470 +++++++++-------- test/request-timeout.js | 350 +++++++------ test/tls-session-reuse.js | 44 +- 11 files changed, 1439 insertions(+), 1142 deletions(-) delete mode 100644 .taprc diff --git a/.taprc b/.taprc deleted file mode 100644 index 61f70513a70..00000000000 --- a/.taprc +++ /dev/null @@ -1,7 +0,0 @@ -ts: false -jsx: false -flow: false -coverage: false -expose-gc: true -timeout: 60 -check-coverage: false diff --git a/package.json b/package.json index 92227f2799e..d03da7e116d 100644 --- a/package.json +++ b/package.json @@ -76,15 +76,15 @@ "build:wasm": "node build/wasm.js --docker", "lint": "standard | snazzy", "lint:fix": "standard --fix | snazzy", - "test": "node scripts/generate-pem && npm run test:tap && npm run test:node-fetch && npm run test:fetch && npm run test:cookies && npm run test:eventsource && npm run test:wpt && npm run test:websocket && npm run test:jest && npm run test:typescript && npm run test:node-test", + "test": "node scripts/generate-pem && npm run test:unit && npm run test:node-fetch && npm run test:fetch && npm run test:cookies && npm run test:eventsource && npm run test:wpt && npm run test:websocket && npm run test:jest && npm run test:typescript && npm run test:node-test", "test:cookies": "borp --coverage -p \"test/cookie/*.js\"", "test:node-fetch": "borp --coverage -p \"test/node-fetch/**/*.js\"", "test:eventsource": "npm run build:node && borp --expose-gc --coverage -p \"test/eventsource/*.js\"", "test:fetch": "npm run build:node && borp --expose-gc --coverage -p \"test/fetch/*.js\" && borp --coverage -p \"test/webidl/*.js\"", "test:jest": "jest", - "test:tap": "tap test/*.js", + "test:unit": "borp --expose-gc -p \"test/*.js\"", "test:node-test": "borp --coverage -p \"test/node-test/**/*.js\"", - "test:tdd": "tap test/*.js --coverage -w", + "test:tdd": "borp --coverage --expose-gc -p \"test/*.js\"", "test:tdd:node-test": "borp -p \"test/node-test/**/*.js\" -w", "test:typescript": "tsd && tsc --skipLibCheck test/imports/undici-import.ts", "test:websocket": "borp --coverage -p \"test/websocket/*.js\"", @@ -130,7 +130,6 @@ "snazzy": "^9.0.0", "standard": "^17.0.0", "superagent": "^8.1.2", - "tap": "^16.1.0", "tsd": "^0.30.1", "typescript": "^5.0.2", "wait-on": "^7.0.1", diff --git a/test/client-request.js b/test/client-request.js index cafcd39989b..2b73d3b01d0 100644 --- a/test/client-request.js +++ b/test/client-request.js @@ -2,7 +2,8 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, errors } = require('..') const { createServer } = require('node:http') const EE = require('node:events') @@ -13,51 +14,53 @@ const { promisify } = require('node:util') const { NotSupportedError } = require('../lib/core/errors') const { parseFormDataString } = require('./utils/formdata') -test('request dump', (t) => { - t.plan(3) +test('request dump', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) let dumped = false client.on('disconnect', () => { - t.equal(dumped, true) + t.strictEqual(dumped, true) }) client.request({ path: '/', method: 'GET' }, (err, { body }) => { - t.error(err) + t.ifError(err) body.dump().then(() => { dumped = true t.ok(true, 'pass') }) }) }) + + await t.completed }) -test('request dump with abort signal', (t) => { - t.plan(2) +test('request dump with abort signal', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.write('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, { body }) => { - t.error(err) + t.ifError(err) let ac if (!global.AbortController) { const { AbortController } = require('abort-controller') @@ -66,50 +69,54 @@ test('request dump with abort signal', (t) => { ac = new AbortController() } body.dump({ signal: ac.signal }).catch((err) => { - t.equal(err.name, 'AbortError') + t.strictEqual(err.name, 'AbortError') server.close() }) ac.abort() }) }) + + await t.completed }) -test('request hwm', (t) => { - t.plan(2) +test('request hwm', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.write('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET', highWaterMark: 1000 }, (err, { body }) => { - t.error(err) - t.same(body.readableHighWaterMark, 1000) + t.ifError(err) + t.deepStrictEqual(body.readableHighWaterMark, 1000) body.dump() }) }) + + await t.completed }) -test('request abort before headers', (t) => { - t.plan(6) +test('request abort before headers', async (t) => { + t = tspl(t, { plan: 6 }) const signal = new EE() const server = createServer((req, res) => { res.end('hello') signal.emit('abort') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client[kConnect](() => { client.request({ @@ -118,9 +125,9 @@ test('request abort before headers', (t) => { signal }, (err) => { t.ok(err instanceof errors.RequestAbortedError) - t.equal(signal.listenerCount('abort'), 0) + t.strictEqual(signal.listenerCount('abort'), 0) }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) client.request({ path: '/', @@ -128,23 +135,25 @@ test('request abort before headers', (t) => { signal }, (err) => { t.ok(err instanceof errors.RequestAbortedError) - t.equal(signal.listenerCount('abort'), 0) + t.strictEqual(signal.listenerCount('abort'), 0) }) - t.equal(signal.listenerCount('abort'), 2) + t.strictEqual(signal.listenerCount('abort'), 2) }) }) + + await t.completed }) -test('request body destroyed on invalid callback', (t) => { - t.plan(1) +test('request body destroyed on invalid callback', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const body = new Readable({ read () {} @@ -156,24 +165,26 @@ test('request body destroyed on invalid callback', (t) => { body }, null) } catch (err) { - t.equal(body.destroyed, true) + t.strictEqual(body.destroyed, true) } }) + + await t.completed }) -test('trailers', (t) => { - t.plan(1) +test('trailers', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.writeHead(200, { Trailer: 'Content-MD5' }) res.addTrailers({ 'Content-MD5': 'test' }) res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const { body, trailers } = await client.request({ path: '/', @@ -183,13 +194,15 @@ test('trailers', (t) => { body .on('data', () => t.fail()) .on('end', () => { - t.strictSame(trailers, { 'content-md5': 'test' }) + t.deepStrictEqual(trailers, { 'content-md5': 'test' }) }) }) + + await t.completed }) -test('destroy socket abruptly', { skip: true }, async (t) => { - t.plan(2) +test('destroy socket abruptly', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer((socket) => { const lines = [ @@ -205,18 +218,18 @@ test('destroy socket abruptly', { skip: true }, async (t) => { // therefore we delay it to the next event loop run. setImmediate(socket.destroy.bind(socket)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const { statusCode, body } = await client.request({ path: '/', method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) body.setEncoding('utf8') @@ -226,11 +239,11 @@ test('destroy socket abruptly', { skip: true }, async (t) => { actual += chunk } - t.equal(actual, 'the body') + t.strictEqual(actual, 'the body') }) -test('destroy socket abruptly with keep-alive', { skip: true }, async (t) => { - t.plan(2) +test('destroy socket abruptly with keep-alive', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer((socket) => { const lines = [ @@ -247,18 +260,18 @@ test('destroy socket abruptly with keep-alive', { skip: true }, async (t) => { // therefore we delay it to the next event loop run. setImmediate(socket.destroy.bind(socket)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const { statusCode, body } = await client.request({ path: '/', method: 'GET' }) - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) body.setEncoding('utf8') @@ -274,81 +287,87 @@ test('destroy socket abruptly with keep-alive', { skip: true }, async (t) => { } }) -test('request json', (t) => { - t.plan(1) +test('request json', async (t) => { + t = tspl(t, { plan: 1 }) const obj = { asd: true } const server = createServer((req, res) => { res.end(JSON.stringify(obj)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', method: 'GET' }) - t.strictSame(obj, await body.json()) + t.deepStrictEqual(obj, await body.json()) }) + + await t.completed }) -test('request long multibyte json', (t) => { - t.plan(1) +test('request long multibyte json', async (t) => { + t = tspl(t, { plan: 1 }) const obj = { asd: 'あ'.repeat(100000) } const server = createServer((req, res) => { res.end(JSON.stringify(obj)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', method: 'GET' }) - t.strictSame(obj, await body.json()) + t.deepStrictEqual(obj, await body.json()) }) + + await t.completed }) -test('request text', (t) => { - t.plan(1) +test('request text', async (t) => { + t = tspl(t, { plan: 1 }) const obj = { asd: true } const server = createServer((req, res) => { res.end(JSON.stringify(obj)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', method: 'GET' }) - t.strictSame(JSON.stringify(obj), await body.text()) + t.strictEqual(JSON.stringify(obj), await body.text()) }) + + await t.completed }) -test('empty host header', (t) => { - t.plan(3) +test('empty host header', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.end(req.headers.host) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const serverAddress = `localhost:${server.address().port}` const client = new Client(`http://${serverAddress}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const getWithHost = async (host, wanted) => { const { body } = await client.request({ @@ -356,49 +375,53 @@ test('empty host header', (t) => { method: 'GET', headers: { host } }) - t.strictSame(await body.text(), wanted) + t.strictEqual(await body.text(), wanted) } await getWithHost('test', 'test') await getWithHost(undefined, serverAddress) await getWithHost('', '') }) + + await t.completed }) -test('request long multibyte text', (t) => { - t.plan(1) +test('request long multibyte text', async (t) => { + t = tspl(t, { plan: 1 }) const obj = { asd: 'あ'.repeat(100000) } const server = createServer((req, res) => { res.end(JSON.stringify(obj)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', method: 'GET' }) - t.strictSame(JSON.stringify(obj), await body.text()) + t.strictEqual(JSON.stringify(obj), await body.text()) }) + + await t.completed }) -test('request blob', (t) => { - t.plan(2) +test('request blob', async (t) => { + t = tspl(t, { plan: 2 }) const obj = { asd: true } const server = createServer((req, res) => { res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify(obj)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -406,23 +429,25 @@ test('request blob', (t) => { }) const blob = await body.blob() - t.strictSame(obj, JSON.parse(await blob.text())) - t.equal(blob.type, 'application/json') + t.deepStrictEqual(obj, JSON.parse(await blob.text())) + t.strictEqual(blob.type, 'application/json') }) + + await t.completed }) -test('request arrayBuffer', (t) => { - t.plan(2) +test('request arrayBuffer', async (t) => { + t = tspl(t, { plan: 2 }) const obj = { asd: true } const server = createServer((req, res) => { res.end(JSON.stringify(obj)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -430,23 +455,25 @@ test('request arrayBuffer', (t) => { }) const ab = await body.arrayBuffer() - t.strictSame(Buffer.from(JSON.stringify(obj)), Buffer.from(ab)) + t.deepStrictEqual(Buffer.from(JSON.stringify(obj)), Buffer.from(ab)) t.ok(ab instanceof ArrayBuffer) }) + + await t.completed }) -test('request body', (t) => { - t.plan(1) +test('request body', async (t) => { + t = tspl(t, { plan: 1 }) const obj = { asd: true } const server = createServer((req, res) => { res.end(JSON.stringify(obj)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -457,26 +484,28 @@ test('request body', (t) => { for await (const chunk of body.body) { x += Buffer.from(chunk) } - t.strictSame(JSON.stringify(obj), x) + t.strictEqual(JSON.stringify(obj), x) }) + + await t.completed }) -test('request post body no missing data', (t) => { - t.plan(2) +test('request post body no missing data', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer(async (req, res) => { let ret = '' for await (const chunk of req) { ret += chunk } - t.equal(ret, 'asd') + t.strictEqual(ret, 'asd') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -492,24 +521,26 @@ test('request post body no missing data', (t) => { await body.text() t.ok(true, 'pass') }) + + await t.completed }) -test('request post body no extra data handler', (t) => { - t.plan(3) +test('request post body no extra data handler', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer(async (req, res) => { let ret = '' for await (const chunk of req) { ret += chunk } - t.equal(ret, 'asd') + t.strictEqual(ret, 'asd') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const reqBody = new Readable({ read () { @@ -518,7 +549,7 @@ test('request post body no extra data handler', (t) => { } }) process.nextTick(() => { - t.equal(reqBody.listenerCount('data'), 0) + t.strictEqual(reqBody.listenerCount('data'), 0) }) const { body } = await client.request({ path: '/', @@ -529,46 +560,50 @@ test('request post body no extra data handler', (t) => { await body.text() t.ok(true, 'pass') }) + + await t.completed }) -test('request with onInfo callback', (t) => { - t.plan(3) +test('request with onInfo callback', async (t) => { + t = tspl(t, { plan: 3 }) const infos = [] const server = createServer((req, res) => { res.writeProcessing() res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify({ foo: 'bar' })) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) await client.request({ path: '/', method: 'GET', onInfo: (x) => { infos.push(x) } }) - t.equal(infos.length, 1) - t.equal(infos[0].statusCode, 102) + t.strictEqual(infos.length, 1) + t.strictEqual(infos[0].statusCode, 102) t.ok(true, 'pass') }) + + await t.completed }) -test('request with onInfo callback but socket is destroyed before end of response', (t) => { - t.plan(5) +test('request with onInfo callback but socket is destroyed before end of response', async (t) => { + t = tspl(t, { plan: 5 }) const infos = [] let response const server = createServer((req, res) => { response = res res.writeProcessing() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) try { await client.request({ path: '/', @@ -578,19 +613,21 @@ test('request with onInfo callback but socket is destroyed before end of respons response.destroy() } }) - t.error() + t.fail() } catch (e) { t.ok(e) - t.equal(e.message, 'other side closed') + t.strictEqual(e.message, 'other side closed') } - t.equal(infos.length, 1) - t.equal(infos[0].statusCode, 102) + t.strictEqual(infos.length, 1) + t.strictEqual(infos[0].statusCode, 102) t.ok(true, 'pass') }) + + await t.completed }) test('request onInfo callback headers parsing', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const infos = [] const server = net.createServer((socket) => { @@ -606,12 +643,12 @@ test('request onInfo callback headers parsing', async (t) => { ] socket.end(lines.join('\r\n')) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const { body } = await client.request({ path: '/', @@ -619,14 +656,14 @@ test('request onInfo callback headers parsing', async (t) => { onInfo: (x) => { infos.push(x) } }) await body.dump() - t.equal(infos.length, 1) - t.equal(infos[0].statusCode, 103) - t.same(infos[0].headers, { link: '; rel=preload; as=style' }) + t.strictEqual(infos.length, 1) + t.strictEqual(infos[0].statusCode, 103) + t.deepStrictEqual(infos[0].headers, { link: '; rel=preload; as=style' }) t.ok(true, 'pass') }) test('request raw responseHeaders', async (t) => { - t.plan(4) + t = tspl(t, { plan: 4 }) const infos = [] const server = net.createServer((socket) => { @@ -642,12 +679,12 @@ test('request raw responseHeaders', async (t) => { ] socket.end(lines.join('\r\n')) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const { body, headers } = await client.request({ path: '/', @@ -656,24 +693,24 @@ test('request raw responseHeaders', async (t) => { onInfo: (x) => { infos.push(x) } }) await body.dump() - t.equal(infos.length, 1) - t.same(infos[0].headers, ['Link', '; rel=preload; as=style']) - t.same(headers, ['Date', 'Sat, 09 Oct 2010 14:28:02 GMT', 'Connection', 'close']) + t.strictEqual(infos.length, 1) + t.deepStrictEqual(infos[0].headers, ['Link', '; rel=preload; as=style']) + t.deepStrictEqual(headers, ['Date', 'Sat, 09 Oct 2010 14:28:02 GMT', 'Connection', 'close']) t.ok(true, 'pass') }) -test('request formData', (t) => { - t.plan(1) +test('request formData', async (t) => { + t = tspl(t, { plan: 1 }) const obj = { asd: true } const server = createServer((req, res) => { res.end(JSON.stringify(obj)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -687,20 +724,22 @@ test('request formData', (t) => { t.ok(error instanceof NotSupportedError) } }) + + await t.completed }) -test('request text2', (t) => { - t.plan(2) +test('request text2', async (t) => { + t = tspl(t, { plan: 2 }) const obj = { asd: true } const server = createServer((req, res) => { res.end(JSON.stringify(obj)) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -711,13 +750,15 @@ test('request text2', (t) => { body.on('data', chunk => { ret += chunk }).on('end', () => { - t.equal(JSON.stringify(obj), ret) + t.strictEqual(JSON.stringify(obj), ret) }) - t.strictSame(JSON.stringify(obj), await p) + t.strictEqual(JSON.stringify(obj), await p) }) + + await t.completed }) -test('request with FormData body', (t) => { +test('request with FormData body', async (t) => { const { FormData } = require('../') const { Blob } = require('node:buffer') @@ -741,10 +782,10 @@ test('request with FormData body', (t) => { contentType ) - t.same(fields[0], { key: 'key', value: 'value' }) + t.deepStrictEqual(fields[0], { key: 'key', value: 'value' }) t.ok(fileMap.has('file')) - t.equal(fileMap.get('file').data.toString(), 'Hello, world!') - t.same(fileMap.get('file').info, { + t.strictEqual(fileMap.get('file').data.toString(), 'Hello, world!') + t.deepStrictEqual(fileMap.get('file').info, { filename: 'hello_world.txt', encoding: '7bit', mimeType: 'application/octet-stream' @@ -752,11 +793,11 @@ test('request with FormData body', (t) => { return res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) await client.request({ path: '/', @@ -766,10 +807,12 @@ test('request with FormData body', (t) => { t.end() }) + + await t.completed }) -test('request post body Buffer from string', (t) => { - t.plan(2) +test('request post body Buffer from string', async (t) => { + t = tspl(t, { plan: 2 }) const requestBody = Buffer.from('abcdefghijklmnopqrstuvwxyz') const server = createServer(async (req, res) => { @@ -777,14 +820,14 @@ test('request post body Buffer from string', (t) => { for await (const chunk of req) { ret += chunk } - t.equal(ret, 'abcdefghijklmnopqrstuvwxyz') + t.strictEqual(ret, 'abcdefghijklmnopqrstuvwxyz') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -795,10 +838,12 @@ test('request post body Buffer from string', (t) => { await body.text() t.ok(true, 'pass') }) + + await t.completed }) -test('request post body Buffer from buffer', (t) => { - t.plan(2) +test('request post body Buffer from buffer', async (t) => { + t = tspl(t, { plan: 2 }) const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') const requestBody = Buffer.from(fullBuffer.buffer, 8, 16) @@ -807,14 +852,14 @@ test('request post body Buffer from buffer', (t) => { for await (const chunk of req) { ret += chunk } - t.equal(ret, 'ijklmnopqrstuvwx') + t.strictEqual(ret, 'ijklmnopqrstuvwx') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -825,10 +870,12 @@ test('request post body Buffer from buffer', (t) => { await body.text() t.ok(true, 'pass') }) + + await t.completed }) -test('request post body Uint8Array', (t) => { - t.plan(2) +test('request post body Uint8Array', async (t) => { + t = tspl(t, { plan: 2 }) const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') const requestBody = new Uint8Array(fullBuffer.buffer, 8, 16) @@ -837,14 +884,14 @@ test('request post body Uint8Array', (t) => { for await (const chunk of req) { ret += chunk } - t.equal(ret, 'ijklmnopqrstuvwx') + t.strictEqual(ret, 'ijklmnopqrstuvwx') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -855,10 +902,12 @@ test('request post body Uint8Array', (t) => { await body.text() t.ok(true, 'pass') }) + + await t.completed }) -test('request post body Uint32Array', (t) => { - t.plan(2) +test('request post body Uint32Array', async (t) => { + t = tspl(t, { plan: 2 }) const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') const requestBody = new Uint32Array(fullBuffer.buffer, 8, 4) @@ -867,14 +916,14 @@ test('request post body Uint32Array', (t) => { for await (const chunk of req) { ret += chunk } - t.equal(ret, 'ijklmnopqrstuvwx') + t.strictEqual(ret, 'ijklmnopqrstuvwx') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -885,10 +934,12 @@ test('request post body Uint32Array', (t) => { await body.text() t.ok(true, 'pass') }) + + await t.completed }) -test('request post body Float64Array', (t) => { - t.plan(2) +test('request post body Float64Array', async (t) => { + t = tspl(t, { plan: 2 }) const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') const requestBody = new Float64Array(fullBuffer.buffer, 8, 2) @@ -897,14 +948,14 @@ test('request post body Float64Array', (t) => { for await (const chunk of req) { ret += chunk } - t.equal(ret, 'ijklmnopqrstuvwx') + t.strictEqual(ret, 'ijklmnopqrstuvwx') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -915,10 +966,12 @@ test('request post body Float64Array', (t) => { await body.text() t.ok(true, 'pass') }) + + await t.completed }) -test('request post body BigUint64Array', (t) => { - t.plan(2) +test('request post body BigUint64Array', async (t) => { + t = tspl(t, { plan: 2 }) const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') const requestBody = new BigUint64Array(fullBuffer.buffer, 8, 2) @@ -927,14 +980,14 @@ test('request post body BigUint64Array', (t) => { for await (const chunk of req) { ret += chunk } - t.equal(ret, 'ijklmnopqrstuvwx') + t.strictEqual(ret, 'ijklmnopqrstuvwx') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -945,10 +998,12 @@ test('request post body BigUint64Array', (t) => { await body.text() t.ok(true, 'pass') }) + + await t.completed }) -test('request post body DataView', (t) => { - t.plan(2) +test('request post body DataView', async (t) => { + t = tspl(t, { plan: 2 }) const fullBuffer = new TextEncoder().encode('abcdefghijklmnopqrstuvwxyz') const requestBody = new DataView(fullBuffer.buffer, 8, 16) @@ -957,14 +1012,14 @@ test('request post body DataView', (t) => { for await (const chunk of req) { ret += chunk } - t.equal(ret, 'ijklmnopqrstuvwx') + t.strictEqual(ret, 'ijklmnopqrstuvwx') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { body } = await client.request({ path: '/', @@ -975,4 +1030,6 @@ test('request post body DataView', (t) => { await body.text() t.ok(true, 'pass') }) + + await t.completed }) diff --git a/test/client.js b/test/client.js index 7c3c8d0fcb3..155023f936e 100644 --- a/test/client.js +++ b/test/client.js @@ -1,9 +1,10 @@ 'use strict' +const { tspl } = require('@matteo.collina/tspl') const { readFileSync, createReadStream } = require('node:fs') const { createServer } = require('node:http') const { Readable } = require('node:stream') -const { test } = require('tap') +const { test, after } = require('node:test') const { Client, errors } = require('..') const { kSocket } = require('../lib/core/symbols') const { wrapWithAsyncIterable } = require('./utils/async-iterators') @@ -18,20 +19,20 @@ const hasIPv6 = (() => { ) })() -test('basic get', (t) => { - t.plan(24) +test('basic get', async (t) => { + t = tspl(t, { plan: 24 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) - t.equal(undefined, req.headers.foo) - t.equal('bar', req.headers.bar) - t.equal(undefined, req.headers['content-length']) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual(undefined, req.headers.foo) + t.strictEqual('bar', req.headers.bar) + t.strictEqual(undefined, req.headers['content-length']) res.setHeader('Content-Type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const reqHeaders = { foo: undefined, @@ -42,9 +43,9 @@ test('basic get', (t) => { const client = new Client(`http://localhost:${server.address().port}`, { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) - t.equal(client[kUrl].origin, `http://localhost:${server.address().port}`) + t.strictEqual(client[kUrl].origin, `http://localhost:${server.address().port}`) const signal = new EE() client.request({ @@ -53,56 +54,58 @@ test('basic get', (t) => { method: 'GET', headers: reqHeaders }, (err, data) => { - t.error(err) + t.ifError(err) const { statusCode, headers, body } = data - t.equal(statusCode, 200) - t.equal(signal.listenerCount('abort'), 1) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(signal.listenerCount('abort'), 1) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal(signal.listenerCount('abort'), 0) - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual(signal.listenerCount('abort'), 0) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) client.request({ path: '/', method: 'GET', headers: reqHeaders }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic get with custom request.reset=true', (t) => { - t.plan(26) +test('basic get with custom request.reset=true', async (t) => { + t = tspl(t, { plan: 26 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) - t.equal(req.headers.connection, 'close') - t.equal(undefined, req.headers.foo) - t.equal('bar', req.headers.bar) - t.equal(undefined, req.headers['content-length']) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual(req.headers.connection, 'close') + t.strictEqual(undefined, req.headers.foo) + t.strictEqual('bar', req.headers.bar) + t.strictEqual(undefined, req.headers['content-length']) res.setHeader('Content-Type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const reqHeaders = { foo: undefined, @@ -111,9 +114,9 @@ test('basic get with custom request.reset=true', (t) => { server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, {}) - t.teardown(client.close.bind(client)) + after(() => client.close()) - t.equal(client[kUrl].origin, `http://localhost:${server.address().port}`) + t.strictEqual(client[kUrl].origin, `http://localhost:${server.address().port}`) const signal = new EE() client.request({ @@ -123,21 +126,21 @@ test('basic get with custom request.reset=true', (t) => { reset: true, headers: reqHeaders }, (err, data) => { - t.error(err) + t.ifError(err) const { statusCode, headers, body } = data - t.equal(statusCode, 200) - t.equal(signal.listenerCount('abort'), 1) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(signal.listenerCount('abort'), 1) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal(signal.listenerCount('abort'), 0) - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual(signal.listenerCount('abort'), 0) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) client.request({ path: '/', @@ -145,26 +148,28 @@ test('basic get with custom request.reset=true', (t) => { method: 'GET', headers: reqHeaders }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic get with query params', (t) => { - t.plan(4) +test('basic get with query params', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { const searchParamsObject = buildParams(req.url) - t.strictSame(searchParamsObject, { + t.deepStrictEqual(searchParamsObject, { bool: 'true', foo: '1', bar: 'bar', @@ -177,7 +182,7 @@ test('basic get with query params', (t) => { res.statusCode = 200 res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const query = { bool: true, @@ -193,7 +198,7 @@ test('basic get with query params', (t) => { const client = new Client(`http://localhost:${server.address().port}`, { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const signal = new EE() client.request({ @@ -202,21 +207,23 @@ test('basic get with query params', (t) => { method: 'GET', query }, (err, data) => { - t.error(err) + t.ifError(err) const { statusCode } = data - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) }) + + await t.completed }) -test('basic get with query params fails if url includes hashmark', (t) => { - t.plan(1) +test('basic get with query params fails if url includes hashmark', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { t.fail() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const query = { foo: 1, @@ -228,7 +235,7 @@ test('basic get with query params fails if url includes hashmark', (t) => { const client = new Client(`http://localhost:${server.address().port}`, { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const signal = new EE() client.request({ @@ -237,22 +244,24 @@ test('basic get with query params fails if url includes hashmark', (t) => { method: 'GET', query }, (err, data) => { - t.equal(err.message, 'Query params cannot be passed when url already contains "?" or "#".') + t.strictEqual(err.message, 'Query params cannot be passed when url already contains "?" or "#".') }) }) + + await t.completed }) -test('basic get with empty query params', (t) => { - t.plan(4) +test('basic get with empty query params', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { const searchParamsObject = buildParams(req.url) - t.strictSame(searchParamsObject, {}) + t.deepStrictEqual(searchParamsObject, {}) res.statusCode = 200 res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const query = {} @@ -260,7 +269,7 @@ test('basic get with empty query params', (t) => { const client = new Client(`http://localhost:${server.address().port}`, { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const signal = new EE() client.request({ @@ -269,21 +278,23 @@ test('basic get with empty query params', (t) => { method: 'GET', query }, (err, data) => { - t.error(err) + t.ifError(err) const { statusCode } = data - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) }) + + await t.completed }) -test('basic get with query params partially in path', (t) => { - t.plan(1) +test('basic get with query params partially in path', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { t.fail() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const query = { foo: 1 @@ -293,7 +304,7 @@ test('basic get with query params partially in path', (t) => { const client = new Client(`http://localhost:${server.address().port}`, { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const signal = new EE() client.request({ @@ -302,25 +313,27 @@ test('basic get with query params partially in path', (t) => { method: 'GET', query }, (err, data) => { - t.equal(err.message, 'Query params cannot be passed when url already contains "?" or "#".') + t.strictEqual(err.message, 'Query params cannot be passed when url already contains "?" or "#".') }) }) + + await t.completed }) -test('basic get returns 400 when configured to throw on errors (callback)', (t) => { - t.plan(7) +test('basic get returns 400 when configured to throw on errors (callback)', async (t) => { + t = tspl(t, { plan: 7 }) const server = createServer((req, res) => { res.statusCode = 400 res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const signal = new EE() client.request({ @@ -329,31 +342,33 @@ test('basic get returns 400 when configured to throw on errors (callback)', (t) method: 'GET', throwOnError: true }, (err) => { - t.equal(err.message, 'Response status code 400: Bad Request') - t.equal(err.status, 400) - t.equal(err.statusCode, 400) - t.equal(err.headers.connection, 'keep-alive') - t.equal(err.headers['content-length'], '5') - t.same(err.body, null) + t.strictEqual(err.message, 'Response status code 400: Bad Request') + t.strictEqual(err.status, 400) + t.strictEqual(err.statusCode, 400) + t.strictEqual(err.headers.connection, 'keep-alive') + t.strictEqual(err.headers['content-length'], '5') + t.strictEqual(err.body, undefined) }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) }) + + await t.completed }) -test('basic get returns 400 when configured to throw on errors and correctly handles malformed json (callback)', (t) => { - t.plan(6) +test('basic get returns 400 when configured to throw on errors and correctly handles malformed json (callback)', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { res.writeHead(400, 'Invalid params', { 'content-type': 'application/json' }) res.end('Invalid params') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const signal = new EE() client.request({ @@ -362,30 +377,32 @@ test('basic get returns 400 when configured to throw on errors and correctly han method: 'GET', throwOnError: true }, (err) => { - t.equal(err.message, 'Response status code 400: Invalid params') - t.equal(err.status, 400) - t.equal(err.statusCode, 400) - t.equal(err.headers.connection, 'keep-alive') - t.same(err.body, null) + t.strictEqual(err.message, 'Response status code 400: Invalid params') + t.strictEqual(err.status, 400) + t.strictEqual(err.statusCode, 400) + t.strictEqual(err.headers.connection, 'keep-alive') + t.strictEqual(err.body, undefined) }) - t.equal(signal.listenerCount('abort'), 1) + t.strictEqual(signal.listenerCount('abort'), 1) }) + + await t.completed }) -test('basic get returns 400 when configured to throw on errors (promise)', (t) => { - t.plan(6) +test('basic get returns 400 when configured to throw on errors (promise)', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { res.writeHead(400, 'Invalid params', { 'content-type': 'text/plain' }) res.end('Invalid params') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`, { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const signal = new EE() try { @@ -397,18 +414,20 @@ test('basic get returns 400 when configured to throw on errors (promise)', (t) = }) t.fail('Should throw an error') } catch (err) { - t.equal(err.message, 'Response status code 400: Invalid params') - t.equal(err.status, 400) - t.equal(err.statusCode, 400) - t.equal(err.body, 'Invalid params') - t.equal(err.headers.connection, 'keep-alive') - t.equal(err.headers['content-type'], 'text/plain') + t.strictEqual(err.message, 'Response status code 400: Invalid params') + t.strictEqual(err.status, 400) + t.strictEqual(err.statusCode, 400) + t.strictEqual(err.body, 'Invalid params') + t.strictEqual(err.headers.connection, 'keep-alive') + t.strictEqual(err.headers['content-type'], 'text/plain') } }) + + await t.completed }) -test('basic get returns error body when configured to throw on errors', (t) => { - t.plan(6) +test('basic get returns error body when configured to throw on errors', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { const body = { msg: 'Error', details: { code: 94 } } @@ -418,13 +437,13 @@ test('basic get returns error body when configured to throw on errors', (t) => { }) res.end(bodyAsString) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`, { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const signal = new EE() try { @@ -436,36 +455,38 @@ test('basic get returns error body when configured to throw on errors', (t) => { }) t.fail('Should throw an error') } catch (err) { - t.equal(err.message, 'Response status code 400: Invalid params') - t.equal(err.status, 400) - t.equal(err.statusCode, 400) - t.equal(err.headers.connection, 'keep-alive') - t.equal(err.headers['content-type'], 'application/json') - t.same(err.body, { msg: 'Error', details: { code: 94 } }) + t.strictEqual(err.message, 'Response status code 400: Invalid params') + t.strictEqual(err.status, 400) + t.strictEqual(err.statusCode, 400) + t.strictEqual(err.headers.connection, 'keep-alive') + t.strictEqual(err.headers['content-type'], 'application/json') + t.deepStrictEqual(err.body, { msg: 'Error', details: { code: 94 } }) } }) + + await t.completed }) -test('basic head', (t) => { - t.plan(14) +test('basic head', async (t) => { + t = tspl(t, { plan: 14 }) const server = createServer((req, res) => { - t.equal('/123', req.url) - t.equal('HEAD', req.method) - t.equal(`localhost:${server.address().port}`, req.headers.host) + t.strictEqual('/123', req.url) + t.strictEqual('HEAD', req.method) + t.strictEqual(`localhost:${server.address().port}`, req.headers.host) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/123', method: 'HEAD' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') body .resume() .on('end', () => { @@ -474,9 +495,9 @@ test('basic head', (t) => { }) client.request({ path: '/123', method: 'HEAD' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') body .resume() .on('end', () => { @@ -484,28 +505,30 @@ test('basic head', (t) => { }) }) }) + + await t.completed }) -test('basic head (IPv6)', { skip: !hasIPv6 }, (t) => { - t.plan(14) +test('basic head (IPv6)', { skip: !hasIPv6 }, async (t) => { + t = tspl(t, { plan: 15 }) const server = createServer((req, res) => { - t.equal('/123', req.url) - t.equal('HEAD', req.method) - t.equal(`[::1]:${server.address().port}`, req.headers.host) + t.strictEqual('/123', req.url) + t.strictEqual('HEAD', req.method) + t.strictEqual(`[::1]:${server.address().port}`, req.headers.host) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, '::', () => { const client = new Client(`http://[::1]:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/123', method: 'HEAD' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') body .resume() .on('end', () => { @@ -514,9 +537,9 @@ test('basic head (IPv6)', { skip: !hasIPv6 }, (t) => { }) client.request({ path: '/123', method: 'HEAD' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') body .resume() .on('end', () => { @@ -524,90 +547,96 @@ test('basic head (IPv6)', { skip: !hasIPv6 }, (t) => { }) }) }) + + await t.completed }) -test('get with host header', (t) => { - t.plan(7) +test('get with host header', async (t) => { + t = tspl(t, { plan: 7 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) - t.equal('example.com', req.headers.host) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) + t.strictEqual('example.com', req.headers.host) res.setHeader('content-type', 'text/plain') res.end('hello from ' + req.headers.host) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', headers: { host: 'example.com' } }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello from example.com', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello from example.com', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('get with host header (IPv6)', { skip: !hasIPv6 }, (t) => { - t.plan(7) +test('get with host header (IPv6)', { skip: !hasIPv6 }, async (t) => { + t = tspl(t, { plan: 7 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) - t.equal('[::1]', req.headers.host) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) + t.strictEqual('[::1]', req.headers.host) res.setHeader('content-type', 'text/plain') res.end('hello from ' + req.headers.host) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, '::', () => { const client = new Client(`http://[::1]:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', headers: { host: '[::1]' } }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello from [::1]', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello from [::1]', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('head with host header', (t) => { - t.plan(7) +test('head with host header', async (t) => { + t = tspl(t, { plan: 7 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('HEAD', req.method) - t.equal('example.com', req.headers.host) + t.strictEqual('/', req.url) + t.strictEqual('HEAD', req.method) + t.strictEqual('example.com', req.headers.host) res.setHeader('content-type', 'text/plain') res.end('hello from ' + req.headers.host) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'HEAD', headers: { host: 'example.com' } }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') body .resume() .on('end', () => { @@ -615,13 +644,15 @@ test('head with host header', (t) => { }) }) }) + + await t.completed }) function postServer (t, expected) { return function (req, res) { - t.equal(req.url, '/') - t.equal(req.method, 'POST') - t.notSame(req.headers['content-length'], null) + t.strictEqual(req.url, '/') + t.strictEqual(req.method, 'POST') + t.notStrictEqual(req.headers['content-length'], null) req.setEncoding('utf8') let data = '' @@ -629,74 +660,78 @@ function postServer (t, expected) { req.on('data', function (d) { data += d }) req.on('end', () => { - t.equal(data, expected) + t.strictEqual(data, expected) res.end('hello') }) } } -test('basic POST with string', (t) => { - t.plan(7) +test('basic POST with string', async (t) => { + t = tspl(t, { plan: 7 }) const expected = readFileSync(__filename, 'utf8') const server = createServer(postServer(t, expected)) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'POST', body: expected }, (err, data) => { - t.error(err) - t.equal(data.statusCode, 200) + t.ifError(err) + t.strictEqual(data.statusCode, 200) const bufs = [] data.body .on('data', (buf) => { bufs.push(buf) }) .on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic POST with empty string', (t) => { - t.plan(7) +test('basic POST with empty string', async (t) => { + t = tspl(t, { plan: 7 }) const server = createServer(postServer(t, '')) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'POST', body: '' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic POST with string and content-length', (t) => { - t.plan(7) +test('basic POST with string and content-length', async (t) => { + t = tspl(t, { plan: 7 }) const expected = readFileSync(__filename, 'utf8') const server = createServer(postServer(t, expected)) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -706,56 +741,60 @@ test('basic POST with string and content-length', (t) => { }, body: expected }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic POST with Buffer', (t) => { - t.plan(7) +test('basic POST with Buffer', async (t) => { + t = tspl(t, { plan: 7 }) const expected = readFileSync(__filename) const server = createServer(postServer(t, expected.toString())) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'POST', body: expected }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic POST with stream', (t) => { - t.plan(7) +test('basic POST with stream', async (t) => { + t = tspl(t, { plan: 7 }) const expected = readFileSync(__filename, 'utf8') const server = createServer(postServer(t, expected)) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -766,30 +805,32 @@ test('basic POST with stream', (t) => { headersTimeout: 0, body: createReadStream(__filename) }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic POST with paused stream', (t) => { - t.plan(7) +test('basic POST with paused stream', async (t) => { + t = tspl(t, { plan: 7 }) const expected = readFileSync(__filename, 'utf8') const server = createServer(postServer(t, expected)) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const stream = createReadStream(__filename) stream.pause() @@ -802,32 +843,34 @@ test('basic POST with paused stream', (t) => { headersTimeout: 0, body: stream }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic POST with custom stream', (t) => { - t.plan(4) +test('basic POST with custom stream', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { req.resume().on('end', () => { res.end('hello') }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const body = new EE() body.pipe = () => {} @@ -837,17 +880,17 @@ test('basic POST with custom stream', (t) => { headersTimeout: 0, body }, (err, data) => { - t.error(err) - t.equal(data.statusCode, 200) + t.ifError(err) + t.strictEqual(data.statusCode, 200) const bufs = [] data.body.on('data', (buf) => { bufs.push(buf) }) data.body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) - t.strictSame(client[kBusy], true) + t.deepStrictEqual(client[kBusy], true) body.on('close', () => { body.emit('end') @@ -866,10 +909,12 @@ test('basic POST with custom stream', (t) => { }) }) }) + + await t.completed }) -test('basic POST with iterator', (t) => { - t.plan(3) +test('basic POST with iterator', async (t) => { + t = tspl(t, { plan: 3 }) const expected = 'hello' @@ -878,7 +923,7 @@ test('basic POST with iterator', (t) => { res.end(expected) }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const iterable = { [Symbol.iterator]: function * () { @@ -891,7 +936,7 @@ test('basic POST with iterator', (t) => { server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -899,24 +944,26 @@ test('basic POST with iterator', (t) => { requestTimeout: 0, body: iterable }, (err, { statusCode, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic POST with iterator with invalid data', (t) => { - t.plan(1) +test('basic POST with iterator with invalid data', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer(() => {}) - t.teardown(server.close.bind(server)) + after(() => server.close()) const iterable = { [Symbol.iterator]: function * () { @@ -926,7 +973,7 @@ test('basic POST with iterator with invalid data', (t) => { server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -937,19 +984,21 @@ test('basic POST with iterator with invalid data', (t) => { t.ok(err instanceof TypeError) }) }) + + await t.completed }) -test('basic POST with async iterator', (t) => { - t.plan(7) +test('basic POST with async iterator', async (t) => { + t = tspl(t, { plan: 7 }) const expected = readFileSync(__filename, 'utf8') const server = createServer(postServer(t, expected)) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', @@ -960,28 +1009,30 @@ test('basic POST with async iterator', (t) => { headersTimeout: 0, body: wrapWithAsyncIterable(createReadStream(__filename)) }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic POST with transfer encoding: chunked', (t) => { - t.plan(8) +test('basic POST with transfer encoding: chunked', async (t) => { + t = tspl(t, { plan: 8 }) let body const server = createServer(function (req, res) { - t.equal(req.url, '/') - t.equal(req.method, 'POST') - t.same(req.headers['content-length'], null) - t.equal(req.headers['transfer-encoding'], 'chunked') + t.strictEqual(req.url, '/') + t.strictEqual(req.method, 'POST') + t.strictEqual(req.headers['content-length'], undefined) + t.strictEqual(req.headers['transfer-encoding'], 'chunked') body.push(null) @@ -991,15 +1042,15 @@ test('basic POST with transfer encoding: chunked', (t) => { req.on('data', function (d) { data += d }) req.on('end', () => { - t.equal(data, 'asd') + t.strictEqual(data, 'asd') res.end('hello') }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) body = new Readable({ read () { } @@ -1011,31 +1062,33 @@ test('basic POST with transfer encoding: chunked', (t) => { // no content-length header body }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('basic POST with empty stream', (t) => { - t.plan(4) +test('basic POST with empty stream', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer(function (req, res) { - t.same(req.headers['content-length'], 0) + t.deepStrictEqual(req.headers['content-length'], '0') req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const body = new Readable({ autoDestroy: false, @@ -1046,7 +1099,7 @@ test('basic POST with empty stream', (t) => { } }).on('end', () => { process.nextTick(() => { - t.equal(body.destroyed, true) + t.strictEqual(body.destroyed, true) }) }) body.push(null) @@ -1055,7 +1108,7 @@ test('basic POST with empty stream', (t) => { method: 'POST', body }, (err, { statusCode, headers, body }) => { - t.error(err) + t.ifError(err) body .on('data', () => { t.fail() @@ -1065,20 +1118,22 @@ test('basic POST with empty stream', (t) => { }) }) }) + + await t.completed }) -test('10 times GET', (t) => { +test('10 times GET', async (t) => { const num = 10 - t.plan(3 * 10) + t = tspl(t, { plan: 3 * num }) const server = createServer((req, res) => { res.end(req.url) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) for (let i = 0; i < num; i++) { makeRequest(i) @@ -1086,32 +1141,34 @@ test('10 times GET', (t) => { function makeRequest (i) { client.request({ path: '/' + i, method: 'GET' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('/' + i, Buffer.concat(bufs).toString('utf8')) + t.strictEqual('/' + i, Buffer.concat(bufs).toString('utf8')) }) }) } }) + + await t.completed }) -test('10 times HEAD', (t) => { +test('10 times HEAD', async (t) => { const num = 10 - t.plan(3 * 10) + t = tspl(t, { plan: num * 3 }) const server = createServer((req, res) => { res.end(req.url) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) for (let i = 0; i < num; i++) { makeRequest(i) @@ -1119,8 +1176,8 @@ test('10 times HEAD', (t) => { function makeRequest (i) { client.request({ path: '/' + i, method: 'HEAD' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) body .resume() .on('end', () => { @@ -1129,49 +1186,53 @@ test('10 times HEAD', (t) => { }) } }) + + await t.completed }) -test('Set-Cookie', (t) => { - t.plan(4) +test('Set-Cookie', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.setHeader('content-type', 'text/plain') res.setHeader('Set-Cookie', ['a cookie', 'another cookie', 'more cookies']) res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.strictSame(headers['set-cookie'], ['a cookie', 'another cookie', 'more cookies']) + t.ifError(err) + t.strictEqual(statusCode, 200) + t.deepStrictEqual(headers['set-cookie'], ['a cookie', 'another cookie', 'more cookies']) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) }) + + await t.completed }) -test('ignore request header mutations', (t) => { - t.plan(2) +test('ignore request header mutations', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { - t.equal(req.headers.test, 'test') + t.strictEqual(req.headers.test, 'test') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const headers = { test: 'test' } client.request({ @@ -1179,20 +1240,22 @@ test('ignore request header mutations', (t) => { method: 'GET', headers }, (err, { body }) => { - t.error(err) + t.ifError(err) body.resume() }) headers.test = 'asd' }) + + await t.completed }) -test('url-like url', (t) => { - t.plan(1) +test('url-like url', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client({ @@ -1200,25 +1263,27 @@ test('url-like url', (t) => { port: server.address().port, protocol: 'http:' }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) }) + + await t.completed }) -test('an absolute url as path', (t) => { - t.plan(2) +test('an absolute url as path', async (t) => { + t = tspl(t, { plan: 2 }) const path = 'http://example.com' const server = createServer((req, res) => { - t.equal(req.url, path) + t.strictEqual(req.url, path) res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client({ @@ -1226,22 +1291,24 @@ test('an absolute url as path', (t) => { port: server.address().port, protocol: 'http:' }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path, method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) }) + + await t.completed }) -test('multiple destroy callback', (t) => { - t.plan(4) +test('multiple destroy callback', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client({ @@ -1249,51 +1316,53 @@ test('multiple destroy callback', (t) => { port: server.address().port, protocol: 'http:' }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() - .on('error', () => { - t.ok(true, 'pass') + .on('error', (err) => { + t.ok(err instanceof Error) }) client.destroy(new Error(), (err) => { - t.error(err) + t.ifError(err) }) client.destroy(new Error(), (err) => { - t.error(err) + t.ifError(err) }) }) }) + + await t.completed }) -test('only one streaming req at a time', (t) => { - t.plan(7) +test('only one streaming req at a time', async (t) => { + t = tspl(t, { plan: 7 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 4 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) @@ -1304,58 +1373,60 @@ test('only one streaming req at a time', (t) => { body: new Readable({ read () { setImmediate(() => { - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) this.push(null) }) } }).on('resume', () => { - t.equal(client[kSize], 1) + t.strictEqual(client[kSize], 1) }) }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { t.ok(true, 'pass') }) }) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) }) }) + + await t.completed }) -test('only one async iterating req at a time', (t) => { - t.plan(6) +test('only one async iterating req at a time', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 4 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) const body = wrapWithAsyncIterable(new Readable({ read () { setImmediate(() => { - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) this.push(null) }) } @@ -1366,48 +1437,52 @@ test('only one async iterating req at a time', (t) => { idempotent: true, body }, (err, data) => { - t.error(err) + t.ifError(err) data.body .resume() .on('end', () => { t.ok(true, 'pass') }) }) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) }) }) + + await t.completed }) -test('300 requests succeed', (t) => { - t.plan(300 * 3) +test('300 requests succeed', async (t) => { + t = tspl(t, { plan: 300 * 3 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) for (let n = 0; n < 300; ++n) { client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.on('data', (chunk) => { - t.equal(chunk.toString(), 'asd') + t.strictEqual(chunk.toString(), 'asd') }).on('end', () => { t.ok(true, 'pass') }) }) } }) + + await t.completed }) -test('request args validation', (t) => { - t.plan(2) +test('request args validation', async (t) => { + t = tspl(t, { plan: 2 }) const client = new Client('http://localhost:5000') @@ -1420,29 +1495,33 @@ test('request args validation', (t) => { } catch (err) { t.ok(err instanceof errors.InvalidArgumentError) } + + await t.completed }) -test('request args validation promise', (t) => { - t.plan(1) +test('request args validation promise', async (t) => { + t = tspl(t, { plan: 1 }) const client = new Client('http://localhost:5000') client.request(null).catch((err) => { t.ok(err instanceof errors.InvalidArgumentError) }) + + await t.completed }) -test('increase pipelining', (t) => { - t.plan(4) +test('increase pipelining', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { req.resume() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', @@ -1462,34 +1541,36 @@ test('increase pipelining', (t) => { } }) - t.equal(client[kRunning], 0) + t.strictEqual(client[kRunning], 0) client.on('connect', () => { - t.equal(client[kRunning], 0) + t.strictEqual(client[kRunning], 0) process.nextTick(() => { - t.equal(client[kRunning], 1) + t.strictEqual(client[kRunning], 1) client.pipelining = 3 - t.equal(client[kRunning], 2) + t.strictEqual(client[kRunning], 2) }) }) }) + + await t.completed }) -test('destroy in push', (t) => { - t.plan(4) +test('destroy in push', async (t) => { + t = tspl(t, { plan: 4 }) let _res const server = createServer((req, res) => { res.write('asd') _res = res }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, { body }) => { - t.error(err) + t.ifError(err) body.once('data', () => { _res.write('asd') body.on('data', (buf) => { @@ -1502,53 +1583,57 @@ test('destroy in push', (t) => { }) client.request({ path: '/', method: 'GET' }, (err, { body }) => { - t.error(err) + t.ifError(err) let buf = '' body.on('data', (chunk) => { buf = chunk.toString() _res.end() }).on('end', () => { - t.equal('asd', buf) + t.strictEqual('asd', buf) }) }) }) + + await t.completed }) -test('non recoverable socket error fails pending request', (t) => { - t.plan(2) +test('non recoverable socket error fails pending request', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.equal(err.message, 'kaboom') + t.strictEqual(err.message, 'kaboom') }) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.equal(err.message, 'kaboom') + t.strictEqual(err.message, 'kaboom') }) client.on('connect', () => { client[kSocket].destroy(new Error('kaboom')) }) }) + + await t.completed }) -test('POST empty with error', (t) => { - t.plan(1) +test('POST empty with error', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const body = new Readable({ read () { @@ -1562,110 +1647,118 @@ test('POST empty with error', (t) => { }) client.request({ path: '/', method: 'POST', body }, (err, data) => { - t.equal(err.message, 'asd') + t.strictEqual(err.message, 'asd') }) }) + + await t.completed }) -test('busy', (t) => { - t.plan(2) +test('busy', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 1 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client[kConnect](() => { client.request({ path: '/', method: 'GET' }, (err) => { - t.error(err) + t.ifError(err) }) - t.equal(client[kBusy], true) + t.strictEqual(client[kBusy], true) }) }) + + await t.completed }) -test('connected', (t) => { - t.plan(7) +test('connected', async (t) => { + t = tspl(t, { plan: 7 }) const server = createServer((req, res) => { // needed so that disconnect is emitted res.setHeader('connection', 'close') req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const url = new URL(`http://localhost:${server.address().port}`) const client = new Client(url, { pipelining: 1 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.on('connect', (origin, [self]) => { - t.equal(origin, url) - t.equal(client, self) + t.strictEqual(origin, url) + t.strictEqual(client, self) }) client.on('disconnect', (origin, [self]) => { - t.equal(origin, url) - t.equal(client, self) + t.strictEqual(origin, url) + t.strictEqual(client, self) }) - t.equal(client[kConnected], false) + t.strictEqual(client[kConnected], false) client[kConnect](() => { client.request({ path: '/', method: 'GET' }, (err) => { - t.error(err) + t.ifError(err) }) - t.equal(client[kConnected], true) + t.strictEqual(client[kConnected], true) }) }) + + await t.completed }) -test('emit disconnect after destroy', t => { - t.plan(4) +test('emit disconnect after destroy', async t => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { req.pipe(res) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const url = new URL(`http://localhost:${server.address().port}`) const client = new Client(url) - t.equal(client[kConnected], false) + t.strictEqual(client[kConnected], false) client[kConnect](() => { - t.equal(client[kConnected], true) + t.strictEqual(client[kConnected], true) let disconnected = false client.on('disconnect', () => { disconnected = true t.ok(true, 'pass') }) client.destroy(() => { - t.equal(disconnected, true) + t.strictEqual(disconnected, true) }) }) }) + + await t.completed }) -test('end response before request', t => { - t.plan(2) +test('end response before request', async t => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Client(`http://localhost:${server.address().port}`) @@ -1688,13 +1781,15 @@ test('end response before request', t => { }) .resume() client.on('disconnect', (url, targets, err) => { - t.equal(err.code, 'UND_ERR_INFO') + t.strictEqual(err.code, 'UND_ERR_INFO') }) }) + + await t.completed }) -test('parser pause with no body timeout', (t) => { - t.plan(2) +test('parser pause with no body timeout', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { let counter = 0 const t = setInterval(() => { @@ -1708,67 +1803,71 @@ test('parser pause with no body timeout', (t) => { } }, 20) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET' }, (err, { statusCode, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) body.resume() }) }) + + await t.completed }) -test('TypedArray and DataView body', (t) => { - t.plan(3) +test('TypedArray and DataView body', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { - t.equal(req.headers['content-length'], '8') + t.strictEqual(req.headers['content-length'], '8') res.end() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const body = Uint8Array.from(Buffer.alloc(8)) client.request({ path: '/', method: 'POST', body }, (err, { statusCode, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) body.resume() }) }) + + await t.completed }) -test('async iterator empty chunk continues', (t) => { - t.plan(5) +test('async iterator empty chunk continues', async (t) => { + t = tspl(t, { plan: 5 }) const serverChunks = ['hello', 'world'] const server = createServer((req, res) => { let str = '' let i = 0 req.on('data', (chunk) => { const content = chunk.toString() - t.equal(serverChunks[i++], content) + t.strictEqual(serverChunks[i++], content) str += content }).on('end', () => { - t.equal(str, serverChunks.join('')) + t.strictEqual(str, serverChunks.join('')) res.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const body = (async function * () { yield serverChunks[0] @@ -1776,27 +1875,29 @@ test('async iterator empty chunk continues', (t) => { yield serverChunks[1] })() client.request({ path: '/', method: 'POST', body }, (err, { statusCode, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) body.resume() }) }) + + await t.completed }) -test('async iterator error from server destroys early', (t) => { - t.plan(3) +test('async iterator error from server destroys early', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { req.on('data', (chunk) => { res.destroy() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) let gotDestroyed const body = (async function * () { try { @@ -1813,14 +1914,16 @@ test('async iterator error from server destroys early', (t) => { })() client.request({ path: '/', method: 'POST', body }, (err, { statusCode, body }) => { t.ok(err) - t.equal(statusCode, undefined) + t.strictEqual(statusCode, undefined) gotDestroyed() }) }) + + await t.completed }) -test('regular iterator error from server closes early', (t) => { - t.plan(3) +test('regular iterator error from server closes early', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { req.on('data', () => { process.nextTick(() => { @@ -1828,13 +1931,13 @@ test('regular iterator error from server closes early', (t) => { }) }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) let gotDestroyed = false const body = (function * () { try { @@ -1853,27 +1956,28 @@ test('regular iterator error from server closes early', (t) => { })() client.request({ path: '/', method: 'POST', body }, (err, { statusCode, body }) => { t.ok(err) - t.equal(statusCode, undefined) + t.strictEqual(statusCode, undefined) gotDestroyed = true }) }) + await t.completed }) -test('async iterator early return closes early', (t) => { - t.plan(3) +test('async iterator early return closes early', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { req.on('data', () => { res.writeHead(200) res.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) let gotDestroyed const body = (async function * () { try { @@ -1889,28 +1993,29 @@ test('async iterator early return closes early', (t) => { } })() client.request({ path: '/', method: 'POST', body }, (err, { statusCode, body }) => { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) gotDestroyed() }) }) + await t.completed }) -test('async iterator yield unsupported TypedArray', (t) => { - t.plan(3) +test('async iterator yield unsupported TypedArray', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { req.on('end', () => { res.writeHead(200) res.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const body = (async function * () { try { yield new Int32Array([1]) @@ -1921,26 +2026,28 @@ test('async iterator yield unsupported TypedArray', (t) => { })() client.request({ path: '/', method: 'POST', body }, (err) => { t.ok(err) - t.equal(err.code, 'ERR_INVALID_ARG_TYPE') + t.strictEqual(err.code, 'ERR_INVALID_ARG_TYPE') }) }) + + await t.completed }) -test('async iterator yield object error', (t) => { - t.plan(3) +test('async iterator yield object error', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { req.on('end', () => { res.writeHead(200) res.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 0 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const body = (async function * () { try { yield {} @@ -1951,9 +2058,11 @@ test('async iterator yield object error', (t) => { })() client.request({ path: '/', method: 'POST', body }, (err) => { t.ok(err) - t.equal(err.code, 'ERR_INVALID_ARG_TYPE') + t.strictEqual(err.code, 'ERR_INVALID_ARG_TYPE') }) }) + + await t.completed }) function buildParams (path) { @@ -1979,8 +2088,8 @@ function buildParams (path) { return builtParams } -test('\\r\\n in Headers', (t) => { - t.plan(1) +test('\\r\\n in Headers', async (t) => { + t = tspl(t, { plan: 1 }) const reqHeaders = { bar: '\r\nbar' @@ -1989,19 +2098,19 @@ test('\\r\\n in Headers', (t) => { const client = new Client('http://localhost:4242', { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', headers: reqHeaders }, (err) => { - t.equal(err.message, 'invalid bar header') + t.strictEqual(err.message, 'invalid bar header') }) }) -test('\\r in Headers', (t) => { - t.plan(1) +test('\\r in Headers', async (t) => { + t = tspl(t, { plan: 1 }) const reqHeaders = { bar: '\rbar' @@ -2010,19 +2119,19 @@ test('\\r in Headers', (t) => { const client = new Client('http://localhost:4242', { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', headers: reqHeaders }, (err) => { - t.equal(err.message, 'invalid bar header') + t.strictEqual(err.message, 'invalid bar header') }) }) -test('\\n in Headers', (t) => { - t.plan(1) +test('\\n in Headers', async (t) => { + t = tspl(t, { plan: 1 }) const reqHeaders = { bar: '\nbar' @@ -2031,19 +2140,19 @@ test('\\n in Headers', (t) => { const client = new Client('http://localhost:4242', { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', headers: reqHeaders }, (err) => { - t.equal(err.message, 'invalid bar header') + t.strictEqual(err.message, 'invalid bar header') }) }) -test('\\n in Headers', (t) => { - t.plan(1) +test('\\n in Headers', async (t) => { + t = tspl(t, { plan: 1 }) const reqHeaders = { '\nbar': 'foo' @@ -2052,45 +2161,45 @@ test('\\n in Headers', (t) => { const client = new Client('http://localhost:4242', { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET', headers: reqHeaders }, (err) => { - t.equal(err.message, 'invalid header key') + t.strictEqual(err.message, 'invalid header key') }) }) -test('\\n in Path', (t) => { - t.plan(1) +test('\\n in Path', async (t) => { + t = tspl(t, { plan: 1 }) const client = new Client('http://localhost:4242', { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/\n', method: 'GET' }, (err) => { - t.equal(err.message, 'invalid request path') + t.strictEqual(err.message, 'invalid request path') }) }) -test('\\n in Method', (t) => { - t.plan(1) +test('\\n in Method', async (t) => { + t = tspl(t, { plan: 1 }) const client = new Client('http://localhost:4242', { keepAliveTimeout: 300e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.request({ path: '/', method: 'GET\n' }, (err) => { - t.equal(err.message, 'invalid request method') + t.strictEqual(err.message, 'invalid request method') }) }) diff --git a/test/close-and-destroy.js b/test/close-and-destroy.js index b946e3e18b6..5d4f135dcd2 100644 --- a/test/close-and-destroy.js +++ b/test/close-and-destroy.js @@ -1,12 +1,13 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { Client, errors } = require('..') const { createServer } = require('node:http') const { kSocket, kSize } = require('../lib/core/symbols') -test('close waits for queued requests to finish', (t) => { - t.plan(16) +test('close waits for queued requests to finish', async (t) => { + t = tspl(t, { plan: 16 }) const server = createServer() @@ -14,11 +15,11 @@ test('close waits for queued requests to finish', (t) => { t.ok(true, 'request received') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, function (err, data) { onRequest(err, data) @@ -36,36 +37,38 @@ test('close waits for queued requests to finish', (t) => { }) function onRequest (err, { statusCode, headers, body }) { - t.error(err) - t.equal(statusCode, 200) + t.ifError(err) + t.strictEqual(statusCode, 200) const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) } + + await t.completed }) -test('destroy invoked all pending callbacks', (t) => { - t.plan(4) +test('destroy invoked all pending callbacks', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer() server.on('request', (req, res) => { res.write('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.on('error', (err) => { t.ok(err) }).resume() @@ -78,49 +81,53 @@ test('destroy invoked all pending callbacks', (t) => { t.ok(err instanceof errors.ClientDestroyedError) }) }) + + await t.completed }) -test('destroy invoked all pending callbacks ticked', (t) => { - t.plan(4) +test('destroy invoked all pending callbacks ticked', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer() server.on('request', (req, res) => { res.write('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 2 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) let ticked = false client.request({ path: '/', method: 'GET' }, (err) => { - t.equal(ticked, true) + t.strictEqual(ticked, true) t.ok(err instanceof errors.ClientDestroyedError) }) client.request({ path: '/', method: 'GET' }, (err) => { - t.equal(ticked, true) + t.strictEqual(ticked, true) t.ok(err instanceof errors.ClientDestroyedError) }) client.destroy() ticked = true }) + + await t.completed }) -test('close waits until socket is destroyed', (t) => { - t.plan(4) +test('close waits until socket is destroyed', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.end(req.url) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) makeRequest() @@ -130,39 +137,41 @@ test('close waits until socket is destroyed', (t) => { done = true }) client.close((err) => { - t.error(err) - t.equal(client.closed, true) - t.equal(done, true) + t.ifError(err) + t.strictEqual(client.closed, true) + t.strictEqual(done, true) }) }) function makeRequest () { client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) }) return client[kSize] <= client.pipelining } }) + + await t.completed }) -test('close should still reconnect', (t) => { - t.plan(6) +test('close should still reconnect', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { res.end(req.url) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) t.ok(makeRequest()) t.ok(!makeRequest()) client.close((err) => { - t.error(err) - t.equal(client.closed, true) + t.ifError(err) + t.strictEqual(client.closed, true) }) client.once('connect', () => { client[kSocket].destroy() @@ -170,57 +179,61 @@ test('close should still reconnect', (t) => { function makeRequest () { client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) return client[kSize] <= client.pipelining } }) + + await t.completed }) -test('close should call callback once finished', (t) => { - t.plan(6) +test('close should call callback once finished', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { setImmediate(function () { res.end(req.url) }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) t.ok(makeRequest()) t.ok(!makeRequest()) client.close((err) => { - t.error(err) - t.equal(client.closed, true) + t.ifError(err) + t.strictEqual(client.closed, true) }) function makeRequest () { client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.resume() }) return client[kSize] <= client.pipelining } }) + + await t.completed }) -test('closed and destroyed errors', (t) => { - t.plan(4) +test('closed and destroyed errors', async (t) => { + t = tspl(t, { plan: 4 }) const client = new Client('http://localhost:4000') - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err) => { t.ok(err) }) client.close((err) => { - t.error(err) + t.ifError(err) }) client.request({ path: '/', method: 'GET' }, (err) => { t.ok(err instanceof errors.ClientClosedError) @@ -229,13 +242,15 @@ test('closed and destroyed errors', (t) => { t.ok(err instanceof errors.ClientDestroyedError) }) }) + + await t.completed }) -test('close after and destroy should error', (t) => { - t.plan(2) +test('close after and destroy should error', async (t) => { + t = tspl(t, { plan: 2 }) const client = new Client('http://localhost:4000') - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.destroy() client.close((err) => { @@ -244,16 +259,18 @@ test('close after and destroy should error', (t) => { client.close().catch((err) => { t.ok(err instanceof errors.ClientDestroyedError) }) + + await t.completed }) -test('close socket and reconnect after maxRequestsPerClient reached', (t) => { - t.plan(5) +test('close socket and reconnect after maxRequestsPerClient reached', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end(req.url) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { let connections = 0 @@ -264,28 +281,30 @@ test('close socket and reconnect after maxRequestsPerClient reached', (t) => { `http://localhost:${server.address().port}`, { maxRequestsPerClient: 2 } ) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) - await t.resolves(makeRequest()) - await t.resolves(makeRequest()) - await t.resolves(makeRequest()) - await t.resolves(makeRequest()) - t.equal(connections, 2) + await makeRequest() + await makeRequest() + await makeRequest() + await makeRequest() + t.strictEqual(connections, 2) function makeRequest () { return client.request({ path: '/', method: 'GET' }) } }) + + await t.completed }) -test('close socket and reconnect after maxRequestsPerClient reached (async)', (t) => { - t.plan(2) +test('close socket and reconnect after maxRequestsPerClient reached (async)', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end(req.url) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { let connections = 0 @@ -296,32 +315,32 @@ test('close socket and reconnect after maxRequestsPerClient reached (async)', (t `http://localhost:${server.address().port}`, { maxRequestsPerClient: 2 } ) - t.teardown(client.destroy.bind(client)) - - await t.resolves( - Promise.all([ - makeRequest(), - makeRequest(), - makeRequest(), - makeRequest() - ]) - ) - t.equal(connections, 2) + after(() => client.destroy()) + + await Promise.all([ + makeRequest(), + makeRequest(), + makeRequest(), + makeRequest() + ]) + t.strictEqual(connections, 2) function makeRequest () { return client.request({ path: '/', method: 'GET' }) } }) + + await t.completed }) -test('should not close socket when no maxRequestsPerClient is provided', (t) => { - t.plan(5) +test('should not close socket when no maxRequestsPerClient is provided', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end(req.url) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { let connections = 0 @@ -329,16 +348,18 @@ test('should not close socket when no maxRequestsPerClient is provided', (t) => connections++ }) const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) - await t.resolves(makeRequest()) - await t.resolves(makeRequest()) - await t.resolves(makeRequest()) - await t.resolves(makeRequest()) - t.equal(connections, 1) + await makeRequest() + await makeRequest() + await makeRequest() + await makeRequest() + t.strictEqual(connections, 1) function makeRequest () { return client.request({ path: '/', method: 'GET' }) } }) + + await t.completed }) diff --git a/test/connect-timeout.js b/test/connect-timeout.js index 5eab8ee1098..d8ff177504c 100644 --- a/test/connect-timeout.js +++ b/test/connect-timeout.js @@ -1,19 +1,22 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after, describe } = require('node:test') const { Client, Pool, errors } = require('..') const net = require('node:net') +const assert = require('node:assert') const sleep = ms => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, Number(ms)) -test('prioritize socket errors over timeouts', (t) => { - t.plan(1) +// Using describe instead of test to avoid the timeout +describe('prioritize socket errors over timeouts', () => { + const t = tspl({ ...assert, after: () => {} }, { plan: 1 }) const connectTimeout = 1000 const client = new Pool('http://foobar.bar:1234', { connectTimeout: 2 }) client.request({ method: 'GET', path: '/foobar' }) .then(() => t.fail()) .catch((err) => { - t.equal(err.code, 'ENOTFOUND') + t.strictEqual(err.code, 'ENOTFOUND') }) // block for 1s which is enough for the dns lookup to complete and TO to fire @@ -25,13 +28,13 @@ net.connect = function (options) { return new net.Socket(options) } -test('connect-timeout', t => { - t.plan(1) +test('connect-timeout', async t => { + t = tspl(t, { plan: 1 }) const client = new Client('http://localhost:9000', { connectTimeout: 1e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const timeout = setTimeout(() => { t.fail() @@ -44,15 +47,17 @@ test('connect-timeout', t => { t.ok(err instanceof errors.ConnectTimeoutError) clearTimeout(timeout) }) + + await t.completed }) -test('connect-timeout', t => { - t.plan(1) +test('connect-timeout', async t => { + t = tspl(t, { plan: 1 }) const client = new Pool('http://localhost:9000', { connectTimeout: 1e3 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) const timeout = setTimeout(() => { t.fail() @@ -65,4 +70,6 @@ test('connect-timeout', t => { t.ok(err instanceof errors.ConnectTimeoutError) clearTimeout(timeout) }) + + await t.completed }) diff --git a/test/gc.js b/test/gc.js index ab3b0e83dbf..91ea6ab170c 100644 --- a/test/gc.js +++ b/test/gc.js @@ -1,18 +1,23 @@ 'use strict' /* global WeakRef, FinalizationRegistry */ -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { createServer } = require('node:net') const { Client, Pool } = require('..') -const SKIP = typeof WeakRef === 'undefined' || typeof FinalizationRegistry === 'undefined' +const SKIP = ( + typeof WeakRef === 'undefined' || + typeof FinalizationRegistry === 'undefined' || + typeof global.gc === 'undefined' +) setInterval(() => { global.gc() }, 100).unref() -test('gc should collect the client if, and only if, there are no active sockets', { skip: SKIP }, t => { - t.plan(4) +test('gc should collect the client if, and only if, there are no active sockets', { skip: SKIP }, async t => { + t = tspl(t, { plan: 4 }) const server = createServer((socket) => { socket.write('HTTP/1.1 200 OK\r\n') @@ -21,15 +26,15 @@ test('gc should collect the client if, and only if, there are no active sockets' socket.write('Connection: keep-alive\r\n') socket.write('\r\n\r\n') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) let weakRef let disconnected = false const registry = new FinalizationRegistry((data) => { - t.equal(data, 'test') - t.equal(disconnected, true) - t.equal(weakRef.deref(), undefined) + t.strictEqual(data, 'test') + t.strictEqual(disconnected, true) + t.strictEqual(weakRef.deref(), undefined) }) server.listen(0, () => { @@ -47,14 +52,16 @@ test('gc should collect the client if, and only if, there are no active sockets' path: '/', method: 'GET' }, (err, { body }) => { - t.error(err) + t.ifError(err) body.resume() }) }) + + await t.completed }) -test('gc should collect the pool if, and only if, there are no active sockets', { skip: SKIP }, t => { - t.plan(4) +test('gc should collect the pool if, and only if, there are no active sockets', { skip: SKIP }, async t => { + t = tspl(t, { plan: 4 }) const server = createServer((socket) => { socket.write('HTTP/1.1 200 OK\r\n') @@ -63,15 +70,15 @@ test('gc should collect the pool if, and only if, there are no active sockets', socket.write('Connection: keep-alive\r\n') socket.write('\r\n\r\n') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) let weakRef let disconnected = false const registry = new FinalizationRegistry((data) => { - t.equal(data, 'test') - t.equal(disconnected, true) - t.equal(weakRef.deref(), undefined) + t.strictEqual(data, 'test') + t.strictEqual(disconnected, true) + t.strictEqual(weakRef.deref(), undefined) }) server.listen(0, () => { @@ -91,8 +98,10 @@ test('gc should collect the pool if, and only if, there are no active sockets', path: '/', method: 'GET' }, (err, { body }) => { - t.error(err) + t.ifError(err) body.resume() }) }) + + await t.completed }) diff --git a/test/issue-2590.js b/test/issue-2590.js index cd4913c642f..c5499bf4513 100644 --- a/test/issue-2590.js +++ b/test/issue-2590.js @@ -1,14 +1,16 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { request } = require('..') const { createServer } = require('node:http') const { once } = require('node:events') test('aborting request with custom reason', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer(() => {}).listen(0) - t.teardown(server.close.bind(server)) + after(() => server.close()) await once(server, 'listening') const timeout = AbortSignal.timeout(0) @@ -25,11 +27,13 @@ test('aborting request with custom reason', async (t) => { await t.rejects( request(`http://localhost:${server.address().port}`, { signal: ac.signal }), - ac.signal.reason + /Request aborted/ ) await t.rejects( request(`http://localhost:${server.address().port}`, { signal: ac2.signal }), { code: 'UND_ERR_ABORTED' } ) + + await t.completed }) diff --git a/test/pool.js b/test/pool.js index af6a019c7a0..4a22aedc84e 100644 --- a/test/pool.js +++ b/test/pool.js @@ -1,5 +1,7 @@ 'use strict' +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { EventEmitter } = require('node:events') const { createServer } = require('node:http') const net = require('node:net') @@ -10,7 +12,6 @@ const { } = require('node:stream') const { promisify } = require('node:util') const proxyquire = require('proxyquire') -const { test } = require('tap') const { kBusy, kPending, @@ -24,60 +25,60 @@ const { errors } = require('..') -test('throws when connection is infinite', (t) => { - t.plan(2) +test('throws when connection is infinite', async (t) => { + t = tspl(t, { plan: 2 }) try { new Pool(null, { connections: 0 / 0 }) // eslint-disable-line } catch (e) { t.ok(e instanceof errors.InvalidArgumentError) - t.equal(e.message, 'invalid connections') + t.strictEqual(e.message, 'invalid connections') } }) -test('throws when connections is negative', (t) => { - t.plan(2) +test('throws when connections is negative', async (t) => { + t = tspl(t, { plan: 2 }) try { new Pool(null, { connections: -1 }) // eslint-disable-line no-new } catch (e) { t.ok(e instanceof errors.InvalidArgumentError) - t.equal(e.message, 'invalid connections') + t.strictEqual(e.message, 'invalid connections') } }) -test('throws when connection is not number', (t) => { - t.plan(2) +test('throws when connection is not number', async (t) => { + t = tspl(t, { plan: 2 }) try { new Pool(null, { connections: true }) // eslint-disable-line no-new } catch (e) { t.ok(e instanceof errors.InvalidArgumentError) - t.equal(e.message, 'invalid connections') + t.strictEqual(e.message, 'invalid connections') } }) -test('throws when factory is not a function', (t) => { - t.plan(2) +test('throws when factory is not a function', async (t) => { + t = tspl(t, { plan: 2 }) try { new Pool(null, { factory: '' }) // eslint-disable-line no-new } catch (e) { t.ok(e instanceof errors.InvalidArgumentError) - t.equal(e.message, 'factory must be a function.') + t.strictEqual(e.message, 'factory must be a function.') } }) -test('does not throw when connect is a function', (t) => { - t.plan(1) +test('does not throw when connect is a function', async (t) => { + t = tspl(t, { plan: 1 }) t.doesNotThrow(() => new Pool('http://localhost', { connect: () => {} })) }) -test('connect/disconnect event(s)', (t) => { +test('connect/disconnect event(s)', async (t) => { const clients = 2 - t.plan(clients * 6) + t = tspl(t, { plan: clients * 6 }) const server = createServer((req, res) => { res.writeHead(200, { @@ -86,23 +87,23 @@ test('connect/disconnect event(s)', (t) => { }) res.end('ok') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const pool = new Pool(`http://localhost:${server.address().port}`, { connections: clients, keepAliveTimeoutThreshold: 100 }) - t.teardown(pool.close.bind(pool)) + after(() => pool.close()) pool.on('connect', (origin, [pool, client]) => { - t.equal(client instanceof Client, true) + t.strictEqual(client instanceof Client, true) }) pool.on('disconnect', (origin, [pool, client], error) => { t.ok(client instanceof Client) t.ok(error instanceof errors.InformationalError) - t.equal(error.code, 'UND_ERR_INFO') - t.equal(error.message, 'socket idle timeout') + t.strictEqual(error.code, 'UND_ERR_INFO') + t.strictEqual(error.message, 'socket idle timeout') }) for (let i = 0; i < clients; i++) { @@ -110,112 +111,118 @@ test('connect/disconnect event(s)', (t) => { path: '/', method: 'GET' }, (err, { headers, body }) => { - t.error(err) + t.ifError(err) body.resume() }) } }) + + await t.completed }) -test('basic get', (t) => { - t.plan(14) +test('basic get', async (t) => { + t = tspl(t, { plan: 14 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) - t.equal(client[kUrl].origin, `http://localhost:${server.address().port}`) + t.strictEqual(client[kUrl].origin, `http://localhost:${server.address().port}`) client.request({ path: '/', method: 'GET' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) - t.equal(client.destroyed, false) - t.equal(client.closed, false) + t.strictEqual(client.destroyed, false) + t.strictEqual(client.closed, false) client.close((err) => { - t.error(err) - t.equal(client.destroyed, true) + t.ifError(err) + t.strictEqual(client.destroyed, true) client.destroy((err) => { - t.error(err) + t.ifError(err) client.close((err) => { t.ok(err instanceof errors.ClientDestroyedError) }) }) }) - t.equal(client.closed, true) + t.strictEqual(client.closed, true) }) + + await t.completed }) -test('URL as arg', (t) => { - t.plan(9) +test('URL as arg', async (t) => { + t = tspl(t, { plan: 9 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const url = new URL('http://localhost') url.port = server.address().port const client = new Pool(url) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) client.close((err) => { - t.error(err) + t.ifError(err) client.destroy((err) => { - t.error(err) + t.ifError(err) client.close((err) => { t.ok(err instanceof errors.ClientDestroyedError) }) }) }) }) + + await t.completed }) -test('basic get error async/await', (t) => { - t.plan(2) +test('basic get error async/await', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.destroy() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) await client.request({ path: '/', method: 'GET' }) .catch((err) => { @@ -228,24 +235,28 @@ test('basic get error async/await', (t) => { t.ok(err instanceof errors.ClientDestroyedError) }) }) + + await t.completed }) test('basic get with async/await', async (t) => { + t = tspl(t, { plan: 4 }) + const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const { statusCode, headers, body } = await client.request({ path: '/', method: 'GET' }) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') body.resume() await promisify(finished)(body) @@ -255,36 +266,40 @@ test('basic get with async/await', async (t) => { }) test('stream get async/await', async (t) => { + t = tspl(t, { plan: 4 }) + const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) await promisify(server.listen.bind(server))(0) const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) await client.stream({ path: '/', method: 'GET' }, ({ statusCode, headers }) => { - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') return new PassThrough() }) + + await t.completed }) -test('stream get error async/await', (t) => { - t.plan(1) +test('stream get error async/await', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.destroy() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) await client.stream({ path: '/', method: 'GET' }, () => { @@ -293,27 +308,29 @@ test('stream get error async/await', (t) => { t.ok(err) }) }) + + await t.completed }) -test('pipeline get', (t) => { - t.plan(5) +test('pipeline get', async (t) => { + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const bufs = [] client.pipeline({ path: '/', method: 'GET' }, ({ statusCode, headers, body }) => { - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') return body }) .end() @@ -321,12 +338,16 @@ test('pipeline get', (t) => { bufs.push(buf) }) .on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) + + await t.completed }) -test('backpressure algorithm', (t) => { +test('backpressure algorithm', async (t) => { + t = tspl(t, { plan: 12 }) + const seen = [] let total = 0 @@ -361,11 +382,11 @@ test('backpressure algorithm', (t) => { pool.dispatch({}, noopHandler) const d1 = seen.shift() // d1 = c0 - t.equal(d1.id, 0) + t.strictEqual(d1.id, 0) const d2 = seen.shift() // d2 = c0 - t.equal(d2.id, 0) + t.strictEqual(d2.id, 0) - t.equal(d1.id, d2.id) + t.strictEqual(d1.id, d2.id) writeMore = false @@ -374,12 +395,12 @@ test('backpressure algorithm', (t) => { pool.dispatch({}, noopHandler) // d4 = c1 const d3 = seen.shift() - t.equal(d3.id, 0) + t.strictEqual(d3.id, 0) const d4 = seen.shift() - t.equal(d4.id, 1) + t.strictEqual(d4.id, 1) - t.equal(d3.id, d2.id) - t.not(d3.id, d4.id) + t.strictEqual(d3.id, d2.id) + t.notEqual(d3.id, d4.id) writeMore = true @@ -392,28 +413,28 @@ test('backpressure algorithm', (t) => { pool.dispatch({}, noopHandler) // d6 = c0 const d5 = seen.shift() - t.equal(d5.id, 1) + t.strictEqual(d5.id, 1) const d6 = seen.shift() - t.equal(d6.id, 0) + t.strictEqual(d6.id, 0) - t.equal(d5.id, d4.id) - t.equal(d3.id, d6.id) + t.strictEqual(d5.id, d4.id) + t.strictEqual(d3.id, d6.id) - t.equal(total, 3) + t.strictEqual(total, 3) t.end() }) -test('busy', (t) => { - t.plan(8 * 16 + 2 + 1) +test('busy', async (t) => { + t = tspl(t, { plan: 8 * 16 + 2 + 1 }) const server = createServer((req, res) => { - t.equal('/', req.url) - t.equal('GET', req.method) + t.strictEqual('/', req.url) + t.strictEqual('GET', req.method) res.setHeader('content-type', 'text/plain') res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const connections = 2 @@ -428,45 +449,47 @@ test('busy', (t) => { client.on('connect', () => { t.ok(true, 'pass') }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) for (let n = 1; n <= 8; ++n) { client.request({ path: '/', method: 'GET' }, (err, { statusCode, headers, body }) => { - t.error(err) - t.equal(statusCode, 200) - t.equal(headers['content-type'], 'text/plain') + t.ifError(err) + t.strictEqual(statusCode, 200) + t.strictEqual(headers['content-type'], 'text/plain') const bufs = [] body.on('data', (buf) => { bufs.push(buf) }) body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) - t.equal(client[kPending], n) - t.equal(client[kBusy], n > 1) - t.equal(client[kSize], n) - t.equal(client[kRunning], 0) - - t.equal(client.stats.connected, 0) - t.equal(client.stats.free, 0) - t.equal(client.stats.queued, Math.max(n - connections, 0)) - t.equal(client.stats.pending, n) - t.equal(client.stats.size, n) - t.equal(client.stats.running, 0) + t.strictEqual(client[kPending], n) + t.strictEqual(client[kBusy], n > 1) + t.strictEqual(client[kSize], n) + t.strictEqual(client[kRunning], 0) + + t.strictEqual(client.stats.connected, 0) + t.strictEqual(client.stats.free, 0) + t.strictEqual(client.stats.queued, Math.max(n - connections, 0)) + t.strictEqual(client.stats.pending, n) + t.strictEqual(client.stats.size, n) + t.strictEqual(client.stats.running, 0) } }) + + await t.completed }) -test('invalid pool dispatch options', (t) => { - t.plan(2) +test('invalid pool dispatch options', async (t) => { + t = tspl(t, { plan: 2 }) const pool = new Pool('http://notahost') t.throws(() => pool.dispatch({}), errors.InvalidArgumentError, 'throws on invalid handler') t.throws(() => pool.dispatch({}, {}), errors.InvalidArgumentError, 'throws on invalid handler') }) -test('pool upgrade promise', (t) => { - t.plan(2) +test('pool upgrade promise', async (t) => { + t = tspl(t, { plan: 2 }) const server = net.createServer((c) => { c.on('data', (d) => { @@ -482,11 +505,11 @@ test('pool upgrade promise', (t) => { c.end() }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const { headers, socket } = await client.upgrade({ path: '/', @@ -500,20 +523,22 @@ test('pool upgrade promise', (t) => { }) socket.on('close', () => { - t.equal(recvData.toString(), 'Body') + t.strictEqual(recvData.toString(), 'Body') }) - t.same(headers, { + t.deepStrictEqual(headers, { hello: 'world', connection: 'upgrade', upgrade: 'websocket' }) socket.end() }) + + await t.completed }) -test('pool connect', (t) => { - t.plan(1) +test('pool connect', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((c) => { t.fail() @@ -530,11 +555,11 @@ test('pool connect', (t) => { socket.end(data) }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) const { socket } = await client.connect({ path: '/' @@ -546,25 +571,27 @@ test('pool connect', (t) => { }) socket.on('end', () => { - t.equal(recvData.toString(), 'Body') + t.strictEqual(recvData.toString(), 'Body') }) socket.write('Body') socket.end() }) + + await t.completed }) -test('pool dispatch', (t) => { - t.plan(2) +test('pool dispatch', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) let buf = '' client.dispatch({ @@ -574,22 +601,24 @@ test('pool dispatch', (t) => { onConnect () { }, onHeaders (statusCode, headers) { - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) }, onData (chunk) { buf += chunk }, onComplete () { - t.equal(buf, 'asd') + t.strictEqual(buf, 'asd') }, onError () { } }) }) + + await t.completed }) -test('pool pipeline args validation', (t) => { - t.plan(2) +test('pool pipeline args validation', async (t) => { + t = tspl(t, { plan: 2 }) const client = new Pool('http://localhost:5000') @@ -598,40 +627,44 @@ test('pool pipeline args validation', (t) => { t.ok(/opts/.test(err.message)) t.ok(err instanceof errors.InvalidArgumentError) }) + + await t.completed }) -test('300 requests succeed', (t) => { - t.plan(300 * 3) +test('300 requests succeed', async (t) => { + t = tspl(t, { plan: 300 * 3 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Pool(`http://localhost:${server.address().port}`, { connections: 1 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) for (let n = 0; n < 300; ++n) { client.request({ path: '/', method: 'GET' }, (err, data) => { - t.error(err) + t.ifError(err) data.body.on('data', (chunk) => { - t.equal(chunk.toString(), 'asd') + t.strictEqual(chunk.toString(), 'asd') }).on('end', () => { t.ok(true, 'pass') }) }) } }) + + await t.completed }) -test('pool connect error', (t) => { - t.plan(1) +test('pool connect error', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((c) => { t.fail() @@ -639,11 +672,11 @@ test('pool connect error', (t) => { server.on('connect', (req, socket, firstBodyChunk) => { socket.destroy() }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) try { await client.connect({ @@ -653,10 +686,12 @@ test('pool connect error', (t) => { t.ok(err) } }) + + await t.completed }) -test('pool upgrade error', (t) => { - t.plan(1) +test('pool upgrade error', async (t) => { + t = tspl(t, { plan: 1 }) const server = net.createServer((c) => { c.on('data', (d) => { @@ -671,11 +706,11 @@ test('pool upgrade error', (t) => { // Ignore error. }) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`) - t.teardown(client.close.bind(client)) + after(() => client.close()) try { await client.upgrade({ @@ -687,22 +722,24 @@ test('pool upgrade error', (t) => { t.ok(err) } }) + + await t.completed }) -test('pool dispatch error', (t) => { - t.plan(3) +test('pool dispatch error', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`, { connections: 1, pipelining: 1 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.dispatch({ path: '/', @@ -711,7 +748,7 @@ test('pool dispatch error', (t) => { onConnect () { }, onHeaders (statusCode, headers) { - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) }, onData (chunk) { }, @@ -739,26 +776,28 @@ test('pool dispatch error', (t) => { t.fail() }, onError (err) { - t.equal(err.code, 'UND_ERR_INVALID_ARG') + t.strictEqual(err.code, 'UND_ERR_INVALID_ARG') } }) }) + + await t.completed }) -test('pool request abort in queue', (t) => { - t.plan(3) +test('pool request abort in queue', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`, { connections: 1, pipelining: 1 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.dispatch({ path: '/', @@ -767,7 +806,7 @@ test('pool request abort in queue', (t) => { onConnect () { }, onHeaders (statusCode, headers) { - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) }, onData (chunk) { }, @@ -784,26 +823,28 @@ test('pool request abort in queue', (t) => { method: 'GET', signal }, (err) => { - t.equal(err.code, 'UND_ERR_ABORTED') + t.strictEqual(err.code, 'UND_ERR_ABORTED') }) signal.emit('abort') }) + + await t.completed }) -test('pool stream abort in queue', (t) => { - t.plan(3) +test('pool stream abort in queue', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`, { connections: 1, pipelining: 1 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.dispatch({ path: '/', @@ -812,7 +853,7 @@ test('pool stream abort in queue', (t) => { onConnect () { }, onHeaders (statusCode, headers) { - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) }, onData (chunk) { }, @@ -829,26 +870,28 @@ test('pool stream abort in queue', (t) => { method: 'GET', signal }, ({ body }) => body, (err) => { - t.equal(err.code, 'UND_ERR_ABORTED') + t.strictEqual(err.code, 'UND_ERR_ABORTED') }) signal.emit('abort') }) + + await t.completed }) -test('pool pipeline abort in queue', (t) => { - t.plan(3) +test('pool pipeline abort in queue', async (t) => { + t = tspl(t, { plan: 3 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`, { connections: 1, pipelining: 1 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) client.dispatch({ path: '/', @@ -857,7 +900,7 @@ test('pool pipeline abort in queue', (t) => { onConnect () { }, onHeaders (statusCode, headers) { - t.equal(statusCode, 200) + t.strictEqual(statusCode, 200) }, onData (chunk) { }, @@ -874,26 +917,28 @@ test('pool pipeline abort in queue', (t) => { method: 'GET', signal }, ({ body }) => body).end().on('error', (err) => { - t.equal(err.code, 'UND_ERR_ABORTED') + t.strictEqual(err.code, 'UND_ERR_ABORTED') }) signal.emit('abort') }) + + await t.completed }) -test('pool stream constructor error destroy body', (t) => { - t.plan(4) +test('pool stream constructor error destroy body', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`, { connections: 1, pipelining: 1 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) { const body = new Readable({ @@ -910,8 +955,8 @@ test('pool stream constructor error destroy body', (t) => { }, () => { t.fail() }, (err) => { - t.equal(err.code, 'UND_ERR_INVALID_ARG') - t.equal(body.destroyed, true) + t.strictEqual(err.code, 'UND_ERR_INVALID_ARG') + t.strictEqual(body.destroyed, true) }) } @@ -927,27 +972,29 @@ test('pool stream constructor error destroy body', (t) => { }, () => { t.fail() }, (err) => { - t.equal(err.code, 'UND_ERR_INVALID_ARG') - t.equal(body.destroyed, true) + t.strictEqual(err.code, 'UND_ERR_INVALID_ARG') + t.strictEqual(body.destroyed, true) }) } }) + + await t.completed }) -test('pool request constructor error destroy body', (t) => { - t.plan(4) +test('pool request constructor error destroy body', async (t) => { + t = tspl(t, { plan: 4 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`, { connections: 1, pipelining: 1 }) - t.teardown(client.close.bind(client)) + after(() => client.close()) { const body = new Readable({ @@ -962,8 +1009,8 @@ test('pool request constructor error destroy body', (t) => { 'transfer-encoding': 'fail' } }, (err) => { - t.equal(err.code, 'UND_ERR_INVALID_ARG') - t.equal(body.destroyed, true) + t.strictEqual(err.code, 'UND_ERR_INVALID_ARG') + t.strictEqual(body.destroyed, true) }) } @@ -977,40 +1024,42 @@ test('pool request constructor error destroy body', (t) => { method: 'CONNECT', body }, (err) => { - t.equal(err.code, 'UND_ERR_INVALID_ARG') - t.equal(body.destroyed, true) + t.strictEqual(err.code, 'UND_ERR_INVALID_ARG') + t.strictEqual(body.destroyed, true) }) } }) + + await t.completed }) -test('pool close waits for all requests', (t) => { - t.plan(5) +test('pool close waits for all requests', async (t) => { + t = tspl(t, { plan: 5 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Pool(`http://localhost:${server.address().port}`, { connections: 1, pipelining: 1 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err) => { - t.error(err) + t.ifError(err) }) client.request({ path: '/', method: 'GET' }, (err) => { - t.error(err) + t.ifError(err) }) client.close(() => { @@ -1028,22 +1077,24 @@ test('pool close waits for all requests', (t) => { t.ok(err instanceof errors.ClientClosedError) }) }) + + await t.completed }) -test('pool destroyed', (t) => { - t.plan(1) +test('pool destroyed', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Pool(`http://localhost:${server.address().port}`, { connections: 1, pipelining: 1 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.destroy() client.request({ @@ -1053,43 +1104,45 @@ test('pool destroyed', (t) => { t.ok(err instanceof errors.ClientDestroyedError) }) }) + + await t.completed }) -test('pool destroy fails queued requests', (t) => { - t.plan(6) +test('pool destroy fails queued requests', async (t) => { + t = tspl(t, { plan: 6 }) const server = createServer((req, res) => { res.end('asd') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, async () => { const client = new Pool(`http://localhost:${server.address().port}`, { connections: 1, pipelining: 1 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const _err = new Error() client.request({ path: '/', method: 'GET' }, (err) => { - t.equal(err, _err) + t.strictEqual(err, _err) }) client.request({ path: '/', method: 'GET' }, (err) => { - t.equal(err, _err) + t.strictEqual(err, _err) }) - t.equal(client.destroyed, false) + t.strictEqual(client.destroyed, false) client.destroy(_err, () => { t.ok(true, 'pass') }) - t.equal(client.destroyed, true) + t.strictEqual(client.destroyed, true) client.request({ path: '/', @@ -1098,4 +1151,5 @@ test('pool destroy fails queued requests', (t) => { t.ok(err instanceof errors.ClientDestroyedError) }) }) + await t.completed }) diff --git a/test/request-timeout.js b/test/request-timeout.js index 0db4417e0d5..f49f6c5bcf3 100644 --- a/test/request-timeout.js +++ b/test/request-timeout.js @@ -1,6 +1,7 @@ 'use strict' -const { test } = require('tap') +const { tspl } = require('@matteo.collina/tspl') +const { test, after } = require('node:test') const { createReadStream, writeFileSync, unlinkSync } = require('node:fs') const { Client, errors } = require('..') const { kConnect } = require('../lib/core/symbols') @@ -16,71 +17,75 @@ const { PassThrough } = require('node:stream') -test('request timeout', (t) => { - t.plan(1) +test('request timeout', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { setTimeout(() => { res.end('hello') }, 1000) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 500 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, response) => { t.ok(err instanceof errors.HeadersTimeoutError) }) }) + + await t.completed }) -test('request timeout with readable body', (t) => { - t.plan(1) +test('request timeout with readable body', async (t) => { + t = tspl(t, { plan: 1 }) const server = createServer((req, res) => { }) - t.teardown(server.close.bind(server)) + after(() => server.close()) const tempfile = `${__filename}.10mb.txt` writeFileSync(tempfile, Buffer.alloc(10 * 1024 * 1024)) - t.teardown(() => unlinkSync(tempfile)) + after(() => unlinkSync(tempfile)) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 1e3 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const body = createReadStream(tempfile) client.request({ path: '/', method: 'POST', body }, (err, response) => { t.ok(err instanceof errors.HeadersTimeoutError) }) }) + + await t.completed }) -test('body timeout', (t) => { - t.plan(2) +test('body timeout', async (t) => { + t = tspl(t, { plan: 2 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) const server = createServer((req, res) => { res.write('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 50 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, { body }) => { - t.error(err) + t.ifError(err) body.on('data', () => { clock.tick(100) }).on('error', (err) => { @@ -90,17 +95,19 @@ test('body timeout', (t) => { clock.tick(50) }) + + await t.completed }) -test('overridden request timeout', (t) => { - t.plan(1) +test('overridden request timeout', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -110,11 +117,11 @@ test('overridden request timeout', (t) => { }, 100) clock.tick(100) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 500 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET', headersTimeout: 50 }, (err, response) => { t.ok(err instanceof errors.HeadersTimeoutError) @@ -122,31 +129,33 @@ test('overridden request timeout', (t) => { clock.tick(50) }) + + await t.completed }) -test('overridden body timeout', (t) => { - t.plan(2) +test('overridden body timeout', async (t) => { + t = tspl(t, { plan: 2 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) const server = createServer((req, res) => { res.write('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 500 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET', bodyTimeout: 50 }, (err, { body }) => { - t.error(err) + t.ifError(err) body.on('data', () => { clock.tick(100) }).on('error', (err) => { @@ -156,17 +165,19 @@ test('overridden body timeout', (t) => { clock.tick(50) }) + + await t.completed }) -test('With EE signal', (t) => { - t.plan(1) +test('With EE signal', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -176,14 +187,14 @@ test('With EE signal', (t) => { }, 100) clock.tick(100) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 50 }) const ee = new EventEmitter() - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET', signal: ee }, (err, response) => { t.ok(err instanceof errors.HeadersTimeoutError) @@ -191,17 +202,19 @@ test('With EE signal', (t) => { clock.tick(50) }) + + await t.completed }) -test('With abort-controller signal', (t) => { - t.plan(1) +test('With abort-controller signal', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -211,14 +224,14 @@ test('With abort-controller signal', (t) => { }, 100) clock.tick(100) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 50 }) const abortController = new AbortController() - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => { t.ok(err instanceof errors.HeadersTimeoutError) @@ -226,17 +239,19 @@ test('With abort-controller signal', (t) => { clock.tick(50) }) + + await t.completed }) -test('Abort before timeout (EE)', (t) => { - t.plan(1) +test('Abort before timeout (EE)', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -248,30 +263,32 @@ test('Abort before timeout (EE)', (t) => { ee.emit('abort') clock.tick(50) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 50 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET', signal: ee }, (err, response) => { t.ok(err instanceof errors.RequestAbortedError) clock.tick(100) }) }) + + await t.completed }) -test('Abort before timeout (abort-controller)', (t) => { - t.plan(1) +test('Abort before timeout (abort-controller)', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -283,30 +300,32 @@ test('Abort before timeout (abort-controller)', (t) => { abortController.abort() clock.tick(50) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 50 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET', signal: abortController.signal }, (err, response) => { t.ok(err instanceof errors.RequestAbortedError) clock.tick(100) }) }) + + await t.completed }) -test('Timeout with pipelining', (t) => { - t.plan(3) +test('Timeout with pipelining', async (t) => { + t = tspl(t, { plan: 3 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -316,14 +335,14 @@ test('Timeout with pipelining', (t) => { }, 100) clock.tick(50) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { pipelining: 10, headersTimeout: 50 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, response) => { t.ok(err instanceof errors.HeadersTimeoutError) @@ -337,17 +356,19 @@ test('Timeout with pipelining', (t) => { t.ok(err instanceof errors.HeadersTimeoutError) }) }) + + await t.completed }) -test('Global option', (t) => { - t.plan(1) +test('Global option', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -357,13 +378,13 @@ test('Global option', (t) => { }, 100) clock.tick(100) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 50 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, response) => { t.ok(err instanceof errors.HeadersTimeoutError) @@ -371,17 +392,19 @@ test('Global option', (t) => { clock.tick(50) }) + + await t.completed }) -test('Request options overrides global option', (t) => { - t.plan(1) +test('Request options overrides global option', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -391,13 +414,13 @@ test('Request options overrides global option', (t) => { }, 100) clock.tick(100) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 50 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, response) => { t.ok(err instanceof errors.HeadersTimeoutError) @@ -405,15 +428,17 @@ test('Request options overrides global option', (t) => { clock.tick(50) }) + + await t.completed }) -test('client.destroy should cancel the timeout', (t) => { - t.plan(2) +test('client.destroy should cancel the timeout', async (t) => { + t = tspl(t, { plan: 2 }) const server = createServer((req, res) => { res.end('hello') }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { @@ -425,39 +450,41 @@ test('client.destroy should cancel the timeout', (t) => { }) client.destroy(err => { - t.error(err) + t.ifError(err) }) }) + + await t.completed }) -test('client.close should wait for the timeout', (t) => { - t.plan(2) +test('client.close should wait for the timeout', async (t) => { + t = tspl(t, { plan: 2 }) const clock = FakeTimers.install({ shouldClearNativeTimers: true }) - t.teardown(clock.uninstall.bind(clock)) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) const server = createServer((req, res) => { }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 100 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, response) => { t.ok(err instanceof errors.HeadersTimeoutError) }) client.close((err) => { - t.error(err) + t.ifError(err) }) client.on('connect', () => { @@ -466,16 +493,18 @@ test('client.close should wait for the timeout', (t) => { }) }) }) + + await t.completed }) -test('Validation', (t) => { - t.plan(4) +test('Validation', async (t) => { + t = tspl(t, { plan: 4 }) try { const client = new Client('http://localhost:3000', { headersTimeout: 'foobar' }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) } catch (err) { t.ok(err instanceof errors.InvalidArgumentError) } @@ -484,7 +513,7 @@ test('Validation', (t) => { const client = new Client('http://localhost:3000', { headersTimeout: -1 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) } catch (err) { t.ok(err instanceof errors.InvalidArgumentError) } @@ -493,7 +522,7 @@ test('Validation', (t) => { const client = new Client('http://localhost:3000', { bodyTimeout: 'foobar' }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) } catch (err) { t.ok(err instanceof errors.InvalidArgumentError) } @@ -502,21 +531,23 @@ test('Validation', (t) => { const client = new Client('http://localhost:3000', { bodyTimeout: -1 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) } catch (err) { t.ok(err instanceof errors.InvalidArgumentError) } + + await t.completed }) -test('Disable request timeout', (t) => { - t.plan(2) +test('Disable request timeout', async (t) => { + t = tspl(t, { plan: 2 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -526,39 +557,41 @@ test('Disable request timeout', (t) => { }, 32e3) clock.tick(33e3) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 0, connectTimeout: 0 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, response) => { - t.error(err) + t.ifError(err) const bufs = [] response.body.on('data', (buf) => { bufs.push(buf) }) response.body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) clock.tick(31e3) }) + + await t.completed }) -test('Disable request timeout for a single request', (t) => { - t.plan(2) +test('Disable request timeout for a single request', async (t) => { + t = tspl(t, { plan: 2 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -568,39 +601,41 @@ test('Disable request timeout for a single request', (t) => { }, 32e3) clock.tick(33e3) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 0, connectTimeout: 0 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.request({ path: '/', method: 'GET' }, (err, response) => { - t.error(err) + t.ifError(err) const bufs = [] response.body.on('data', (buf) => { bufs.push(buf) }) response.body.on('end', () => { - t.equal('hello', Buffer.concat(bufs).toString('utf8')) + t.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }) }) clock.tick(31e3) }) + + await t.completed }) -test('stream timeout', (t) => { - t.plan(1) +test('stream timeout', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -610,11 +645,11 @@ test('stream timeout', (t) => { }, 301e3) clock.tick(301e3) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { connectTimeout: 0 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.stream({ path: '/', @@ -626,17 +661,19 @@ test('stream timeout', (t) => { t.ok(err instanceof errors.HeadersTimeoutError) }) }) + + await t.completed }) -test('stream custom timeout', (t) => { - t.plan(1) +test('stream custom timeout', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -646,13 +683,13 @@ test('stream custom timeout', (t) => { }, 31e3) clock.tick(31e3) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 30e3 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client.stream({ path: '/', @@ -664,17 +701,19 @@ test('stream custom timeout', (t) => { t.ok(err instanceof errors.HeadersTimeoutError) }) }) + + await t.completed }) -test('pipeline timeout', (t) => { - t.plan(1) +test('pipeline timeout', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -684,11 +723,11 @@ test('pipeline timeout', (t) => { }, 301e3) clock.tick(301e3) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const buf = Buffer.alloc(1e6).toString() pipeline( @@ -719,17 +758,19 @@ test('pipeline timeout', (t) => { } ) }) + + await t.completed }) -test('pipeline timeout', (t) => { - t.plan(1) +test('pipeline timeout', async (t) => { + t = tspl(t, { plan: 1 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) @@ -739,13 +780,13 @@ test('pipeline timeout', (t) => { }, 31e3) clock.tick(31e3) }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { headersTimeout: 30e3 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) const buf = Buffer.alloc(1e6).toString() pipeline( @@ -776,30 +817,32 @@ test('pipeline timeout', (t) => { } ) }) + + await t.completed }) -test('client.close should not deadlock', (t) => { - t.plan(2) +test('client.close should not deadlock', async (t) => { + t = tspl(t, { plan: 2 }) - const clock = FakeTimers.install() - t.teardown(clock.uninstall.bind(clock)) + const clock = FakeTimers.install({ shouldClearNativeTimers: true }) + after(() => clock.uninstall()) const orgTimers = { ...timers } Object.assign(timers, { setTimeout, clearTimeout }) - t.teardown(() => { + after(() => { Object.assign(timers, orgTimers) }) const server = createServer((req, res) => { }) - t.teardown(server.close.bind(server)) + after(() => server.close()) server.listen(0, () => { const client = new Client(`http://localhost:${server.address().port}`, { bodyTimeout: 200, headersTimeout: 100 }) - t.teardown(client.destroy.bind(client)) + after(() => client.destroy()) client[kConnect](() => { client.request({ @@ -810,10 +853,11 @@ test('client.close should not deadlock', (t) => { }) client.close((err) => { - t.error(err) + t.ifError(err) }) clock.tick(100) }) }) + await t.completed }) diff --git a/test/tls-session-reuse.js b/test/tls-session-reuse.js index 0c784456798..c70578bed1f 100644 --- a/test/tls-session-reuse.js +++ b/test/tls-session-reuse.js @@ -1,10 +1,11 @@ 'use strict' +const { tspl } = require('@matteo.collina/tspl') +const { test, after, describe } = require('node:test') const { readFileSync } = require('node:fs') const { join } = require('node:path') const https = require('node:https') const crypto = require('node:crypto') -const { test, teardown } = require('tap') const { Client, Pool } = require('..') const { kSocket } = require('../lib/core/symbols') @@ -14,12 +15,12 @@ const options = { } const ca = readFileSync(join(__dirname, 'fixtures', 'ca.pem'), 'utf8') -test('A client should disable session caching', t => { +describe('A client should disable session caching', () => { const clientSessions = {} let serverRequests = 0 - t.test('Prepare request', t => { - t.plan(3) + test('Prepare request', async t => { + t = tspl(t, { plan: 3 }) const server = https.createServer(options, (req, res) => { if (req.url === '/drop-key') { server.setTicketKeys(crypto.randomBytes(48)) @@ -40,7 +41,7 @@ test('A client should disable session caching', t => { maxCachedSessions: 0 }) - t.teardown(() => { + after(() => { client.close() server.close() }) @@ -64,7 +65,7 @@ test('A client should disable session caching', t => { delete tls.ciphers } client.request(options, (err, data) => { - t.error(err) + t.ifError(err) clientSessions[options.name] = client[kSocket].getSession() data.body.resume().on('end', () => { if (queue.length !== 0) { @@ -76,28 +77,29 @@ test('A client should disable session caching', t => { } request() }) + + await t.completed }) - t.test('Verify cached sessions', t => { - t.plan(2) - t.equal(serverRequests, 2) - t.not( + test('Verify cached sessions', async t => { + t = tspl(t, { plan: 2 }) + t.strictEqual(serverRequests, 2) + t.notEqual( clientSessions.first.toString('hex'), clientSessions.second.toString('hex') ) + await t.completed }) - - t.end() }) -test('A pool should be able to reuse TLS sessions between clients', t => { +describe('A pool should be able to reuse TLS sessions between clients', () => { let serverRequests = 0 const REQ_COUNT = 10 const ASSERT_PERFORMANCE_GAIN = false - t.test('Prepare request', t => { - t.plan(2 + 1 + (ASSERT_PERFORMANCE_GAIN ? 1 : 0)) + test('Prepare request', async t => { + t = tspl(t, { plan: 2 + 1 + (ASSERT_PERFORMANCE_GAIN ? 1 : 0) }) const server = https.createServer(options, (req, res) => { serverRequests++ res.end() @@ -137,7 +139,7 @@ test('A pool should be able to reuse TLS sessions between clients', t => { numSessions++ }) - t.teardown(() => { + after(() => { poolWithSessionReuse.close() poolWithoutSessionReuse.close() server.close() @@ -168,13 +170,11 @@ test('A pool should be able to reuse TLS sessions between clients', t => { await runRequests(poolWithoutSessionReuse, REQ_COUNT, false) await runRequests(poolWithSessionReuse, REQ_COUNT, true) - t.equal(numSessions, 2) - t.equal(serverRequests, 2 + REQ_COUNT * 2) + t.strictEqual(numSessions, 2) + t.strictEqual(serverRequests, 2 + REQ_COUNT * 2) t.ok(true, 'pass') }) - }) - t.end() + await t.completed + }) }) - -teardown(() => process.exit()) From d076328204b591986f5d252c2b338bc4a8812a9a Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Tue, 13 Feb 2024 22:30:03 +0100 Subject: [PATCH 22/23] chore: remove usage of http-errors in proxy example (#2753) --- examples/proxy/proxy.js | 68 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/examples/proxy/proxy.js b/examples/proxy/proxy.js index 6c16a5e70b0..8826bc722ce 100644 --- a/examples/proxy/proxy.js +++ b/examples/proxy/proxy.js @@ -1,6 +1,8 @@ +'use strict' + const net = require('node:net') const { pipeline } = require('node:stream') -const createError = require('http-errors') +const { STATUS_CODES } = require('node:http') module.exports = async function proxy (ctx, client) { const { req, socket, proxyName } = ctx @@ -214,13 +216,13 @@ function getHeaders ({ ].join(';')) } else if (forwarded) { // The forwarded header should not be included in response. - throw new createError.BadGateway() + throw new BadGateway() } if (proxyName) { if (via) { if (via.split(',').some(name => name.endsWith(proxyName))) { - throw new createError.LoopDetected() + throw new LoopDetected() } via += ', ' } @@ -254,3 +256,63 @@ function printIp (address, port) { } return str } + +class BadGateway extends Error { + constructor (message = STATUS_CODES[502]) { + super(message) + } + + toString () { + return `BadGatewayError: ${this.message}` + } + + get name () { + return 'BadGatewayError' + } + + get status () { + return 502 + } + + get statusCode () { + return 502 + } + + get expose () { + return false + } + + get headers () { + return undefined + } +} + +class LoopDetected extends Error { + constructor (message = STATUS_CODES[508]) { + super(message) + } + + toString () { + return `LoopDetectedError: ${this.message}` + } + + get name () { + return 'LoopDetectedError' + } + + get status () { + return 508 + } + + get statusCode () { + return 508 + } + + get expose () { + return false + } + + get headers () { + return undefined + } +} From 64b133cf56a2d5ca772cdb1f919265dcd95af484 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Wed, 14 Feb 2024 07:43:19 +0100 Subject: [PATCH 23/23] fix: dont package wasm files of llhttp with npm (#2752) --- .npmignore | 10 ++++++++++ package.json | 9 --------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.npmignore b/.npmignore index 344e7f65bc9..c55b19ffd15 100644 --- a/.npmignore +++ b/.npmignore @@ -1,2 +1,12 @@ +* +!lib/**/* +!index.js +!index-fetch.js + +# The wasm files are stored as base64 strings in the corresponding .js files lib/llhttp/llhttp_simd.wasm lib/llhttp/llhttp.wasm + +!types/**/* +!index.d.ts +!docs/**/* diff --git a/package.json b/package.json index d03da7e116d..0c42aa0696f 100644 --- a/package.json +++ b/package.json @@ -61,15 +61,6 @@ ], "main": "index.js", "types": "index.d.ts", - "files": [ - "*.d.ts", - "index.js", - "index-fetch.js", - "loader.js", - "lib", - "types", - "docs" - ], "scripts": { "build:node": "npx esbuild@0.19.4 index-fetch.js --bundle --platform=node --outfile=undici-fetch.js --define:esbuildDetection=1 --keep-names && node scripts/strip-comments.js", "prebuild:wasm": "node build/wasm.js --prebuild",