Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 80 additions & 56 deletions spec/operators/defaultIfEmpty-spec.ts
Original file line number Diff line number Diff line change
@@ -1,94 +1,119 @@
/** @prettier */
import { expect } from 'chai';
import { hot, cold, expectObservable, expectSubscriptions } from '../helpers/marble-testing';
import { observableMatcher } from '../helpers/observableMatcher';
import { of, Observable } from 'rxjs';
import { defaultIfEmpty, mergeMap, take } from 'rxjs/operators';
import { TestScheduler } from 'rxjs/internal/testing/TestScheduler';

/** @test {defaultIfEmpty} */
describe('Observable.prototype.defaultIfEmpty', () => {
describe('defaultIfEmpty', () => {
let testScheduler: TestScheduler;

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

it('should return the Observable if not empty with a default value', () => {
const e1 = hot('--------|');
const expected = '--------(x|)';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --------|');
const e1subs = ' ^-------!';
const expected = '--------(x|)';

// TODO: Fix `defaultIfEmpty` typings
expectObservable(e1.pipe(defaultIfEmpty(42) as any)).toBe(expected, { x: 42 });
expectObservable(e1.pipe(defaultIfEmpty(42))).toBe(expected, { x: 42 });
expectSubscriptions(e1.subscriptions).toBe(e1subs);
});
});

it('should return the argument if Observable is empty', () => {
const e1 = cold('|');
const e1subs = '(^!)';
const expected = '(x|)';
testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {
const e1 = cold(' |');
const e1subs = ' (^!)';
const expected = '(x|)';

expectObservable(e1.pipe(defaultIfEmpty('x'))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectObservable(e1.pipe(defaultIfEmpty('x'))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
});
});

it('should return null if the Observable is empty and no arguments', () => {
const e1 = cold('|');
const e1subs = '(^!)';
const expected = '(x|)';
testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {
const e1 = cold(' |');
const e1subs = ' (^!)';
const expected = '(x|)';

expectObservable(e1.pipe(defaultIfEmpty())).toBe(expected, { x: null });
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectObservable(e1.pipe(defaultIfEmpty())).toBe(expected, { x: null });
expectSubscriptions(e1.subscriptions).toBe(e1subs);
});
});

it('should return the Observable if not empty with a default value', () => {
const e1 = hot('--a--b--|');
const e1subs = '^ !';
const expected = '--a--b--|';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--b--|');
const e1subs = ' ^-------!';
const expected = '--a--b--|';

expectObservable(e1.pipe(defaultIfEmpty('x'))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectObservable(e1.pipe(defaultIfEmpty('x'))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
});
});

it('should return the Observable if not empty with no default value', () => {
const e1 = hot('--a--b--|');
const e1subs = '^ !';
const expected = '--a--b--|';
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--b--|');
const e1subs = ' ^-------!';
const expected = '--a--b--|';

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

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

const result = e1.pipe(defaultIfEmpty('x'));
const result = e1.pipe(defaultIfEmpty('x'));

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

it('should not break unsubscription chains when unsubscribed explicitly', () => {
const e1 = hot('--a--b--|');
const e1subs = '^ ! ';
const expected = '--a-- ';
const unsub = ' ! ';

const result = e1.pipe(
mergeMap(x => of(x)),
defaultIfEmpty('x'),
mergeMap(x => of(x)),
);

expectObservable(result, unsub).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {
const e1 = hot(' --a--b--|');
const e1subs = ' ^---! ';
const expected = '--a-- ';
const unsub = ' ----! ';

const result = e1.pipe(
mergeMap((x) => of(x)),
defaultIfEmpty('x'),
mergeMap((x) => of(x))
);

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

it('should error if the Observable errors', () => {
const e1 = cold('#');
const e1subs = '(^!)';
const expected = '#';
testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {
const e1 = cold(' #');
const e1subs = ' (^!)';
const expected = '#';

expectObservable(e1.pipe(defaultIfEmpty('x'))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectObservable(e1.pipe(defaultIfEmpty('x'))).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
});
});

it('should stop listening to a synchronous observable when unsubscribed', () => {
const sideEffects: number[] = [];
const synchronousObservable = new Observable(subscriber => {
const synchronousObservable = new Observable((subscriber) => {
// This will check to see if the subscriber was closed on each loop
// when the unsubscribe hits (from the `take`), it should be closed
for (let i = 0; !subscriber.closed && i < 10; i++) {
Expand All @@ -97,10 +122,9 @@ describe('Observable.prototype.defaultIfEmpty', () => {
}
});

synchronousObservable.pipe(
defaultIfEmpty(0),
take(3),
).subscribe(() => { /* noop */ });
synchronousObservable.pipe(defaultIfEmpty(0), take(3)).subscribe(() => {
/* noop */
});

expect(sideEffects).to.deep.equal([0, 1, 2]);
});
Expand Down