From 200d8dc32e08370bda07effc654d602ffe3ef99c Mon Sep 17 00:00:00 2001 From: Blephy Date: Wed, 29 Jan 2025 18:20:18 +0100 Subject: [PATCH] feat: make MockCallHistory iterable --- docs/docs/api/MockCallHistory.md | 11 ++++++++++ lib/mock/mock-call-history.js | 6 ++++++ package.json | 2 +- test/imports/undici-import.ts | 21 ++++++++++++++++++- test/mock-call-history.js | 36 ++++++++++++++++++++++++++++++-- types/mock-call-history.d.ts | 2 ++ 6 files changed, 74 insertions(+), 4 deletions(-) diff --git a/docs/docs/api/MockCallHistory.md b/docs/docs/api/MockCallHistory.md index 9415ee43dd7..0c6c0aae878 100644 --- a/docs/docs/api/MockCallHistory.md +++ b/docs/docs/api/MockCallHistory.md @@ -21,6 +21,17 @@ mockClient mockAgent.getCallHistory('my-custom-history') ``` +a MockCallHistory instance implements a **Symbol.iterator** letting you iterate on registered logs : + +```ts +for (const log of mockAgent.getCallHistory('my-custom-history')) { + //... +} + +const array: Array = [...mockAgent.getCallHistory('my-custom-history')] +const set: Set = new Set(mockAgent.getCallHistory('my-custom-history')) +``` + ## class methods ### clear diff --git a/lib/mock/mock-call-history.js b/lib/mock/mock-call-history.js index c3c3efe8820..2cc4325a621 100644 --- a/lib/mock/mock-call-history.js +++ b/lib/mock/mock-call-history.js @@ -273,6 +273,12 @@ class MockCallHistory { return log } + + * [Symbol.iterator] () { + for (const log of this.calls()) { + yield log + } + } } module.exports.MockCallHistory = MockCallHistory diff --git a/package.json b/package.json index e90a4dbfbf6..4ecfcecd059 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "test:node-test": "borp -p \"test/node-test/**/*.js\"", "test:tdd": "borp --expose-gc -p \"test/*.js\"", "test:tdd:node-test": "borp -p \"test/node-test/**/*.js\" -w", - "test:typescript": "tsd && tsc test/imports/undici-import.ts --typeRoots ./types --noEmit && tsc ./types/*.d.ts --noEmit --typeRoots ./types", + "test:typescript": "tsd && tsc test/imports/undici-import.ts --downlevelIteration --typeRoots ./types --noEmit && tsc ./types/*.d.ts --noEmit --typeRoots ./types", "test:webidl": "borp -p \"test/webidl/*.js\"", "test:websocket": "borp -p \"test/websocket/*.js\"", "test:websocket:autobahn": "node test/autobahn/client.js", diff --git a/test/imports/undici-import.ts b/test/imports/undici-import.ts index 8be95cdd009..f3c12270772 100644 --- a/test/imports/undici-import.ts +++ b/test/imports/undici-import.ts @@ -1,5 +1,6 @@ import { expectType } from 'tsd' -import { Dispatcher, interceptors, request } from '../../' +import { Dispatcher, interceptors, MockCallHistory, MockCallHistoryLog, request } from '../../' +import { kMockCallHistoryAddLog, kMockCallHistoryDeleteAll } from '../../lib/mock/mock-symbols' async function exampleCode () { const retry = interceptors.retry() @@ -13,4 +14,22 @@ async function exampleCode () { await request('http://localhost:3000/foo') } +function checkMockCallHistoryIterator () { + const mockCallHistory = new MockCallHistory('hello') + // @ts-ignore -- not relevant here + mockCallHistory[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000', method: 'GET' }) + // @ts-ignore -- not relevant here + mockCallHistory[kMockCallHistoryAddLog]({ path: '/endpoint', origin: 'http://localhost:4000', method: 'GET' }) + + expectType>([...mockCallHistory]) + + for (const log of mockCallHistory) { + expectType(log) + } + + // @ts-ignore -- not relevant here + MockCallHistory[kMockCallHistoryDeleteAll]() +} + exampleCode() +checkMockCallHistoryIterator() diff --git a/test/mock-call-history.js b/test/mock-call-history.js index 68a8cc1d672..67ff8b8c00b 100644 --- a/test/mock-call-history.js +++ b/test/mock-call-history.js @@ -2,7 +2,7 @@ const { tspl } = require('@matteo.collina/tspl') const { test, describe, after } = require('node:test') -const { MockCallHistory } = require('../lib/mock/mock-call-history') +const { MockCallHistory, MockCallHistoryLog } = require('../lib/mock/mock-call-history') const { kMockCallHistoryDeleteAll, kMockCallHistoryCreate, kMockCallHistoryAddLog, kMockCallHistoryClearAll, kMockCallHistoryAllMockCallHistoryInstances } = require('../lib/mock/mock-symbols') const { InvalidArgumentError } = require('../lib/core/errors') @@ -220,6 +220,38 @@ describe('MockCallHistory - nthCall', () => { }) }) +describe('MockCallHistory - iterator', () => { + test('should permit to iterate over logs with for..of', t => { + t = tspl(t, { plan: 4 }) + after(MockCallHistory[kMockCallHistoryDeleteAll]) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'http://localhost:4000' }) + + for (const log of mockCallHistoryHello) { + t.ok(log instanceof MockCallHistoryLog) + t.ok(typeof log.path === 'string') + } + }) + + test('should permit to iterate over logs with spread operator', t => { + t = tspl(t, { plan: 2 }) + after(MockCallHistory[kMockCallHistoryDeleteAll]) + + const mockCallHistoryHello = new MockCallHistory('hello') + + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000' }) + mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/noop', origin: 'http://localhost:4000' }) + + const logs = [...mockCallHistoryHello] + + t.ok(logs.every((log) => log instanceof MockCallHistoryLog)) + t.strictEqual(logs.length, 2) + }) +}) + describe('MockCallHistory - filterCalls without options', () => { test('should filter logs with a function', t => { t = tspl(t, { plan: 2 }) @@ -406,7 +438,7 @@ describe('MockCallHistory - filterCalls without options', () => { mockCallHistoryHello[kMockCallHistoryAddLog]({ path: '/', origin: 'http://localhost:4000' }) - t.throws(() => mockCallHistoryHello.filterCalls(3), new InvalidArgumentError('criteria parameter should be one of string, function, regexp, or object')) + t.throws(() => mockCallHistoryHello.filterCalls(3), new InvalidArgumentError('criteria parameter should be one of function, regexp, or object')) }) }) diff --git a/types/mock-call-history.d.ts b/types/mock-call-history.d.ts index 7126a181188..9d14e530f70 100644 --- a/types/mock-call-history.d.ts +++ b/types/mock-call-history.d.ts @@ -89,6 +89,8 @@ declare class MockCallHistory { filterCallsByMethod (method: MockCallHistory.FilterCallsParameter): Array /** clear all MockCallHistoryLog on this MockCallHistory. */ clear (): void + /** use it with for..of loop or spread operator */ + [Symbol.iterator]: () => Generator } export { MockCallHistoryLog, MockCallHistory }