diff --git a/lib/mock/mock-utils.js b/lib/mock/mock-utils.js index 586e6521840..a80ae28f406 100644 --- a/lib/mock/mock-utils.js +++ b/lib/mock/mock-utils.js @@ -386,6 +386,12 @@ function dispatchMockReply (mockDispatches, mockDispatch, key, opts, handler, re paused: false, rawHeaders: null, rawTrailers: null, + // Mirrors the `aborted` property of a real Request, which fetch consults to + // decide whether an error on the current connection was caused by itself + // aborting the connection (e.g. during a redirect) + get aborted () { + return aborted + }, pause () { this.paused = true }, diff --git a/test/fetch/issue-5963.js b/test/fetch/issue-5963.js new file mode 100644 index 00000000000..25dd60e6961 --- /dev/null +++ b/test/fetch/issue-5963.js @@ -0,0 +1,22 @@ +'use strict' + +const { test } = require('node:test') +const { fetch, MockAgent } = require('../..') + +// https://github.com/nodejs/undici/issues/5963 +test('MockAgent follows a redirect', async (t) => { + const mockAgent = new MockAgent() + mockAgent.disableNetConnect() + t.after(() => mockAgent.close()) + + const mockPool = mockAgent.get('http://localhost') + mockPool.intercept({ path: '/redirect', method: 'GET' }) + .reply(307, '', { headers: { location: 'http://localhost/final' } }) + mockPool.intercept({ path: '/final', method: 'GET' }).reply(200, 'ok') + + const response = await fetch('http://localhost/redirect', { dispatcher: mockAgent }) + + t.assert.strictEqual(response.status, 200) + t.assert.strictEqual(await response.text(), 'ok') + t.assert.ok(response.redirected) +})