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

chore(takeUntil): convert takeUntil tests to run mode #6200

Merged
merged 1 commit into from Apr 3, 2021
Merged
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
324 changes: 183 additions & 141 deletions spec/operators/takeUntil-spec.ts
@@ -1,213 +1,255 @@
import { hot, cold, expectObservable, expectSubscriptions } from '../helpers/marble-testing';
/** @prettier */
import { takeUntil, mergeMap } from 'rxjs/operators';
import { of, EMPTY } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { observableMatcher } from '../helpers/observableMatcher';

/** @test {takeUntil} */
describe('takeUntil operator', () => {
let testScheduler: TestScheduler;

beforeEach(() => {
testScheduler = new TestScheduler(observableMatcher);
});

it('should take values until notifier emits', () => {
const e1 = hot('--a--b--c--d--e--f--g--|');
const e1subs = '^ ! ';
const e2 = hot('-------------z--| ');
const e2subs = '^ ! ';
const expected = '--a--b--c--d-| ';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--b--c--d--e--f--g--|');
const e1subs = ' ^------------! ';
const e2 = hot(' -------------z--| ');
const e2subs = ' ^------------! ';
const expected = '--a--b--c--d-| ';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should take values and raises error when notifier raises error', () => {
const e1 = hot('--a--b--c--d--e--f--g--|');
const e1subs = '^ ! ';
const e2 = hot('-------------# ');
const e2subs = '^ ! ';
const expected = '--a--b--c--d-# ';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--b--c--d--e--f--g--|');
const e1subs = ' ^------------! ';
const e2 = hot(' -------------# ');
const e2subs = ' ^------------! ';
const expected = '--a--b--c--d-# ';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should take all values when notifier is empty', () => {
const e1 = hot('--a--b--c--d--e--f--g--|');
const e1subs = '^ !';
const e2 = hot('-------------| ');
const e2subs = '^ ! ';
const expected = '--a--b--c--d--e--f--g--|';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--b--c--d--e--f--g--|');
const e1subs = ' ^----------------------!';
const e2 = hot(' -------------| ');
const e2subs = ' ^------------! ';
const expected = '--a--b--c--d--e--f--g--|';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should take all values when notifier does not complete', () => {
const e1 = hot('--a--b--c--d--e--f--g--|');
const e1subs = '^ !';
const e2 = hot('-');
const e2subs = '^ !';
const expected = '--a--b--c--d--e--f--g--|';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--b--c--d--e--f--g--|');
const e1subs = ' ^----------------------!';
const e2 = hot(' - ');
const e2subs = ' ^----------------------!';
const expected = '--a--b--c--d--e--f--g--|';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should complete without subscribing to the source when notifier synchronously emits', () => {
const e1 = hot('----a--|');
const e2 = of(1, 2, 3);
const expected = '(|) ';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' ----a--|');
const e2 = of(1, 2, 3);
const expected = '(|) ';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe([]);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe([]);
});
});

it('should subscribe to the source when notifier synchronously completes without emitting', () => {
const e1 = hot('----a--|');
const e1subs = '^ !';
const e2 = EMPTY;
const expected = '----a--|';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' ----a--|');
const e1subs = ' ^------!';
const e2 = EMPTY;
const expected = '----a--|';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
});
});

