jasmine-marbles
Version:
Marble testing helpers for RxJS and Jasmine
130 lines (128 loc) • 4.55 kB
JavaScript
import { Observable, } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { isEqual } from 'lodash';
import { getTestScheduler } from './scheduler';
import { mapSymbolsToNotifications } from './map-symbols-to-notifications';
import { unparseMarble } from './marble-unparser';
/*
* Based on source code found in rxjs library
* https://github.com/ReactiveX/rxjs/blob/master/src/testing/TestScheduler.ts
*
*/
export function materializeInnerObservable(observable, outerFrame) {
const messages = [];
const scheduler = getTestScheduler();
observable.subscribe({
next: (value) => {
messages.push({
frame: scheduler.frame - outerFrame,
notification: {
kind: 'N',
value,
error: undefined,
},
});
},
error: (error) => {
messages.push({
frame: scheduler.frame - outerFrame,
notification: {
kind: 'E',
value: undefined,
error,
},
});
},
complete: () => {
messages.push({
frame: scheduler.frame - outerFrame,
notification: {
kind: 'C',
value: undefined,
error: undefined,
},
});
},
});
return messages;
}
export function toHaveSubscriptionsComparer(actual, marbles) {
const marblesArray = typeof marbles === 'string' ? [marbles] : marbles;
const results = marblesArray.map((marbles) => TestScheduler.parseMarblesAsSubscriptions(marbles));
expect(results).toEqual(actual.getSubscriptions());
return { pass: true, message: () => '' };
}
export function toBeObservableComparer(actual, fixture) {
const results = [];
let subscription;
const scheduler = getTestScheduler();
scheduler.schedule(() => {
subscription = actual.subscribe({
next: (x) => {
let value = x;
// Support Observable-of-Observables
if (x instanceof Observable) {
value = materializeInnerObservable(value, scheduler.frame);
}
results.push({
frame: scheduler.frame,
notification: {
kind: 'N',
value,
error: undefined,
},
});
},
error: (error) => {
results.push({
frame: scheduler.frame,
notification: {
kind: 'E',
value: undefined,
error,
},
});
},
complete: () => {
results.push({
frame: scheduler.frame,
notification: {
kind: 'C',
value: undefined,
error: undefined,
},
});
},
});
});
scheduler.flush();
const expected = TestScheduler.parseMarbles(fixture.marbles, fixture.values, fixture.error, true, true);
try {
expect(results).toEqual(expected);
return { pass: true, message: () => '' };
}
catch (e) {
const mapNotificationToSymbol = buildNotificationToSymbolMapper(fixture.marbles, expected, isEqual);
const receivedMarble = unparseMarble(results, mapNotificationToSymbol);
const message = formatMessage(fixture.marbles, expected, receivedMarble, results);
return { pass: false, message: () => message };
}
}
function buildNotificationToSymbolMapper(expectedMarbles, expectedMessages, equalityFn) {
const symbolsToNotificationsMap = mapSymbolsToNotifications(expectedMarbles, expectedMessages);
return (notification) => {
const mapped = Object.keys(symbolsToNotificationsMap).find((key) => equalityFn(symbolsToNotificationsMap[key], notification));
return mapped || '?';
};
}
function formatMessage(expectedMarbles, expectedMessages, receivedMarbles, receivedMessages) {
return `
Expected: ${expectedMarbles},
Received: ${receivedMarbles},
Expected:
${JSON.stringify(expectedMessages)}
Received:
${JSON.stringify(receivedMessages)},
`;
}
//# sourceMappingURL=utils.js.map