Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(TestScheduler): Add subscription schedule to expectObservable #3997

Merged
merged 1 commit into from Aug 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/marble-testing.md
Expand Up @@ -44,7 +44,7 @@ testScheduler.run(helpers => {

- `hot(marbleDiagram: string, values?: object, error?: any)` - creates a ["hot" observable](https://medium.com/@benlesh/hot-vs-cold-observables-f8094ed53339) (like a subject) that will behave as though it's already "running" when the test begins. An interesting difference is that `hot` marbles allow a `^` character to signal where the "zero frame" is. That is the point at which the subscription to observables being tested begins.
- `cold(marbleDiagram: string, values?: object, error?: any)` - creates a ["cold" observable](https://medium.com/@benlesh/hot-vs-cold-observables-f8094ed53339) whose subscription starts when the test begins.
- `expectObservable(actual: Observable<T>).toBe(marbleDiagram: string, values?: object, error?: any)` - schedules an assertion for when the TestScheduler flushes.
- `expectObservable(actual: Observable<T>).toBe(marbleDiagram: string, values?: object, error?: any)` - schedules an assertion for when the TestScheduler flushes. Give `subscriptionMarbles` as parameter to change the schedule of subscription and unsubscription. If you don't provide the `subscriptionMarbles` parameter it will subscribe at the beginning and never unsubscribe. Read below about subscription marble diagram.
- `expectSubscriptions(actualSubscriptionLogs: SubscriptionLog[]).toBe(subscriptionMarbles: string)` - like `expectObservable` schedules an assertion for when the testScheduler flushes. Both `cold()` and `hot()` return an observable with a property `subscriptions` of type `SubscriptionLog[]`. Give `subscriptions` as parameter to `expectSubscriptions` to assert whether it matches the `subscriptionsMarbles` marble diagram given in `toBe()`. Subscription marble diagrams are slightly different than Observable marble diagrams. Read more below.
- `flush()` - immediately starts virtual time. Not often used since `run()` will automatically flush for you when your callback returns, but in some cases you may wish to flush more than once or otherwise have more control.

Expand Down
7 changes: 7 additions & 0 deletions spec/schedulers/TestScheduler-spec.ts
Expand Up @@ -248,6 +248,13 @@ describe('TestScheduler', () => {
const expected = '--a';
expectObservable(source, unsubscribe).toBe(expected);
});

it('should accept a subscription marble diagram', () => {
const source = hot('-a-b-c|');
const subscribe = '---^';
const expected = '---b-c|';
expectObservable(source, subscribe).toBe(expected);
});
});

describe('expectSubscriptions()', () => {
Expand Down
10 changes: 6 additions & 4 deletions src/internal/testing/TestScheduler.ts
Expand Up @@ -92,11 +92,13 @@ export class TestScheduler extends VirtualTimeScheduler {
}

expectObservable(observable: Observable<any>,
unsubscriptionMarbles: string = null): ({ toBe: observableToBeFn }) {
subscriptionMarbles: string = null): ({ toBe: observableToBeFn }) {
const actual: TestMessage[] = [];
const flushTest: FlushableTest = { actual, ready: false };
const unsubscriptionFrame = TestScheduler
.parseMarblesAsSubscriptions(unsubscriptionMarbles, this.runMode).unsubscribedFrame;
const subscriptionParsed = TestScheduler.parseMarblesAsSubscriptions(subscriptionMarbles, this.runMode);
const subscriptionFrame = subscriptionParsed.subscribedFrame === Number.POSITIVE_INFINITY ?
0 : subscriptionParsed.subscribedFrame;
const unsubscriptionFrame = subscriptionParsed.unsubscribedFrame;
let subscription: Subscription;

this.schedule(() => {
Expand All @@ -112,7 +114,7 @@ export class TestScheduler extends VirtualTimeScheduler {
}, () => {
actual.push({ frame: this.frame, notification: Notification.createComplete() });
});
}, 0);
}, subscriptionFrame);

if (unsubscriptionFrame !== Number.POSITIVE_INFINITY) {
this.schedule(() => subscription.unsubscribe(), unsubscriptionFrame);
Expand Down