it('should allow unsubscribing explicitly and early', () => {
const e1 = hot('--a--b--c--d--e--f--g--|');
const e1subs = '^ ! ';
const e2 = hot('-------------z--| ');
const e2subs = '^ ! ';
const unsub = ' ! ';
const expected = '--a--b-- ';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--b--c--d--e--f--g--|');
const e1subs = ' ^------! ';
const e2 = hot(' -------------z--| ');
const e2subs = ' ^------! ';
const unsub = ' -------! ';
const expected = '--a--b-- ';

expectObservable(e1.pipe(takeUntil(e2)), unsub).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2)), unsub).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should complete when notifier emits if source observable does not complete', () => {
const e1 = hot('-');
const e1subs = '^ !';
const e2 = hot('--a--b--|');
const e2subs = '^ !';
const expected = '--|';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' - ');
const e1subs = ' ^-! ';
const e2 = hot(' --a--b--|');
const e2subs = ' ^-! ';
const expected = '--| ';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should raise error when notifier raises error if source observable does not complete', () => {
const e1 = hot('-');
const e1subs = '^ !';
const e2 = hot('--#');
const e2subs = '^ !';
const expected = '--#';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' - ');
const e1subs = ' ^-!';
const e2 = hot(' --#');
const e2subs = ' ^-!';
const expected = '--#';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should not complete when notifier is empty if source observable does not complete', () => {
const e1 = hot('-');
const e1subs = '^';
const e2 = hot('--|');
const e2subs = '^ !';
const expected = '---';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' - ');
const e1subs = ' ^ ';
const e2 = hot(' --|');
const e2subs = ' ^-!';
const expected = '---';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should not complete when source and notifier do not complete', () => {
const e1 = hot('-');
const e1subs = '^';
const e2 = hot('-');
const e2subs = '^';
const expected = '-';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' -');
const e1subs = ' ^';
const e2 = hot(' -');
const e2subs = ' ^';
const expected = '-';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should complete when notifier emits before source observable emits', () => {
const e1 = hot('----a--|');
const e1subs = '^ ! ';
const e2 = hot('--x ');
const e2subs = '^ ! ';
const expected = '--| ';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' ----a--|');
const e1subs = ' ^-! ';
const e2 = hot(' --x ');
const e2subs = ' ^-! ';
const expected = '--| ';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should raise error if source raises error before notifier emits', () => {
const e1 = hot('--a--b--c--d--# ');
const e1subs = '^ ! ';
const e2 = hot('----------------a--|');
const e2subs = '^ ! ';
const expected = '--a--b--c--d--# ';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--b--c--d--# ');
const e1subs = ' ^-------------! ';
const e2 = hot(' ----------------a--|');
const e2subs = ' ^-------------! ';
const expected = '--a--b--c--d--# ';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should raise error immediately if source throws', () => {
const e1 = cold( '#');
const e1subs = '(^!)';
const e2 = hot('--x');
const e2subs = '(^!)';
const expected = '#';
testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {
const e1 = cold(' # ');
const e1subs = ' (^!)';
const e2 = hot(' --x ');
const e2subs = ' (^!)';
const expected = '# ';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should dispose source observable if notifier emits before source emits', () => {
const e1 = hot('---a---|');
const e1subs = '^ ! ';
const e2 = hot('--x-| ');
const e2subs = '^ ! ';
const expected = '--| ';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' ---a---|');
const e1subs = ' ^-! ';
const e2 = hot(' --x-| ');
const e2subs = ' ^-! ';
const expected = '--| ';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should dispose notifier if source observable completes', () => {
const e1 = hot('--a--| ');
const e1subs = '^ ! ';
const e2 = hot('-------x--|');
const e2subs = '^ ! ';
const expected = '--a--| ';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--| ');
const e1subs = ' ^----! ';
const e2 = hot(' -------x--|');
const e2subs = ' ^----! ';
const expected = '--a--| ';

expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});

it('should not break unsubscription chain when unsubscribed explicitly', () => {
const e1 = hot('--a--b--c--d--e--f--g--|');
const e1subs = '^ ! ';
const e2 = hot('-------------z--| ');
const e2subs = '^ ! ';
const unsub = ' ! ';
const expected = '--a--b-- ';

const result = e1.pipe(
mergeMap((x: string) => of(x)),
takeUntil(e2),
mergeMap((x: string) => of(x))
);

expectObservable(result, unsub).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--b--c--d--e--f--g--|');
const e1subs = ' ^------! ';
const e2 = hot(' -------------z--| ');
const e2subs = ' ^------! ';
const unsub = ' -------! ';
const expected = '--a--b-- ';

const result = e1.pipe(
mergeMap((x: string) => of(x)),
takeUntil(e2),
mergeMap((x: string) => of(x))
);

expectObservable(result, unsub).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
});
});