UNPKG

jest-marbles

Version:

Marble testing helpers library for RxJs and Jest

124 lines (102 loc) 3.97 kB
import { ColdObservable } from './src/rxjs/cold-observable'; import { HotObservable } from './src/rxjs/hot-observable'; import { Scheduler } from './src/rxjs/scheduler'; import { stripAlignmentChars } from './src/rxjs/strip-alignment-chars'; import { Observable, Subscription } from 'rxjs'; export type ObservableWithSubscriptions = ColdObservable<any> | HotObservable<any>; export { Scheduler } from './src/rxjs/scheduler'; export { marbleTest } from './src/marble-test'; export { animate } from './src/animate'; declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace jest { interface Matchers<R extends void | Promise<void>> { toBeObservable(observable: ObservableWithSubscriptions): R; toHaveSubscriptions(marbles: string | string[]): R; toHaveNoSubscriptions(): R; toBeMarble(marble: string): R; toSatisfyOnFlush(func: () => void): R; } } } declare module 'expect' { interface Matchers<R extends void | Promise<void>> { toBeObservable(observable: ObservableWithSubscriptions): R; toHaveSubscriptions(marbles: string | string[]): R; toHaveNoSubscriptions(): R; toBeMarble(marble: string): R; toSatisfyOnFlush(func: () => void): R; } } export function hot<T = unknown>(marbles: string, values?: Record<string, T>, error?: any): HotObservable<T> { return new HotObservable<T>(stripAlignmentChars(marbles), values, error); } export function cold<T = unknown>(marbles: string, values?: Record<string, T>, error?: any): ColdObservable<T> { return new ColdObservable<T>(stripAlignmentChars(marbles), values, error); } export function time(marbles: string): number { return Scheduler.get().createTime(stripAlignmentChars(marbles)); } export function schedule(work: () => void, delay: number): Subscription { return Scheduler.get().schedule(work, delay); } const dummyPass = { message: () => '', pass: true, }; const dummyFail = { message: () => '', pass: false, }; expect.extend({ toHaveSubscriptions(actual: ObservableWithSubscriptions, marbles: string | string[]) { const sanitizedMarbles = Array.isArray(marbles) ? marbles.map(stripAlignmentChars) : stripAlignmentChars(marbles); if (this.isNot) { Scheduler.get().expectSubscriptions(actual.getSubscriptions()).toBe(sanitizedMarbles); Scheduler.markLastNegated(); return dummyFail; } Scheduler.get().expectSubscriptions(actual.getSubscriptions()).toBe(sanitizedMarbles); return dummyPass; }, toHaveNoSubscriptions(actual: ObservableWithSubscriptions) { if (this.isNot) { throw new Error('toHaveNoSubscriptions cannot be negated — use toHaveSubscriptions instead'); } Scheduler.get().expectSubscriptions(actual.getSubscriptions()).toBe([]); return dummyPass; }, toBeObservable(actual: Observable<unknown>, expected: ObservableWithSubscriptions) { if (this.isNot) { Scheduler.get().expectObservable(actual).toBe(expected.marbles, expected.values, expected.error); Scheduler.markLastNegated(); return dummyFail; } Scheduler.get().expectObservable(actual).toBe(expected.marbles, expected.values, expected.error); return dummyPass; }, toBeMarble(actual: ObservableWithSubscriptions, marbles: string) { if (this.isNot) { Scheduler.get().expectObservable(actual).toBe(stripAlignmentChars(marbles)); Scheduler.markLastNegated(); return dummyFail; } Scheduler.get().expectObservable(actual).toBe(stripAlignmentChars(marbles)); return dummyPass; }, toSatisfyOnFlush(actual: ObservableWithSubscriptions, func: () => void) { if (this.isNot) { throw new Error('toSatisfyOnFlush cannot be negated'); } Scheduler.get().expectObservable(actual); Scheduler.markLastReady(); Scheduler.queueOnFlush(func); return dummyPass; }, }); beforeEach(() => { Scheduler.init(); }); afterEach(() => { Scheduler.teardown(); });