-
Notifications
You must be signed in to change notification settings - Fork 1
/
spyOnObservable.ts
50 lines (46 loc) · 1.52 KB
/
spyOnObservable.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { Observable, Subscription } from 'rxjs'
import { Mock } from 'vitest'
/**
* Utility function for testing observables.
* Returns an object containing mock observer functions.
*
* To ensure your test does not cause a memory leak, assert that `complete`
* has been called; this will verify that this utility has unsubscribed
* from the observable under test. Alternatively, explicitly unsubscribe
* the subscription that is returned.
*
* Example usage:
*
* const { next, error, complete, subscription, latestEmission, emissionCount } =
* spyOnObservable(observableToTest$.pipe(take(1)))
*
* expect(next).toHaveBeenCalledTimes(1)
* expect(next).toHaveBeenCalledWith(someValue)
* expect(latestEmission()).toBe(someValue)
* expect(error).not.toHaveBeenCalled()
* subscription.unsubscribe()
* expect(complete).toHaveBeenCalled()
*/
export function spyOnObservable(observable$: Observable<unknown>) {
const next: Mock<any, any> = vi.fn()
const error: Mock<any, any> = vi.fn()
const complete: Mock<any, any> = vi.fn()
const emissionCount = () => next.mock.calls.length
const latestEmission = () => {
try {
return next.mock.calls.at(-1)![0]
} catch (e) {
throw new Error('expected next to have been called')
}
}
let subscription: Subscription
subscription = observable$.subscribe({
next,
error,
complete: () => {
subscription?.unsubscribe()
complete()
},
})
return { next, error, complete, subscription, latestEmission, emissionCount }
}