From a15aade931f8f147878905be3436d0a08dcd3c52 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 27 May 2026 13:20:23 +0200 Subject: [PATCH] fix(mock): restore single-arg MockCallHistory.filterCallsByX The internal `handleFilterCallsWithOptions` refactor in 8.2.0 added a required `logs` parameter to the helper returned by `makeFilterCalls`, breaking the documented public API: callers using `mockCallHistory.filterCallsByPath('/foo')` hit `Cannot read properties of undefined (reading 'filter')`. Default `logs` to `this.logs` so the external single-argument form works again. The internal callers in `filterCalls` still pass an explicit `logs` argument, so the AND/OR behavior from #5045 is unaffected. Fixes #5324. --- lib/mock/mock-call-history.js | 2 +- test/mock-call-history.js | 135 ++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/lib/mock/mock-call-history.js b/lib/mock/mock-call-history.js index 74de68247c7..d963c3c7427 100644 --- a/lib/mock/mock-call-history.js +++ b/lib/mock/mock-call-history.js @@ -35,7 +35,7 @@ function buildAndValidateFilterCallsOptions (options = {}) { } function makeFilterCalls (parameterName) { - return (parameterValue, logs) => { + return (parameterValue, logs = this.logs) => { if (typeof parameterValue === 'string' || parameterValue == null) { return logs.filter((log) => { return log[parameterName] === parameterValue diff --git a/test/mock-call-history.js b/test/mock-call-history.js index e074ddf3b5f..209a9ba63f4 100644 --- a/test/mock-call-history.js +++ b/test/mock-call-history.js @@ -445,3 +445,138 @@ describe('MockCallHistory - filterCalls with options', () => { t.assert.strictEqual(filtered.length, 2) }) }) + +describe('MockCallHistory - filterCallsByX', () => { + test('filterCallsByProtocol should filter logs with a string', t => { + t.plan(2) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'https://localhost:4000' }) + + const filtered = mockCallHistoryHello.filterCallsByProtocol('https:') + + t.assert.strictEqual(filtered.length, 1) + t.assert.strictEqual(filtered[0]?.path, '/noop') + }) + + test('filterCallsByProtocol should filter logs with a regexp', t => { + t.plan(1) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'https://localhost:4000' }) + + const filtered = mockCallHistoryHello.filterCallsByProtocol(/^https:/) + + t.assert.strictEqual(filtered.length, 1) + }) + + test('filterCallsByHost should filter logs with a string', t => { + t.plan(1) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'http://127.0.0.1:4000' }) + + const filtered = mockCallHistoryHello.filterCallsByHost('127.0.0.1:4000') + + t.assert.strictEqual(filtered.length, 1) + }) + + test('filterCallsByPort should filter logs with a string', t => { + t.plan(1) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:1000' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'http://localhost:4000' }) + + const filtered = mockCallHistoryHello.filterCallsByPort('1000') + + t.assert.strictEqual(filtered.length, 1) + }) + + test('filterCallsByOrigin should filter logs with a regexp', t => { + t.plan(1) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'https://127.0.0.1:4000' }) + + const filtered = mockCallHistoryHello.filterCallsByOrigin(/localhost/) + + t.assert.strictEqual(filtered.length, 1) + }) + + test('filterCallsByPath should filter logs with a string', t => { + t.plan(1) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'http://localhost:4000' }) + + const filtered = mockCallHistoryHello.filterCallsByPath('/noop') + + t.assert.strictEqual(filtered.length, 1) + }) + + test('filterCallsByHash should filter logs with a string', t => { + t.plan(1) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/#hello', origin: 'http://localhost:4000' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'http://localhost:4000' }) + + const filtered = mockCallHistoryHello.filterCallsByHash('#hello') + + t.assert.strictEqual(filtered.length, 1) + }) + + test('filterCallsByFullUrl should filter logs with a string', t => { + t.plan(1) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'http://localhost:4000' }) + + const filtered = mockCallHistoryHello.filterCallsByFullUrl('http://localhost:4000/noop') + + t.assert.strictEqual(filtered.length, 1) + }) + + test('filterCallsByMethod should filter logs with a regexp', t => { + t.plan(1) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000', method: 'POST' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'http://localhost:4000', method: 'GET' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/yes', origin: 'http://localhost:4000', method: 'PUT' }) + + const filtered = mockCallHistoryHello.filterCallsByMethod(/(POST|PUT)/) + + t.assert.strictEqual(filtered.length, 2) + }) + + test('filterCallsByX should reflect logs added after the method was bound', t => { + t.plan(2) + + const mockCallHistoryHello = new MockCallHistory('hello') + + const before = mockCallHistoryHello.filterCallsByPath('/') + t.assert.strictEqual(before.length, 0) + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000' }) + + const after = mockCallHistoryHello.filterCallsByPath('/') + t.assert.strictEqual(after.length, 1) + }) +})