Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BREAKING CHANGE: drop support for Node < 18
- Loading branch information
Showing
5 changed files
with
186 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
'use strict' | ||
|
||
const { headersArrayToObject } = require('./common') | ||
|
||
/** | ||
* Creates a Fetch API `Response` instance from the given | ||
* `http.IncomingMessage` instance. | ||
* Inspired by: https://github.com/mswjs/interceptors/blob/04152ed914f8041272b6e92ed374216b8177e1b2/src/interceptors/ClientRequest/utils/createResponse.ts#L8 | ||
*/ | ||
|
||
/** | ||
* Response status codes for responses that cannot have body. | ||
* @see https://fetch.spec.whatwg.org/#statuses | ||
*/ | ||
const responseStatusCodesWithoutBody = [204, 205, 304] | ||
|
||
/** | ||
* @param {IncomingMessage} message | ||
*/ | ||
function createResponse(message) { | ||
const responseBodyOrNull = responseStatusCodesWithoutBody.includes( | ||
message.statusCode, | ||
) | ||
? null | ||
: new ReadableStream({ | ||
start(controller) { | ||
message.on('data', chunk => controller.enqueue(chunk)) | ||
message.on('end', () => controller.close()) | ||
|
||
/** | ||
* @todo Should also listen to the "error" on the message | ||
* and forward it to the controller. Otherwise the stream | ||
* will pend indefinitely. | ||
*/ | ||
}, | ||
}) | ||
|
||
return new Response(responseBodyOrNull, { | ||
status: message.statusCode, | ||
statusText: message.statusMessage, | ||
headers: headersArrayToObject(message.rawHeaders), | ||
}) | ||
} | ||
|
||
module.exports = { createResponse } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
'use strict' | ||
|
||
const { expect } = require('chai') | ||
const nock = require('..') | ||
const assertRejects = require('assert-rejects') | ||
const { startHttpServer } = require('./servers') | ||
|
||
describe('Native Fetch', () => { | ||
it('input is string', async () => { | ||
const scope = nock('http://example.test').get('/').reply() | ||
|
||
const { status } = await fetch('http://example.test/') | ||
expect(status).to.equal(200) | ||
scope.done() | ||
}) | ||
|
||
it('input is URL', async () => { | ||
const scope = nock('http://example.test').get('/').reply() | ||
|
||
const { status } = await fetch(new URL('http://example.test/')) | ||
expect(status).to.equal(200) | ||
scope.done() | ||
}) | ||
|
||
it('input is Request object', async () => { | ||
const scope = nock('http://example.test').get('/').reply() | ||
|
||
const { status } = await fetch(new Request('http://example.test/')) | ||
expect(status).to.equal(200) | ||
scope.done() | ||
}) | ||
|
||
it('filter by body', async () => { | ||
const scope = nock('http://example.test') | ||
.post('/', { test: 'fetch' }) | ||
.reply() | ||
|
||
const { status } = await fetch('http://example.test/', { | ||
method: 'POST', | ||
body: JSON.stringify({ test: 'fetch' }), | ||
}) | ||
expect(status).to.equal(200) | ||
scope.done() | ||
}) | ||
|
||
it('filter by request body', async () => { | ||
const scope = nock('http://example.test') | ||
.post('/', { test: 'fetch' }) | ||
.reply() | ||
|
||
const { status } = await fetch( | ||
new Request('http://example.test/', { | ||
method: 'POST', | ||
body: JSON.stringify({ test: 'fetch' }), | ||
}), | ||
) | ||
expect(status).to.equal(200) | ||
scope.done() | ||
}) | ||
|
||
it('no match', async () => { | ||
nock('http://example.test').get('/').reply() | ||
|
||
await assertRejects( | ||
fetch('http://example.test/wrong-path'), | ||
/Nock: No match for request/, | ||
) | ||
}) | ||
|
||
it('forward request if no mock', async () => { | ||
const { origin } = await startHttpServer((request, response) => { | ||
response.write('live') | ||
response.end() | ||
}) | ||
|
||
const { status } = await fetch(origin) | ||
expect(status).to.equal(200) | ||
}) | ||
|
||
it('should work with empty response', async () => { | ||
nock('http://example.test').get('/').reply(204) | ||
|
||
const { status } = await fetch('http://example.test') | ||
expect(status).to.equal(204) | ||
}) | ||
|
||
it('should work https', async () => { | ||
nock('https://example.test').get('/').reply() | ||
|
||
const { status } = await fetch('https://example.test') | ||
expect(status).to.equal(200) | ||
}) | ||
}) |