From fcecfe45175e02330efc9d6b2e11466243da5dea Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Thu, 1 Aug 2024 10:22:21 +0200 Subject: [PATCH 1/2] feat(matchers): add missingHeaders Close #716 --- packages/core/src/Matchers.js | 18 +++++++++++ packages/core/src/Route.js | 1 + .../src/__tests__/Matchers/headers.test.js | 30 +++++++++++++++++++ packages/core/types/Route.d.ts | 1 + 4 files changed, 50 insertions(+) diff --git a/packages/core/src/Matchers.js b/packages/core/src/Matchers.js index d0abd8fcd..5c6cbbc2b 100644 --- a/packages/core/src/Matchers.js +++ b/packages/core/src/Matchers.js @@ -101,6 +101,23 @@ const getHeaderMatcher = ({ headers: expectedHeaders }) => { ); }; }; +/** + * @type {MatcherGenerator} + */ +const getMissingHeaderMatcher = ({ + missingHeaders: expectedMissingHeaders, +}) => { + if (!expectedMissingHeaders) { + return; + } + const expectation = expectedMissingHeaders.map((header) => + header.toLowerCase(), + ); + return ({ options: { headers = {} } }) => { + const lowerCaseHeaders = normalizeHeaders(headers); + return expectation.every((headerName) => !(headerName in lowerCaseHeaders)); + }; +}; /** * @type {MatcherGenerator} */ @@ -306,6 +323,7 @@ export const builtInMatchers = [ { name: 'query', matcher: getQueryParamsMatcher }, { name: 'method', matcher: getMethodMatcher }, { name: 'headers', matcher: getHeaderMatcher }, + { name: 'missingHeaders', matcher: getMissingHeaderMatcher }, { name: 'params', matcher: getExpressParamsMatcher }, { name: 'body', matcher: getBodyMatcher, usesBody: true }, { name: 'matcherFunction', matcher: getFunctionMatcher }, diff --git a/packages/core/src/Route.js b/packages/core/src/Route.js index e24106b9e..92e4ede58 100644 --- a/packages/core/src/Route.js +++ b/packages/core/src/Route.js @@ -15,6 +15,7 @@ import statusTextMap from './StatusTextMap.js'; * @property {RouteName} [name] * @property {string} [method] * @property {{ [key: string]: string | number }} [headers] + * @property {string[]} [missingHeaders] * @property {{ [key: string]: string }} [query] * @property {{ [key: string]: string }} [params] * @property {object} [body] diff --git a/packages/core/src/__tests__/Matchers/headers.test.js b/packages/core/src/__tests__/Matchers/headers.test.js index a49656902..be06eb47d 100644 --- a/packages/core/src/__tests__/Matchers/headers.test.js +++ b/packages/core/src/__tests__/Matchers/headers.test.js @@ -45,6 +45,36 @@ describe('header matching', () => { ).toBe(true); }); + it('match missing headers', () => { + const route = new Route({ + missingHeaders: ['a'], + response: 200, + }); + expect( + route.matcher({ + url: 'http://a.com/', + options: { + headers: { b: 'c' }, + }, + }), + ).toBe(true); + }); + + it('not match present missing header', () => { + const route = new Route({ + missingHeaders: ['a'], + response: 200, + }); + expect( + route.matcher({ + url: 'http://a.com/', + options: { + headers: { a: 'b' }, + }, + }), + ).toBe(false); + }); + it('be case insensitive', () => { const route = new Route({ headers: { a: 'b' }, diff --git a/packages/core/types/Route.d.ts b/packages/core/types/Route.d.ts index 6efdb646a..1873a7029 100644 --- a/packages/core/types/Route.d.ts +++ b/packages/core/types/Route.d.ts @@ -12,6 +12,7 @@ export type UserRouteConfig = { headers?: { [key: string]: string | number; }; + missingHeaders?: string[]; query?: { [key: string]: string; }; From bb7ef68b18057a3f4d3d38bb5d0a842ebd6210c4 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Fri, 2 Aug 2024 16:40:08 +0200 Subject: [PATCH 2/2] test: extra test --- .../core/src/__tests__/Matchers/headers.test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/core/src/__tests__/Matchers/headers.test.js b/packages/core/src/__tests__/Matchers/headers.test.js index be06eb47d..9d6218bd3 100644 --- a/packages/core/src/__tests__/Matchers/headers.test.js +++ b/packages/core/src/__tests__/Matchers/headers.test.js @@ -75,6 +75,20 @@ describe('header matching', () => { ).toBe(false); }); + it('not error when request sent without headers', () => { + const route = new Route({ + missingHeaders: ['a'], + response: 200, + }); + + expect( + route.matcher({ + url: 'http://a.com/', + options: {}, + }), + ).toBe(true); + }); + it('be case insensitive', () => { const route = new Route({ headers: { a: 'b' },