diff --git a/lib/mock/mock-utils.js b/lib/mock/mock-utils.js index ed7e6c3432f..1912a38fc48 100644 --- a/lib/mock/mock-utils.js +++ b/lib/mock/mock-utils.js @@ -31,6 +31,26 @@ function lowerCaseEntries (headers) { ) } +/** + * @param {import('../../index').Headers|string[]|Record} headers + * @param {string} key + */ +function getHeaderByName (headers, key) { + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (headers[i] === key) { + return headers[i + 1] + } + } + + return undefined + } else if (typeof headers.get === 'function') { + return headers.get(key) + } else { + return headers[key] + } +} + function matchHeaders (mockDispatch, headers) { if (typeof mockDispatch.headers === 'function') { if (Array.isArray(headers)) { // fetch HeadersList @@ -51,9 +71,9 @@ function matchHeaders (mockDispatch, headers) { } for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch.headers)) { - const header = typeof headers.get === 'function' ? headers.get(matchHeaderName) : headers[matchHeaderName] + const headerValue = getHeaderByName(headers, matchHeaderName) - if (!matchValue(matchHeaderValue, header)) { + if (!matchValue(matchHeaderValue, headerValue)) { return false } } @@ -337,5 +357,6 @@ module.exports = { mockDispatch, buildMockDispatch, checkNetConnect, - buildMockOptions + buildMockOptions, + getHeaderByName } diff --git a/test/mock-pool.js b/test/mock-pool.js index f89c3c5cea1..929ebeebb93 100644 --- a/test/mock-pool.js +++ b/test/mock-pool.js @@ -11,6 +11,8 @@ const { MockInterceptor } = require('../lib/mock/mock-interceptor') const { getResponse } = require('../lib/mock/mock-utils') const Dispatcher = require('../lib/dispatcher') +const nodeMajor = Number(process.versions.node.split('.', 1)[0]) + test('MockPool - constructor', t => { t.plan(3) @@ -300,3 +302,48 @@ test('MockPool - basic intercept with MockPool.request', async (t) => { foo: 'bar' }) }) + +test('MockPool - allows matching headers in fetch', { skip: nodeMajor < 16 }, async (t) => { + const { fetch, getGlobalDispatcher, setGlobalDispatcher } = require('../index') + + const oldDispatcher = getGlobalDispatcher() + + const baseUrl = 'http://localhost:9999' + const mockAgent = new MockAgent() + mockAgent.disableNetConnect() + setGlobalDispatcher(mockAgent) + + t.teardown(async () => { + await mockAgent.close() + setGlobalDispatcher(oldDispatcher) + }) + + const pool = mockAgent.get(baseUrl) + pool.intercept({ + path: '/foo', + method: 'GET', + headers: { + accept: 'application/json' + } + }).reply(200, { ok: 1 }).times(3) + + await t.resolves( + 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`), { + headers: { + accept: 'text/plain' + } + }, TypeError) + + t.end() +}) diff --git a/test/mock-utils.js b/test/mock-utils.js index 3e6637e7989..86d69434218 100644 --- a/test/mock-utils.js +++ b/test/mock-utils.js @@ -6,7 +6,8 @@ const { deleteMockDispatch, getMockDispatch, getResponseData, - getStatusText + getStatusText, + getHeaderByName } = require('../lib/mock/mock-utils') test('deleteMockDispatch - should do nothing if not able to find mock dispatch', (t) => { @@ -129,3 +130,30 @@ test('getStatusText', (t) => { t.end() }) + +test('getHeaderByName', (t) => { + const headersRecord = { + key: 'value' + } + + t.equal(getHeaderByName(headersRecord, 'key'), 'value') + t.equal(getHeaderByName(headersRecord, 'anotherKey'), undefined) + + const headersArray = ['key', 'value'] + + t.equal(getHeaderByName(headersArray, 'key'), 'value') + t.equal(getHeaderByName(headersArray, 'anotherKey'), undefined) + + if (Number(process.versions.node.split('.')[0]) >= 16) { + const { Headers } = require('../index') + + const headers = new Headers([ + ['key', 'value'] + ]) + + t.equal(getHeaderByName(headers, 'key'), 'value') + t.equal(getHeaderByName(headers, 'anotherKey'), null) + } + + t.end() +})