Skip to content

Commit 5d69498

Browse files
authored
feat: using test helper (#11)
1 parent 83db97d commit 5d69498

File tree

4 files changed

+45
-12
lines changed

4 files changed

+45
-12
lines changed

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,20 +270,22 @@ await QueueManager.init({
270270
locations: ['./app/jobs/**/*.ts'],
271271
})
272272

273-
const adapter = QueueManager.fake()
273+
// The `using` keyword automatically restores the real adapters when
274+
// the variable goes out of scope (at the end of the test function).
275+
using fake = QueueManager.fake()
274276

275277
await SendEmailJob.dispatch({ to: 'user@example.com' })
276278

277-
adapter.assertPushed(SendEmailJob)
278-
adapter.assertPushed(SendEmailJob, {
279+
fake.assertPushed(SendEmailJob)
280+
fake.assertPushed(SendEmailJob, {
279281
queue: 'default',
280282
payload: (payload) => payload.to === 'user@example.com',
281283
})
282-
adapter.assertPushedCount(1)
283-
284-
QueueManager.restore()
284+
fake.assertPushedCount(1)
285285
```
286286

287+
You can also call `QueueManager.restore()` manually if you need more control over when the real adapters are restored.
288+
287289
### Sync (for testing)
288290

289291
```typescript

src/drivers/fake_adapter.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@ export class FakeAdapter implements Adapter {
7171
#pendingTimeouts = new Set<NodeJS.Timeout>()
7272
#schedules = new Map<string, ScheduleData>()
7373
#pushedJobs: FakeJobRecord[] = []
74+
#onDispose?: () => void
75+
76+
/**
77+
* Set the function to call when the fake is disposed
78+
*/
79+
onDispose(fn: () => void) {
80+
this.#onDispose = fn
81+
return this
82+
}
83+
84+
[Symbol.dispose]() {
85+
this.#onDispose?.()
86+
}
7487

7588
setWorkerId(_workerId: string): void {}
7689

src/queue_manager.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,19 +219,18 @@ class QueueManagerSingleton {
219219
* Replace all adapters with a fake adapter for testing.
220220
*
221221
* The fake adapter records pushed jobs and exposes assertion helpers.
222-
* Call `restore()` to return to the previous configuration.
223-
*
224-
* @returns The fake adapter instance for assertions
225-
* @throws {E_QUEUE_NOT_INITIALIZED} If `init()` hasn't been called
222+
* Use the `using` keyword to automatically restore the previous
223+
* configuration when the variable goes out of scope, or call
224+
* `restore()` manually.
226225
*
227226
* @example
228227
* ```typescript
229-
* const fake = QueueManager.fake()
228+
* using fake = QueueManager.fake()
230229
*
231230
* await SendEmailJob.dispatch({ to: 'user@example.com' })
232231
*
233232
* fake.assertPushed(SendEmailJob)
234-
* QueueManager.restore()
233+
* // Automatically restored at end of scope
235234
* ```
236235
*/
237236
fake(): FakeAdapter {
@@ -244,6 +243,7 @@ class QueueManagerSingleton {
244243
}
245244

246245
const fakeAdapter = new FakeAdapter()
246+
fakeAdapter.onDispose(() => this.restore())
247247

248248
this.#fakeState = {
249249
defaultAdapter: this.#defaultAdapter,

tests/queue_manager.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,24 @@ test.group('QueueManager', () => {
168168
await QueueManager.destroy()
169169
})
170170

171+
test('should restore fake using Symbol.dispose', async ({ assert }) => {
172+
await QueueManager.init({
173+
default: 'sync',
174+
adapters: { sync: sync() },
175+
})
176+
177+
const original = QueueManager.use()
178+
179+
{
180+
using fake = QueueManager.fake()
181+
assert.strictEqual(QueueManager.use(), fake)
182+
}
183+
184+
assert.strictEqual(QueueManager.use(), original)
185+
186+
await QueueManager.destroy()
187+
})
188+
171189
test('should destroy existing adapter instances before reinitializing', async ({
172190
assert,
173191
cleanup,

0 commit comments

Comments
 (0)