Skip to content

Commit

Permalink
feat: make MockCallHistory iterable
Browse files Browse the repository at this point in the history
  • Loading branch information
blephy committed Jan 29, 2025
1 parent 882af1e commit 200d8dc
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 4 deletions.
11 changes: 11 additions & 0 deletions docs/docs/api/MockCallHistory.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<MockCallHistoryLog> = [...mockAgent.getCallHistory('my-custom-history')]
const set: Set<MockCallHistoryLog> = new Set(mockAgent.getCallHistory('my-custom-history'))
```

## class methods

### clear
Expand Down
6 changes: 6 additions & 0 deletions lib/mock/mock-call-history.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,12 @@ class MockCallHistory {

return log
}

* [Symbol.iterator] () {
for (const log of this.calls()) {
yield log
}
}
}

module.exports.MockCallHistory = MockCallHistory
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
21 changes: 20 additions & 1 deletion test/imports/undici-import.ts
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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<Array<MockCallHistoryLog>>([...mockCallHistory])

for (const log of mockCallHistory) {
expectType<MockCallHistoryLog>(log)
}

// @ts-ignore -- not relevant here
MockCallHistory[kMockCallHistoryDeleteAll]()
}

exampleCode()
checkMockCallHistoryIterator()
36 changes: 34 additions & 2 deletions test/mock-call-history.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand Down Expand Up @@ -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 })
Expand Down Expand Up @@ -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'))
})
})

Expand Down
2 changes: 2 additions & 0 deletions types/mock-call-history.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ declare class MockCallHistory {
filterCallsByMethod (method: MockCallHistory.FilterCallsParameter): Array<MockCallHistoryLog>
/** clear all MockCallHistoryLog on this MockCallHistory. */
clear (): void
/** use it with for..of loop or spread operator */
[Symbol.iterator]: () => Generator<MockCallHistoryLog>
}

export { MockCallHistoryLog, MockCallHistory }

0 comments on commit 200d8dc

Please sign in to comment.