From eddfbf86554394ce080c8c32f14c2acedffa9535 Mon Sep 17 00:00:00 2001 From: Aras Abbasi Date: Tue, 1 Oct 2024 01:05:20 +0200 Subject: [PATCH] fix: mock interceptor should ignore trailing slashes --- lib/mock/mock-utils.js | 7 +++- test/issue-3649.js | 78 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 test/issue-3649.js diff --git a/lib/mock/mock-utils.js b/lib/mock/mock-utils.js index 56be2c8a06e..78f6c0047eb 100644 --- a/lib/mock/mock-utils.js +++ b/lib/mock/mock-utils.js @@ -178,7 +178,12 @@ function deleteMockDispatch (mockDispatches, key) { } function buildKey (opts) { - const { path, method, body, headers, query } = opts + let { path, method, body, headers, query } = opts + + while (path.length > 1 && path.endsWith('/')) { + path = path.slice(0, -1) + } + return { path, method, diff --git a/test/issue-3649.js b/test/issue-3649.js new file mode 100644 index 00000000000..9dd6082e14c --- /dev/null +++ b/test/issue-3649.js @@ -0,0 +1,78 @@ +'use strict' + +const { tspl } = require('@matteo.collina/tspl') +const { describe, test, beforeEach } = require('node:test') +const { MockAgent, fetch, setGlobalDispatcher, getGlobalDispatcher } = require('..') + +describe('https://github.com/nodejs/undici/issues/3649', () => { + const undiciGlobalDispatcher = getGlobalDispatcher() + if (!undiciGlobalDispatcher) throw new Error('Could not find the global Undici dispatcher') + + let mockAgent + + beforeEach(() => { + mockAgent = new MockAgent() + mockAgent.disableNetConnect() + setGlobalDispatcher(mockAgent) + }) + + test('MockAgent should match with or without trailing slash /1', async (t) => { + t = tspl(t, { plan: 1 }) + + mockAgent + .get('https://localhost') + .intercept({ path: '/api/some-path' }).reply(200, { ok: true }) + + const res = await fetch(new URL('/api/some-path', 'https://localhost')) + + t.deepStrictEqual(await res.json(), { ok: true }) + }) + + test('MockAgent should match with or without trailing slash /2', async (t) => { + t = tspl(t, { plan: 1 }) + + mockAgent + .get('https://localhost') + .intercept({ path: '/api/some-path' }).reply(200, { ok: true }) + + const res = await fetch(new URL('/api/some-path/', 'https://localhost')) + + t.deepStrictEqual(await res.json(), { ok: true }) + }) + + test('MockAgent should match with or without trailing slash /3', async (t) => { + t = tspl(t, { plan: 1 }) + + mockAgent + .get('https://localhost') + .intercept({ path: '/api/some-path/' }).reply(200, { ok: true }) + + const res = await fetch(new URL('/api/some-path', 'https://localhost')) + + t.deepStrictEqual(await res.json(), { ok: true }) + }) + + test('MockAgent should match with or without trailing slash /4', async (t) => { + t = tspl(t, { plan: 1 }) + + mockAgent + .get('https://localhost') + .intercept({ path: '/api/some-path/' }).reply(200, { ok: true }) + + const res = await fetch(new URL('/api/some-path/', 'https://localhost')) + + t.deepStrictEqual(await res.json(), { ok: true }) + }) + + test('MockAgent should match with or without trailing slash /5', async (t) => { + t = tspl(t, { plan: 1 }) + + mockAgent + .get('https://localhost') + .intercept({ path: '/api/some-path////' }).reply(200, { ok: true }) + + const res = await fetch(new URL('/api/some-path//', 'https://localhost')) + + t.deepStrictEqual(await res.json(), { ok: true }) + }) +})