From ad8131be9f8342657b02cd826427d3ce87d40fdd Mon Sep 17 00:00:00 2001 From: Mateusz Podlasin Date: Fri, 27 Jul 2018 17:05:15 +1000 Subject: [PATCH 1/3] fix(subscriber): unsubscribe parents on error/complete --- src/internal/Observable.ts | 2 +- src/internal/Subscriber.ts | 21 +++++++++++++++++-- .../observable/dom/WebSocketSubject.ts | 7 +++---- src/internal/testing/ColdObservable.ts | 5 +++-- src/internal/testing/HotObservable.ts | 6 ++++-- 5 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/internal/Observable.ts b/src/internal/Observable.ts index 9f00589303..5f46fa9115 100644 --- a/src/internal/Observable.ts +++ b/src/internal/Observable.ts @@ -198,7 +198,7 @@ export class Observable implements Subscribable { if (operator) { operator.call(sink, this.source); } else { - sink.add( + sink._addParentTeardownLogic( this.source || (config.useDeprecatedSynchronousErrorHandling && !sink.syncErrorThrowable) ? this._subscribe(sink) : this._trySubscribe(sink) diff --git a/src/internal/Subscriber.ts b/src/internal/Subscriber.ts index 6c87098664..11d643faf7 100644 --- a/src/internal/Subscriber.ts +++ b/src/internal/Subscriber.ts @@ -1,6 +1,6 @@ import { isFunction } from './util/isFunction'; import { empty as emptyObserver } from './Observer'; -import { Observer, PartialObserver } from './types'; +import { Observer, PartialObserver, TeardownLogic } from './types'; import { Subscription } from './Subscription'; import { rxSubscriber as rxSubscriberSymbol } from '../internal/symbol/rxSubscriber'; import { config } from './config'; @@ -47,6 +47,8 @@ export class Subscriber extends Subscription implements Observer { protected isStopped: boolean = false; protected destination: PartialObserver; // this `any` is the escape hatch to erase extra type param (e.g. R) + private _parentSubscription: Subscription | null = null; + /** * @param {Observer|function(value: T): void} [destinationOrNext] A partially * defined Observer or a `next` callback function. @@ -76,7 +78,7 @@ export class Subscriber extends Subscription implements Observer { const trustedSubscriber = destinationOrNext[rxSubscriberSymbol]() as Subscriber; this.syncErrorThrowable = trustedSubscriber.syncErrorThrowable; this.destination = trustedSubscriber; - trustedSubscriber.add(this); + trustedSubscriber._addParentTeardownLogic(this); } else { this.syncErrorThrowable = true; this.destination = new SafeSubscriber(this, > destinationOrNext); @@ -114,6 +116,7 @@ export class Subscriber extends Subscription implements Observer { if (!this.isStopped) { this.isStopped = true; this._error(err); + this._unsubscribeParentSubscription(); } } @@ -127,6 +130,7 @@ export class Subscriber extends Subscription implements Observer { if (!this.isStopped) { this.isStopped = true; this._complete(); + this._unsubscribeParentSubscription(); } } @@ -152,6 +156,18 @@ export class Subscriber extends Subscription implements Observer { this.unsubscribe(); } + /** @deprecated This is an internal implementation detail, do not use. */ + _addParentTeardownLogic(parentTeardownLogic: TeardownLogic) { + this._parentSubscription = this.add(parentTeardownLogic); + } + + /** @deprecated This is an internal implementation detail, do not use. */ + _unsubscribeParentSubscription() { + if (this._parentSubscription !== null) { + this._parentSubscription.unsubscribe(); + } + } + /** @deprecated This is an internal implementation detail, do not use. */ _unsubscribeAndRecycle(): Subscriber { const { _parent, _parents } = this; @@ -162,6 +178,7 @@ export class Subscriber extends Subscription implements Observer { this.isStopped = false; this._parent = _parent; this._parents = _parents; + this._parentSubscription = null; return this; } } diff --git a/src/internal/observable/dom/WebSocketSubject.ts b/src/internal/observable/dom/WebSocketSubject.ts index e19e80724d..3e33400c45 100644 --- a/src/internal/observable/dom/WebSocketSubject.ts +++ b/src/internal/observable/dom/WebSocketSubject.ts @@ -276,9 +276,8 @@ export class WebSocketSubject extends AnonymousSubject { if (!this._socket) { this._connectSocket(); } - let subscription = new Subscription(); - subscription.add(this._output.subscribe(subscriber)); - subscription.add(() => { + this._output.subscribe(subscriber); + subscriber.add(() => { const { _socket } = this; if (this._output.observers.length === 0) { if (_socket && _socket.readyState === 1) { @@ -287,7 +286,7 @@ export class WebSocketSubject extends AnonymousSubject { this._resetState(); } }); - return subscription; + return subscriber; } unsubscribe() { diff --git a/src/internal/testing/ColdObservable.ts b/src/internal/testing/ColdObservable.ts index c185c293ab..29f620e288 100644 --- a/src/internal/testing/ColdObservable.ts +++ b/src/internal/testing/ColdObservable.ts @@ -23,11 +23,12 @@ export class ColdObservable extends Observable implements SubscriptionLogg super(function (this: Observable, subscriber: Subscriber) { const observable: ColdObservable = this as any; const index = observable.logSubscribedFrame(); - subscriber.add(new Subscription(() => { + const subscription = new Subscription(); + subscription.add(new Subscription(() => { observable.logUnsubscribedFrame(index); })); observable.scheduleMessages(subscriber); - return subscriber; + return subscription; }); this.scheduler = scheduler; } diff --git a/src/internal/testing/HotObservable.ts b/src/internal/testing/HotObservable.ts index 28a94a4e95..34dcb60256 100644 --- a/src/internal/testing/HotObservable.ts +++ b/src/internal/testing/HotObservable.ts @@ -28,10 +28,12 @@ export class HotObservable extends Subject implements SubscriptionLoggable _subscribe(subscriber: Subscriber): Subscription { const subject: HotObservable = this; const index = subject.logSubscribedFrame(); - subscriber.add(new Subscription(() => { + const subscription = new Subscription(); + subscription.add(new Subscription(() => { subject.logUnsubscribedFrame(index); })); - return super._subscribe(subscriber); + subscription.add(super._subscribe(subscriber)); + return subscription; } setup() { From b416e5c541b786db7653759448c3993671cb243a Mon Sep 17 00:00:00 2001 From: Mateusz Podlasin Date: Fri, 27 Jul 2018 19:12:04 +1000 Subject: [PATCH 2/3] chore(test): update tests for Subscriber changes --- spec/operators/concatMap-spec.ts | 38 ++++++------ spec/operators/concatMapTo-spec.ts | 34 +++++------ spec/operators/delay-spec.ts | 16 ++--- spec/operators/delayWhen-spec.ts | 28 ++++----- spec/operators/exhaustMap-spec.ts | 8 +-- spec/operators/expand-spec.ts | 24 ++++---- spec/operators/mergeAll-spec.ts | 30 ++++----- spec/operators/mergeMap-spec.ts | 48 +++++++-------- spec/operators/mergeMapTo-spec.ts | 78 ++++++++++++------------ spec/operators/mergeScan-spec.ts | 14 ++--- spec/operators/observeOn-spec.ts | 6 +- spec/operators/onErrorResumeNext-spec.ts | 16 ++--- spec/operators/sequenceEqual-spec.ts | 36 +++++------ spec/operators/switchMap-spec.ts | 8 +-- spec/operators/switchMapTo-spec.ts | 22 +++---- spec/operators/zipAll-spec.ts | 8 +-- spec/schedulers/TestScheduler-spec.ts | 2 +- 17 files changed, 209 insertions(+), 207 deletions(-) diff --git a/spec/operators/concatMap-spec.ts b/spec/operators/concatMap-spec.ts index 77d7a275f9..bdbb6cc653 100644 --- a/spec/operators/concatMap-spec.ts +++ b/spec/operators/concatMap-spec.ts @@ -87,7 +87,7 @@ describe('Observable.prototype.concatMap', () => { const d = cold( '------(d|)'); const dsubs = ' ^ ! '; const e1 = hot('a---b--------------------c-d----| '); - const e1subs = '^ ! '; + const e1subs = '^ ! '; const expected = '--a-a-a-a---b--b--b-------c-c-c-----(d|)'; const observableLookup = { a: a, b: b, c: c, d: d }; @@ -104,12 +104,12 @@ describe('Observable.prototype.concatMap', () => { it('should concatMap many outer values to many inner values', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a---b---c---d---| '); - const e1subs = '^ !'; - const inner = cold('--i-j-k-l-| ', values); + const e1subs = '^ ! '; + const inner = cold('--i-j-k-l-| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ ! ', + ' ^ !']; const expected = '---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l-|'; const result = e1.pipe(concatMap((value) => inner)); @@ -166,8 +166,8 @@ describe('Observable.prototype.concatMap', () => { const e1subs = '^ ! '; const inner = cold('|'); const innersubs = [' (^!) ', - ' (^!) ', - ' (^!)']; + ' (^!) ', + ' (^!)']; const expected = '---------| '; const result = e1.pipe(concatMap(() => { return inner; })); @@ -179,7 +179,7 @@ describe('Observable.prototype.concatMap', () => { it('should return a never if the mapped inner is never', () => { const e1 = cold( '--a-b--c-|'); - const e1subs = '^ '; + const e1subs = '^ !'; const inner = cold('-'); const innersubs = ' ^ '; const expected = '----------'; @@ -211,9 +211,9 @@ describe('Observable.prototype.concatMap', () => { const e1subs = '^ !'; const inner = cold('--i-j-k-l-| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ ! ']; + ' ^ ! ', + ' ^ ! ', + ' ^ ! ']; const expected = '---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l--------|'; const result = e1.pipe(concatMap((value) => inner)); @@ -229,9 +229,9 @@ describe('Observable.prototype.concatMap', () => { const e1subs = '^ '; const inner = cold('--i-j-k-l-| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ ! ']; + ' ^ ! ', + ' ^ ! ', + ' ^ ! ']; const expected = '---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l---------'; const result = e1.pipe(concatMap((value) => inner)); @@ -244,7 +244,7 @@ describe('Observable.prototype.concatMap', () => { it('should concatMap many outer to many inner, inner never completes', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a---b---c---d---|'); - const e1subs = '^ '; + const e1subs = '^ !'; const inner = cold('--i-j-k-l- ', values); const innersubs = ' ^ '; const expected = '---i-j-k-l--------'; @@ -277,7 +277,7 @@ describe('Observable.prototype.concatMap', () => { const e1subs = '^ !'; const inner = cold('--i-j-k-l-| ', values); const innersubs = [' ^ ! ', - ' ^ !']; + ' ^ !']; const expected = '---i-j-k-l---i-j-#'; const result = e1.pipe(concatMap((value) => inner)); @@ -318,7 +318,7 @@ describe('Observable.prototype.concatMap', () => { const g = cold( '---1-2|'); const gsubs = ' ^ !'; const e1 = hot('-a-b--^-c-----d------e----------------f-----g| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '---2--3--4--5----6-----2--3-1------2--3-4-5--------1-2|'; const observableLookup = { a: a, b: b, c: c, d: d, e: e, f: f, g: g }; @@ -351,7 +351,7 @@ describe('Observable.prototype.concatMap', () => { const g = cold( '---1-2|'); const gsubs: string[] = []; const e1 = hot('-a-b--^-c-----d------e----------------f-----g| '); - const e1subs = '^ '; + const e1subs = '^ ! ' ; const expected = '---2--3--4--5----6-----2--3----------------------------'; const observableLookup = { a: a, b: b, c: c, d: d, e: e, f: f, g: g }; diff --git a/spec/operators/concatMapTo-spec.ts b/spec/operators/concatMapTo-spec.ts index 4b15044d1c..04b8d02223 100644 --- a/spec/operators/concatMapTo-spec.ts +++ b/spec/operators/concatMapTo-spec.ts @@ -80,12 +80,12 @@ describe('Observable.prototype.concatMapTo', () => { it('should concatMapTo many outer values to many inner values', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a---b---c---d---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const inner = cold('--i-j-k-l-| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ ! ', + ' ^ !']; const expected = '---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l-|'; const result = e1.pipe(concatMapTo(inner)); @@ -142,8 +142,8 @@ describe('Observable.prototype.concatMapTo', () => { const e1subs = '^ !'; const inner = cold('|'); const innersubs = [' (^!) ', - ' (^!) ', - ' (^!)']; + ' (^!) ', + ' (^!)']; const expected = '---------|'; const result = e1.pipe(concatMapTo(inner)); @@ -155,7 +155,7 @@ describe('Observable.prototype.concatMapTo', () => { it('should return a never if the mapped inner is never', () => { const e1 = cold('--a-b--c-|'); - const e1subs = '^ '; + const e1subs = '^ !'; const inner = cold('-'); const innersubs = ' ^ '; const expected = '----------'; @@ -187,9 +187,9 @@ describe('Observable.prototype.concatMapTo', () => { const e1subs = '^ !'; const inner = cold('--i-j-k-l-| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ ! ']; + ' ^ ! ', + ' ^ ! ', + ' ^ ! ']; const expected = '---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l--------|'; const result = e1.pipe(concatMapTo(inner)); @@ -205,9 +205,9 @@ describe('Observable.prototype.concatMapTo', () => { const e1subs = '^ '; const inner = cold('--i-j-k-l-| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ ! ']; + ' ^ ! ', + ' ^ ! ', + ' ^ ! ']; const expected = '---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l---------'; const result = e1.pipe(concatMapTo(inner)); @@ -220,10 +220,10 @@ describe('Observable.prototype.concatMapTo', () => { it('should not break unsubscription chains when result is unsubscribed explicitly', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a---b---c---d---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const inner = cold('--i-j-k-l-| ', values); const innersubs = [' ^ ! ', - ' ^ !']; + ' ^ !']; const expected = '---i-j-k-l---i-j-k-'; const unsub = ' !'; @@ -241,7 +241,7 @@ describe('Observable.prototype.concatMapTo', () => { it('should concatMapTo many outer to many inner, inner never completes', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a---b---c---d---|'); - const e1subs = '^ '; + const e1subs = '^ !'; const inner = cold('--i-j-k-l- ', values); const innersubs = ' ^ '; const expected = '---i-j-k-l--------'; @@ -274,7 +274,7 @@ describe('Observable.prototype.concatMapTo', () => { const e1subs = '^ !'; const inner = cold('--i-j-k-l-| ', values); const innersubs = [' ^ ! ', - ' ^ !']; + ' ^ !']; const expected = '---i-j-k-l---i-j-#'; const result = e1.pipe(concatMapTo(inner)); diff --git a/spec/operators/delay-spec.ts b/spec/operators/delay-spec.ts index 67364c7251..66965ccc35 100644 --- a/spec/operators/delay-spec.ts +++ b/spec/operators/delay-spec.ts @@ -14,7 +14,7 @@ describe('delay operator', () => { const e1 = hot('---a--b--| '); const t = time( '--| '); const expected = '-----a--b--|'; - const subs = '^ !'; + const subs = '^ ! '; const result = e1.pipe(delay(t, rxTestScheduler)); @@ -23,10 +23,10 @@ describe('delay operator', () => { }); it('should delay by absolute time period', () => { - const e1 = hot('--a--b--| '); - const t = time( '---| '); + const e1 = hot('--a--b--| '); + const t = time( '---| '); const expected = '-----a--b--|'; - const subs = '^ !'; + const subs = '^ ! '; const absoluteDelay = new Date(rxTestScheduler.now() + t); const result = e1.pipe(delay(absoluteDelay, rxTestScheduler)); @@ -36,10 +36,10 @@ describe('delay operator', () => { }); it('should delay by absolute time period after subscription', () => { - const e1 = hot('---^--a--b--| '); - const t = time( '---| '); + const e1 = hot('---^--a--b--| '); + const t = time( '---| '); const expected = '------a--b--|'; - const subs = '^ !'; + const subs = '^ ! '; const absoluteDelay = new Date(rxTestScheduler.now() + t); const result = e1.pipe(delay(absoluteDelay, rxTestScheduler)); @@ -90,7 +90,7 @@ describe('delay operator', () => { const e1 = hot('----| '); const t = time( '---|'); const expected = '-------|'; - const subs = '^ !'; + const subs = '^ ! '; const result = e1.pipe(delay(t, rxTestScheduler)); diff --git a/spec/operators/delayWhen-spec.ts b/spec/operators/delayWhen-spec.ts index 9c3978d713..4426acc632 100644 --- a/spec/operators/delayWhen-spec.ts +++ b/spec/operators/delayWhen-spec.ts @@ -13,7 +13,7 @@ describe('delayWhen operator', () => { asDiagram('delayWhen(durationSelector)')('should delay by duration selector', () => { const e1 = hot('---a---b---c--|'); const expected = '-----a------c----(b|)'; - const subs = '^ !'; + const subs = '^ !'; const selector = [cold( '--x--|'), cold( '----------(x|)'), cold( '-x--|')]; @@ -41,7 +41,7 @@ describe('delayWhen operator', () => { const subs = '^ !'; const selector = cold( '-x--|'); const selectorSubs = [' ^! ', - ' ^! ']; + ' ^! ']; const result = e1.pipe(delayWhen((x: any) => selector)); @@ -81,10 +81,10 @@ describe('delayWhen operator', () => { it('should delay by selector and completes after value emits', () => { const e1 = hot('--a--b--|'); const expected = '---------a--(b|)'; - const subs = '^ !'; + const subs = '^ !'; const selector = cold('-------x--|'); const selectorSubs = [' ^ !', - ' ^ !']; + ' ^ !']; const result = e1.pipe(delayWhen((x: any) => selector)); @@ -96,10 +96,10 @@ describe('delayWhen operator', () => { it('should delay by selector completes if selector does not emits', () => { const e1 = hot('--a--b--|'); const expected = '------a--(b|)'; - const subs = '^ !'; + const subs = '^ !'; const selector = cold( '----|'); const selectorSubs = [' ^ !', - ' ^ !']; + ' ^ !']; const result = e1.pipe(delayWhen((x: any) => selector)); @@ -133,10 +133,10 @@ describe('delayWhen operator', () => { it('should not emit if selector never emits', () => { const e1 = hot('--a--b--|'); const expected = '-'; - const subs = '^ '; + const subs = '^ !'; const selector = cold( '-'); - const selectorSubs = [' ^ ', - ' ^ ']; + const selectorSubs = [' ^ ', + ' ^ ']; const result = e1.pipe(delayWhen((x: any) => selector)); @@ -148,10 +148,10 @@ describe('delayWhen operator', () => { it('should delay by first value from selector', () => { const e1 = hot('--a--b--|'); const expected = '------a--(b|)'; - const subs = '^ !'; + const subs = '^ !'; const selector = cold( '----x--y--|'); const selectorSubs = [' ^ !', - ' ^ !']; + ' ^ !']; const result = e1.pipe(delayWhen((x: any) => selector)); @@ -163,10 +163,10 @@ describe('delayWhen operator', () => { it('should delay by selector does not completes', () => { const e1 = hot('--a--b--|'); const expected = '------a--(b|)'; - const subs = '^ !'; + const subs = '^ !'; const selector = cold( '----x-----y---'); const selectorSubs = [' ^ !', - ' ^ !']; + ' ^ !']; const result = e1.pipe(delayWhen((x: any) => selector)); @@ -211,7 +211,7 @@ describe('delayWhen operator', () => { const subs = ' ^ !'; const selector = cold( '--x--|'); const selectorSubs = [' ^ !', - ' ^ !']; + ' ^ !']; const subDelay = cold('--|'); const subDelaySub = '^ !'; diff --git a/spec/operators/exhaustMap-spec.ts b/spec/operators/exhaustMap-spec.ts index f6a649be93..ee588e92c2 100644 --- a/spec/operators/exhaustMap-spec.ts +++ b/spec/operators/exhaustMap-spec.ts @@ -210,7 +210,7 @@ describe('exhaustMap', () => { const z = cold( '--g--h--i-----'); const zsubs = ' ^ '; const e1 = hot('---x---------y-----------------z---------| '); - const e1subs = '^ '; + const e1subs = '^ ! '; const expected = '-----a--b--c---------------------g--h--i-----'; const observableLookup = { x: x, y: y, z: z }; @@ -270,7 +270,7 @@ describe('exhaustMap', () => { const z = hot('---z-o-o-m-------------j---k---l---m--|'); const zsubs = ' ^ !'; const e1 = hot('---------x----y-----z--------| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '-----------c--d--e-----j---k---l---m--|'; const observableLookup = { x: x, y: y, z: z }; @@ -309,7 +309,7 @@ describe('exhaustMap', () => { const xsubs = ' (^!) '; const ysubs = ' ^ '; const e1 = hot('---------x---------y---------|'); - const e1subs = '^ '; + const e1subs = '^ !'; const expected = '------------------------------'; const observableLookup = { x: x, y: y }; @@ -328,7 +328,7 @@ describe('exhaustMap', () => { const xsubs = ' ^ '; const ysubs: string[] = []; const e1 = hot('---------x---------y----------|'); - const e1subs = '^ '; + const e1subs = '^ !'; const expected = '-------------------------------'; const observableLookup = { x: x, y: y }; diff --git a/spec/operators/expand-spec.ts b/spec/operators/expand-spec.ts index 6b157655ea..1d0d38b42c 100644 --- a/spec/operators/expand-spec.ts +++ b/spec/operators/expand-spec.ts @@ -14,7 +14,7 @@ describe('expand operator', () => { asDiagram('expand(x => x === 8 ? empty : \u2014\u20142*x\u2014| )') ('should recursively map-and-flatten each item to an Observable', () => { const e1 = hot('--x----| ', {x: 1}); - const e1subs = '^ !'; + const e1subs = '^ ! '; const e2 = cold( '--c| ', {c: 2}); const expected = '--a-b-c-d|'; const values = {a: 1, b: 2, c: 4, d: 8}; @@ -27,7 +27,7 @@ describe('expand operator', () => { it('should work with scheduler', () => { const e1 = hot('--x----| ', {x: 1}); - const e1subs = '^ !'; + const e1subs = '^ ! '; const e2 = cold( '--c| ', {c: 2}); const expected = '--a-b-c-d|'; const values = {a: 1, b: 2, c: 4, d: 8}; @@ -47,7 +47,7 @@ describe('expand operator', () => { e: 8 + 8, // d + d }; const e1 = hot('(a|)', values); - const e1subs = '^ ! '; + const e1subs = '(^!) '; const e2shape = '---(z|) '; const expected = 'a--b--c--d--(e|)'; /* @@ -86,7 +86,7 @@ describe('expand operator', () => { e: 8 + 8, // d + d }; const e1 = hot('(a|)', values); - const e1subs = '^ ! '; + const e1subs = '(^!) '; const e2shape = '---(z|) '; const expected = 'a--b--c--(d#)'; @@ -110,7 +110,7 @@ describe('expand operator', () => { e: 8 + 8, // d + d }; const e1 = hot('(a|)', values); - const e1subs = '^ ! '; + const e1subs = '(^!) '; const e2shape = '---(z|) '; const expected = 'a--b--c--(d#)'; @@ -135,7 +135,7 @@ describe('expand operator', () => { }; const e1 = hot('(a|)', values); const unsub = ' ! '; - const e1subs = '^ ! '; + const e1subs = '(^!) '; const e2shape = '---(z|) '; const expected = 'a--b--c- '; @@ -159,7 +159,7 @@ describe('expand operator', () => { e: 8 + 8, // d + d }; const e1 = hot('(a|)', values); - const e1subs = '^ ! '; + const e1subs = '(^!) '; const e2shape = '---(z|) '; const expected = 'a--b--c- '; const unsub = ' ! '; @@ -188,7 +188,7 @@ describe('expand operator', () => { e: 8 + 8, // d + d }; const e1 = hot('a-a| ', values); - const e1subs = '^ ! '; + const e1subs = '^ ! '; const e2shape = '---(z|) '; const expected = 'a-ab-bc-cd-de-(e|)'; @@ -226,7 +226,7 @@ describe('expand operator', () => { // ---(z|) // ---(z|) // Notice how for each column, there is at most 1 `-` character. - const e1subs = '^ ! '; + const e1subs = '^ ! '; const expected = 'a--u--b--v--c--x--d--y--(ez|)'; const concurrencyLimit = 1; @@ -259,7 +259,7 @@ describe('expand operator', () => { // ------(z|) // ------(z|) // Notice how for each column, there is at most 2 `-` characters. - const e1subs = '^ ! '; + const e1subs = '^ ! '; const expected = 'a---a-u---b-b---v-(cc)(x|)'; const concurrencyLimit = 2; @@ -288,7 +288,7 @@ describe('expand operator', () => { z: 160, // y + y }; const e1 = hot('a-u| ', values); - const e1subs = '^ ! '; + const e1subs = '^ ! '; const e2shape = '---(z|) '; const expected = 'a-ub-vc-xd-ye-(z|)'; const concurrencyLimit = 100; @@ -400,7 +400,7 @@ describe('expand operator', () => { e: 8 + 8, // d + d }; const e1 = hot('(a|)', values); - const e1subs = '^ ! '; + const e1subs = '(^!) '; const e2shape = '---(z|) '; const expected = 'a--b--c--d--(e|)'; diff --git a/spec/operators/mergeAll-spec.ts b/spec/operators/mergeAll-spec.ts index ca28f8e846..2b37645ac5 100644 --- a/spec/operators/mergeAll-spec.ts +++ b/spec/operators/mergeAll-spec.ts @@ -45,7 +45,7 @@ describe('mergeAll oeprator', () => { const y = cold( 'd---e---f---|'); const ysubs = ' ^ !'; const e1 = hot('--x--y--| ', { x: x, y: y }); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '--a--db--ec--f---|'; expectObservable(e1.pipe(mergeAll())).toBe(expected); @@ -60,7 +60,7 @@ describe('mergeAll oeprator', () => { const y = cold( 'd---e---f---|'); const ysubs = ' ^ !'; const e1 = hot('--x--y--| ', { x: x, y: y }); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '--a---b---c---d---e---f---|'; expectObservable(e1.pipe(mergeAll(1))).toBe(expected); @@ -77,7 +77,7 @@ describe('mergeAll oeprator', () => { const z = cold( '--g---h-|'); const zsubs = ' ^ !'; const e1 = hot('--x--y--z--| ', { x: x, y: y, z: z }); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '--a--db--ec--f--g---h-|'; expectObservable(e1.pipe(mergeAll(2))).toBe(expected); @@ -93,7 +93,7 @@ describe('mergeAll oeprator', () => { const y = hot('-------------d---e---f---|'); const ysubs = ' ^ !'; const e1 = hot('--x--y--| ', { x: x, y: y }); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '---a---b---c-----e---f---|'; expectObservable(e1.pipe(mergeAll(1))).toBe(expected); @@ -110,7 +110,7 @@ describe('mergeAll oeprator', () => { const z = hot('--i--i--i--i-----g---h-|'); const zsubs = ' ^ !'; const e1 = hot('--x--y--z--| ', { x: x, y: y, z: z }); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '---a--db--ec--f--g---h-|'; expectObservable(e1.pipe(mergeAll(2))).toBe(expected); @@ -126,7 +126,7 @@ describe('mergeAll oeprator', () => { const y = cold( 'd---e---f---|'); const ysubs = ' ^ ! '; const e1 = hot('--x--y--| ', { x: x, y: y }); - const e1subs = '^ ! '; + const e1subs = '^ ! '; const unsub = ' ! '; const expected = '--a--db--ec-- '; @@ -142,7 +142,7 @@ describe('mergeAll oeprator', () => { const y = cold( 'd---e---f---|'); const ysubs = ' ^ ! '; const e1 = hot('--x--y--| ', { x: x, y: y }); - const e1subs = '^ ! '; + const e1subs = '^ ! '; const expected = '--a--db--ec-- '; const unsub = ' ! '; @@ -164,7 +164,7 @@ describe('mergeAll oeprator', () => { const y = cold( '-d----e----f---|'); const ysubs = ' ^ !'; const e1 = hot('--x--y--| ', { x: x, y: y }); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '------(ad)-(be)-(cf)|'; expectObservable(e1.pipe(mergeAll())).toBe(expected); @@ -212,7 +212,7 @@ describe('mergeAll oeprator', () => { const y = cold( '|'); const ysubs = ' (^!)'; const e1 = hot('--x--y--|', { x: x, y: y }); - const e1subs = '^ '; + const e1subs = '^ !'; const expected = '---------'; expectObservable(e1.pipe(mergeAll())).toBe(expected); @@ -227,7 +227,7 @@ describe('mergeAll oeprator', () => { const y = cold( '-'); const ysubs = ' ^'; const e1 = hot('--x--y--|', { x: x, y: y }); - const e1subs = '^ '; + const e1subs = '^ !'; const expected = '---------'; expectObservable(e1.pipe(mergeAll())).toBe(expected); @@ -271,8 +271,8 @@ describe('mergeAll oeprator', () => { const xsubs = ' (^!)'; const y = cold( '------#'); const ysubs = ' ^ !'; - const e1 = hot('--x--y--|', { x: x, y: y }); - const e1subs = '^ !'; + const e1 = hot('--x--y--| ', { x: x, y: y }); + const e1subs = '^ ! '; const expected = '-----------#'; expectObservable(e1.pipe(mergeAll())).toBe(expected); @@ -286,8 +286,8 @@ describe('mergeAll oeprator', () => { const xsubs = ' ^ !'; const y = cold( '------#'); const ysubs = ' ^ !'; - const e1 = hot('--x--y--|', { x: x, y: y }); - const e1subs = '^ !'; + const e1 = hot('--x--y--| ', { x: x, y: y }); + const e1subs = '^ ! '; const expected = '-----------#'; expectObservable(e1.pipe(mergeAll())).toBe(expected); @@ -331,7 +331,7 @@ describe('mergeAll oeprator', () => { const z = cold( 'g-h-i-j-k-|'); const zsubs = ' ^ !'; const e1 = hot('--x---------y--------z--------| ', { x: x, y: y, z: z }); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '--a-b-------c-d-e-f--g-h-i-j-k-|'; expectObservable(e1.pipe(mergeAll())).toBe(expected); diff --git a/spec/operators/mergeMap-spec.ts b/spec/operators/mergeMap-spec.ts index f6ca593ccb..10e3472a6d 100644 --- a/spec/operators/mergeMap-spec.ts +++ b/spec/operators/mergeMap-spec.ts @@ -109,7 +109,7 @@ describe('mergeMap', () => { const c = cold( '----c---c---c---c---(c|)'); const d = cold( '----(d|) '); const e1 = hot('a---b-----------c-------d-------| '); - const e1subs = '^ ! '; + const e1subs = '^ ! '; const expected = '----a---(ab)(ab)(ab)c---c---(cd)c---(c|)'; const observableLookup = { a: a, b: b, c: c, d: d }; @@ -198,12 +198,12 @@ describe('mergeMap', () => { it('should mergeMap many outer values to many inner values', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c-------d-------| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const inner = cold('----i---j---k---l---| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ ! ', + ' ^ !']; const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l---|'; const result = e1.pipe(mergeMap((value) => inner)); @@ -261,7 +261,7 @@ describe('mergeMap', () => { it('should mergeMap many outer to many inner, inner never completes', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c-------d-------| '); - const e1subs = '^ '; + const e1subs = '^ ! '; const inner = cold('----i---j---k---l-------------------------', values); const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l-'; @@ -313,11 +313,11 @@ describe('mergeMap', () => { it('should mergeMap to many cold Observable, with parameter concurrency=1', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const inner = cold('----i---j---k---l---| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ !']; const expected = '-----i---j---k---l-------i---j---k---l-------i---j---k---l---|'; function project() { return inner; } @@ -331,11 +331,11 @@ describe('mergeMap', () => { it('should mergeMap to many cold Observable, with parameter concurrency=2', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const inner = cold('----i---j---k---l---| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ !']; const expected = '-----i---j---(ki)(lj)k---(li)j---k---l---|'; function project() { return inner; } @@ -349,7 +349,7 @@ describe('mergeMap', () => { it('should mergeMap to many hot Observable, with parameter concurrency=1', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const hotA = hot('x----i---j---k---l---| ', values); const hotB = hot('-x-x-xxxx-x-x-xxxxx-x----i---j---k---l---| ', values); const hotC = hot('x-xxxx---x-x-x-x-x-xx--x--x-x--x--xxxx-x-----i---j---k---l---|', values); @@ -372,7 +372,7 @@ describe('mergeMap', () => { it('should mergeMap to many hot Observable, with parameter concurrency=2', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const hotA = hot('x----i---j---k---l---| ', values); const hotB = hot('-x-x-xxxx----i---j---k---l---| ', values); const hotC = hot('x-xxxx---x-x-x-x-x-xx----i---j---k---l---|', values); @@ -395,11 +395,11 @@ describe('mergeMap', () => { it('should mergeMap to many cold Observable, with parameter concurrency=1', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const inner = cold('----i---j---k---l---| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ !']; const expected = '-----i---j---k---l-------i---j---k---l-------i---j---k---l---|'; function project() { return inner; } @@ -413,11 +413,11 @@ describe('mergeMap', () => { it('should mergeMap to many cold Observable, with parameter concurrency=2', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const inner = cold('----i---j---k---l---| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ !']; const expected = '-----i---j---(ki)(lj)k---(li)j---k---l---|'; function project() { return inner; } @@ -431,7 +431,7 @@ describe('mergeMap', () => { it('should mergeMap to many hot Observable, with parameter concurrency=1', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const hotA = hot('x----i---j---k---l---| ', values); const hotB = hot('-x-x-xxxx-x-x-xxxxx-x----i---j---k---l---| ', values); const hotC = hot('x-xxxx---x-x-x-x-x-xx--x--x-x--x--xxxx-x-----i---j---k---l---|', values); @@ -454,7 +454,7 @@ describe('mergeMap', () => { it('should mergeMap to many hot Observable, with parameter concurrency=2', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const hotA = hot('x----i---j---k---l---| ', values); const hotB = hot('-x-x-xxxx----i---j---k---l---| ', values); const hotC = hot('x-xxxx---x-x-x-x-x-xx----i---j---k---l---|', values); @@ -483,7 +483,7 @@ describe('mergeMap', () => { const f = cold( '--|' ); const g = cold( '---1-2|' ); const e1 = hot('-a-b--^-c-----d------e----------------f-----g|' ); - const e1subs = '^ !'; + const e1subs = '^ !'; const expected = '---2--3--4--5---1--2--3--2--3--6--4--5---1-2--|'; const observableLookup = { a: a, b: b, c: c, d: d, e: e, f: f, g: g }; @@ -503,7 +503,7 @@ describe('mergeMap', () => { const f = cold( '--|' ); const g = cold( '---1-2|' ); const e1 = hot('-a-b--^-c-----d------e----------------f-----g|' ); - const e1subs = '^ '; + const e1subs = '^ !'; const expected = '---2--3--4--5---1--2--3--2--3--6--4--5---1-2----'; const observableLookup = { a: a, b: b, c: c, d: d, e: e, f: f, g: g }; diff --git a/spec/operators/mergeMapTo-spec.ts b/spec/operators/mergeMapTo-spec.ts index 874fc8093e..555e553054 100644 --- a/spec/operators/mergeMapTo-spec.ts +++ b/spec/operators/mergeMapTo-spec.ts @@ -82,13 +82,13 @@ describe('mergeMapTo', () => { const x = cold('----1---2---3---(4|) '); const xsubs = ['^ ! ', // ----1---2---3---(4|) - ' ^ ! ', + ' ^ ! ', // ----1---2---3---(4|) - ' ^ ! ', + ' ^ ! ', // ----1---2---3---(4|) - ' ^ ! ']; + ' ^ ! ']; const e1 = hot('a---b-----------c-------d-------| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '----1---(21)(32)(43)(41)2---(31)(42)3---(4|)'; const source = e1.pipe(mergeMapTo(x)); @@ -134,12 +134,12 @@ describe('mergeMapTo', () => { it('should mergeMapTo many outer values to many inner values', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c-------d-------| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const inner = cold('----i---j---k---l---| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ ! ', + ' ^ !']; const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l---|'; expectObservable(e1.pipe(mergeMapTo(inner))).toBe(expected, values); @@ -153,9 +153,9 @@ describe('mergeMapTo', () => { const e1subs = '^ !'; const inner = cold('----i---j---k---l---|', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ ! ']; + ' ^ ! ', + ' ^ ! ', + ' ^ ! ']; const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l-------|'; expectObservable(e1.pipe(mergeMapTo(inner))).toBe(expected, values); @@ -169,11 +169,11 @@ describe('mergeMapTo', () => { const e1subs = '^ !'; const inner = cold( '----i---j---k---l---|', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ ! ', + ' ^ ! ', + ' ^ ! ', + ' ^ !']; const unsub = ' !'; const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)(ki)(lj)k---l---i-'; @@ -189,11 +189,11 @@ describe('mergeMapTo', () => { const e1subs = '^ !'; const inner = cold( '----i---j---k---l---|', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ ! ', + ' ^ ! ', + ' ^ ! ', + ' ^ !']; const unsub = ' !'; const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)(ki)(lj)k---l---i-'; @@ -211,12 +211,12 @@ describe('mergeMapTo', () => { it('should mergeMapTo many outer to many inner, inner never completes', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c-------d-------| '); - const e1subs = '^ '; + const e1subs = '^ ! '; const inner = cold('----i---j---k---l-', values); const innersubs = [' ^ ', - ' ^ ', - ' ^ ', - ' ^ ']; + ' ^ ', + ' ^ ', + ' ^ ']; const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l-'; expectObservable(e1.pipe(mergeMapTo(inner))).toBe(expected, values); @@ -230,9 +230,9 @@ describe('mergeMapTo', () => { const e1subs = '^ ! '; const inner = cold('----i---j---k---l-------# ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ ! ', - ' (^!) ']; + ' ^ ! ', + ' ^ ! ', + ' (^!) ']; const expected = '-----i---j---(ki)(lj)(ki)#'; expectObservable(e1.pipe(mergeMapTo(inner))).toBe(expected, values); @@ -246,9 +246,9 @@ describe('mergeMapTo', () => { const e1subs = '^ !'; const inner = cold('----i---j---k---l---| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ !', - ' ^ !']; + ' ^ ! ', + ' ^ !', + ' ^ !']; const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)#'; expectObservable(e1.pipe(mergeMapTo(inner))).toBe(expected, values); @@ -262,8 +262,8 @@ describe('mergeMapTo', () => { const e1subs = '^ !'; const inner = cold('----i---j---k---l---#', values); const innersubs = [' ^ !', - ' ^ !', - ' ^ !']; + ' ^ !', + ' ^ !']; const expected = '-----i---j---(ki)(lj)#'; expectObservable(e1.pipe(mergeMapTo(inner))).toBe(expected, values); @@ -274,11 +274,11 @@ describe('mergeMapTo', () => { it('should mergeMapTo many cold Observable, with parameter concurrency=1, without resultSelector', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const inner = cold('----i---j---k---l---| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ !']; const expected = '-----i---j---k---l-------i---j---k---l-------i---j---k---l---|'; const result = e1.pipe(mergeMapTo(inner, 1)); @@ -291,11 +291,11 @@ describe('mergeMapTo', () => { it('should mergeMap to many cold Observable, with parameter concurrency=2, without resultSelector', () => { const values = {i: 'foo', j: 'bar', k: 'baz', l: 'qux'}; const e1 = hot('-a-------b-------c---| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const inner = cold('----i---j---k---l---| ', values); const innersubs = [' ^ ! ', - ' ^ ! ', - ' ^ !']; + ' ^ ! ', + ' ^ !']; const expected = '-----i---j---(ki)(lj)k---(li)j---k---l---|'; const result = e1.pipe(mergeMapTo(inner, 2)); diff --git a/spec/operators/mergeScan-spec.ts b/spec/operators/mergeScan-spec.ts index 2a0d484bd9..7d41f39cbe 100644 --- a/spec/operators/mergeScan-spec.ts +++ b/spec/operators/mergeScan-spec.ts @@ -66,7 +66,7 @@ describe('mergeScan', () => { it('should not stop ongoing async projections when source completes', () => { const e1 = hot('--a--^--b--c--d--e--f--g--|'); - const e1subs = '^ !'; + const e1subs = '^ !'; const expected = '--------u--v--w--x--y--(z|)'; const values = { @@ -183,7 +183,7 @@ describe('mergeScan', () => { it('should handle a never projected Observable', () => { const e1 = hot('--a--^--b--c--d--e--f--g--|'); - const e1subs = '^ '; + const e1subs = '^ !'; const expected = '----------------------'; const values = { x: [] }; @@ -252,7 +252,7 @@ describe('mergeScan', () => { it('should mergescan projects cold Observable with single concurrency', () => { const e1 = hot('--a--b--c--|'); - const e1subs = '^ !'; + const e1subs = '^ !'; const inner = [ cold( '--d--e--f--| '), @@ -293,7 +293,7 @@ describe('mergeScan', () => { it('should emit accumulator if inner completes without value after source completes', () => { const e1 = hot('--a--^--b--c--d--e--f--g--|'); - const e1subs = '^ !'; + const e1subs = '^ !'; const expected = '-----------------------(x|)'; const source = e1.pipe( @@ -306,7 +306,7 @@ describe('mergeScan', () => { it('should mergescan projects hot Observable with single concurrency', () => { const e1 = hot('---a---b---c---|'); - const e1subs = '^ !'; + const e1subs = '^ !'; const inner = [ hot( '--d--e--f--|'), @@ -336,7 +336,7 @@ describe('mergeScan', () => { it('should mergescan projects cold Observable with dual concurrency', () => { const e1 = hot('----a----b----c----|'); - const e1subs = '^ !'; + const e1subs = '^ !'; const inner = [ cold( '---d---e---f---| '), @@ -366,7 +366,7 @@ describe('mergeScan', () => { it('should mergescan projects hot Observable with dual concurrency', () => { const e1 = hot('---a---b---c---|'); - const e1subs = '^ !'; + const e1subs = '^ !'; const inner = [ hot( '--d--e--f--|'), diff --git a/spec/operators/observeOn-spec.ts b/spec/operators/observeOn-spec.ts index 103eac0222..59f8deedfb 100644 --- a/spec/operators/observeOn-spec.ts +++ b/spec/operators/observeOn-spec.ts @@ -20,9 +20,9 @@ describe('observeOn operator', () => { }); it('should observe after specified delay', () => { - const e1 = hot('--a--b--|'); + const e1 = hot('--a--b--| '); const expected = '-----a--b--|'; - const sub = '^ !'; + const sub = '^ ! '; expectObservable(e1.pipe(observeOn(rxTestScheduler, 30))).toBe(expected); expectSubscriptions(e1.subscriptions).toBe(sub); @@ -83,7 +83,7 @@ describe('observeOn operator', () => { expectSubscriptions(e1.subscriptions).toBe(sub); }); - it('should clean up subscriptions created by async scheduling (prevent memory leaks #2244)', (done) => { + xit('should clean up subscriptions created by async scheduling (prevent memory leaks #2244)', (done) => { //HACK: Deep introspection to make sure we're cleaning up notifications in scheduling. // as the architecture changes, this test may become brittle. const results: number[] = []; diff --git a/spec/operators/onErrorResumeNext-spec.ts b/spec/operators/onErrorResumeNext-spec.ts index f454e6bdb8..f1fa1b2cdf 100644 --- a/spec/operators/onErrorResumeNext-spec.ts +++ b/spec/operators/onErrorResumeNext-spec.ts @@ -9,7 +9,7 @@ describe('onErrorResumeNext operator', () => { asDiagram('onErrorResumeNext')('should continue observable sequence with next observable', () => { const source = hot('--a--b--#'); const next = cold( '--c--d--|'); - const subs = '^ !'; + const subs = '^ !'; const expected = '--a--b----c--d--|'; expectObservable(source.pipe(onErrorResumeNext(next))).toBe(expected); @@ -19,7 +19,7 @@ describe('onErrorResumeNext operator', () => { it('should continue with hot observables', () => { const source = hot('--a--b--#'); const next = hot('-----x----c--d--|'); - const subs = '^ !'; + const subs = '^ !'; const expected = '--a--b----c--d--|'; expectObservable(source.pipe(onErrorResumeNext(next))).toBe(expected); @@ -31,7 +31,7 @@ describe('onErrorResumeNext operator', () => { const next = [cold( '--c--d--#'), cold( '--e--#'), cold( '--f--g--|')]; - const subs = '^ !'; + const subs = '^ !'; const expected = '--a--b----c--d----e----f--g--|'; expectObservable(source.pipe(onErrorResumeNext(next))).toBe(expected); @@ -43,7 +43,7 @@ describe('onErrorResumeNext operator', () => { const next1 = cold( '--c--d--#'); const next2 = cold( '--e--#'); const next3 = cold( '--f--g--|'); - const subs = '^ !'; + const subs = '^ !'; const expected = '--a--b----c--d----e----f--g--|'; expectObservable(source.pipe(onErrorResumeNext(next1, next2, next3))).toBe(expected); @@ -55,7 +55,7 @@ describe('onErrorResumeNext operator', () => { const next1 = cold( '--c--d--|'); const next2 = cold( '--e--|'); const next3 = cold( '--f--g--|'); - const subs = '^ !'; + const subs = '^ !'; const expected = '--a--b----c--d----e----f--g--|'; expectObservable(source.pipe(onErrorResumeNext(next1, next2, next3))).toBe(expected); @@ -67,7 +67,7 @@ describe('onErrorResumeNext operator', () => { const next1 = cold('--c--d--|'); const next2 = cold( '--e--#'); const next3 = cold( '--f--g--|'); - const subs = '^ !'; + const subs = '(^!)'; const expected = '--c--d----e----f--g--|'; expectObservable(source.pipe(onErrorResumeNext(next1, next2, next3))).toBe(expected); @@ -77,7 +77,7 @@ describe('onErrorResumeNext operator', () => { it('should not complete with observble does not ends', () => { const source = hot('--a--b--|'); const next1 = cold( '--'); - const subs = '^ '; + const subs = '^ !'; const expected = '--a--b----'; expectObservable(source.pipe(onErrorResumeNext(next1))).toBe(expected); @@ -97,7 +97,7 @@ describe('onErrorResumeNext operator', () => { it('should complete observable with next observable throws', () => { const source = hot('--a--b--#'); const next = cold( '--c--d--#'); - const subs = '^ !'; + const subs = '^ !'; const expected = '--a--b----c--d--|'; expectObservable(source.pipe(onErrorResumeNext(next))).toBe(expected); diff --git a/spec/operators/sequenceEqual-spec.ts b/spec/operators/sequenceEqual-spec.ts index 7604a44528..e0029d9d17 100644 --- a/spec/operators/sequenceEqual-spec.ts +++ b/spec/operators/sequenceEqual-spec.ts @@ -12,7 +12,7 @@ const booleans = { T: true, F: false }; describe('sequenceEqual operator', () => { asDiagram('sequenceEqual(observable)')('should return true for two equal sequences', () => { const s1 = hot('--a--^--b--c--d--e--f--g--|'); - const s1subs = '^ !'; + const s1subs = '^ !'; const s2 = hot('-----^-----b--c--d-e-f------g-|'); const s2subs = '^ !'; const expected = '-------------------------(T|)'; @@ -46,7 +46,7 @@ describe('sequenceEqual operator', () => { it('should return true for two observables that match when the last one emits and completes in the same frame', () => { const s1 = hot('--a--^--b--c--d--e--f--g--|'); - const s1subs = '^ !'; + const s1subs = '^ !'; const s2 = hot('-----^--b--c--d--e--f--g------|'); const s2subs = '^ !'; const expected = '-------------------------(T|)'; @@ -60,7 +60,7 @@ describe('sequenceEqual operator', () => { it('should return true for two observables that match when the last one emits and completes in the same frame', () => { const s1 = hot('--a--^--b--c--d--e--f--g--|'); - const s1subs = '^ !'; + const s1subs = '^ !'; const s2 = hot('-----^--b--c--d--e--f---------(g|)'); const s2subs = '^ !'; const expected = '-------------------------(T|)'; @@ -132,26 +132,28 @@ describe('sequenceEqual operator', () => { const s1 = cold('|'); // empty const s2 = cold('------a------'); const expected = '------(F|)'; - const subs = '^ !'; + const s1subs = '(^!)'; + const s2subs = '^ !'; const source = s1.pipe(sequenceEqual(s2)); expectObservable(source).toBe(expected, booleans); - expectSubscriptions(s1.subscriptions).toBe(subs); - expectSubscriptions(s2.subscriptions).toBe(subs); + expectSubscriptions(s1.subscriptions).toBe(s1subs); + expectSubscriptions(s2.subscriptions).toBe(s2subs); }); it('should return false if compareTo is empty and source is not', () => { const s1 = cold('------a------'); const s2 = cold('|'); // empty const expected = '------(F|)'; - const subs = '^ !'; + const s1subs = '^ !'; + const s2subs = '(^!)'; const source = s1.pipe(sequenceEqual(s2)); expectObservable(source).toBe(expected, booleans); - expectSubscriptions(s1.subscriptions).toBe(subs); - expectSubscriptions(s2.subscriptions).toBe(subs); + expectSubscriptions(s1.subscriptions).toBe(s1subs); + expectSubscriptions(s2.subscriptions).toBe(s2subs); }); it('should return never if compareTo is empty and source is never', () => { @@ -206,7 +208,7 @@ describe('sequenceEqual operator', () => { it('should use the provided comparor', () => { const s1 = hot('--a--^--b-----c------d--|'); - const s1subs = '^ !'; + const s1subs = '^ !'; const s2 = hot('-----^--------x---y---z-------|'); const s2subs = '^ !'; const expected = '-------------------------(T|)'; @@ -230,7 +232,7 @@ describe('sequenceEqual operator', () => { it('should return false for two unequal sequences, compareTo finishing last', () => { const s1 = hot('--a--^--b--c--d--e--f--g--|'); - const s1subs = '^ !'; + const s1subs = '^ !'; const s2 = hot('-----^-----b--c--d-e-f------z-|'); const s2subs = '^ !'; const expected = '-----------------------(F|)'; @@ -260,7 +262,7 @@ describe('sequenceEqual operator', () => { const s1 = hot('--a--^--b--c--d--e--f--g--h--|'); const s1subs = '^ !'; const s2 = hot('-----^--b--c--d-|'); - const s2subs = '^ !'; + const s2subs = '^ !'; const expected = '------------(F|)'; const source = s1.pipe(sequenceEqual(s2)); @@ -272,7 +274,7 @@ describe('sequenceEqual operator', () => { it('should return false when the compareTo emits an extra value after the source completes', () => { const s1 = hot('--a--^--b--c--d-|'); - const s1subs = '^ !'; + const s1subs = '^ !'; const s2 = hot('-----^--b--c--d--e--f--g--h--|'); const s2subs = '^ !'; const expected = '------------(F|)'; @@ -306,18 +308,18 @@ describe('sequenceEqual operator', () => { const s1 = hot('---a--^---b---c---d---e---f---g---h---i---j---|'); const s2 = cold( '----b---c-|'); const expected1 = '------------(F|)'; - const subs1 = '^ !'; + const s2subs = '^ !'; const delay = '-------------------|'; const s3 = cold( '-f---g---h---i---j---|'); const expected2 = ' ---------------------(T|)'; - const subs2 = ' ^ !'; + const s3subs = ' ^ !'; const test1 = s1.pipe(sequenceEqual(s2)); const test2 = s1.pipe(sequenceEqual(s3)); expectObservable(test1).toBe(expected1, booleans); rxTestScheduler.schedule(() => expectObservable(test2).toBe(expected2, booleans), time(delay)); - expectSubscriptions(s2.subscriptions).toBe(subs1); - expectSubscriptions(s3.subscriptions).toBe(subs2); + expectSubscriptions(s2.subscriptions).toBe(s2subs); + expectSubscriptions(s3.subscriptions).toBe(s3subs); }); }); diff --git a/spec/operators/switchMap-spec.ts b/spec/operators/switchMap-spec.ts index 822739ea7b..4eabe0ae3d 100644 --- a/spec/operators/switchMap-spec.ts +++ b/spec/operators/switchMap-spec.ts @@ -100,7 +100,7 @@ describe('switchMap', () => { const y = cold( '---f---g---h---i--|'); const ysubs = ' ^ !'; const e1 = hot('---------x---------y---------| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '-----------a--b--c----f---g---h---i--|'; const observableLookup = { x: x, y: y }; @@ -175,7 +175,7 @@ describe('switchMap', () => { const y = cold( '---f---g---h---i--'); const ysubs = ' ^ '; const e1 = hot('---------x---------y---------| '); - const e1subs = '^ '; + const e1subs = '^ ! '; const expected = '-----------a--b--c----f---g---h---i--'; const observableLookup = { x: x, y: y }; @@ -232,7 +232,7 @@ describe('switchMap', () => { const y = hot('--p-o-o-p-------------f---g---h---i--|'); const ysubs = ' ^ !'; const e1 = hot('---------x---------y---------| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '-----------c--d--e----f---g---h---i--|'; const observableLookup = { x: x, y: y }; @@ -270,7 +270,7 @@ describe('switchMap', () => { const xsubs = ' (^!) '; const ysubs = ' ^ '; const e1 = hot('---------x---------y---------|'); - const e1subs = '^ '; + const e1subs = '^ !'; const expected = '------------------------------'; const observableLookup = { x: x, y: y }; diff --git a/spec/operators/switchMapTo-spec.ts b/spec/operators/switchMapTo-spec.ts index 9d7a402e4f..0c86385ec5 100644 --- a/spec/operators/switchMapTo-spec.ts +++ b/spec/operators/switchMapTo-spec.ts @@ -104,9 +104,9 @@ describe('switchMapTo', () => { const x = cold( '--a--b--c--d--e--| '); const xsubs = [' ^ ! ', // --a--b--c--d--e--| - ' ^ !']; + ' ^ !']; const e1 = hot('---------x---------x---------| '); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '-----------a--b--c---a--b--c--d--e--|'; expectObservable(e1.pipe(switchMapTo(x))).toBe(expected); @@ -130,7 +130,7 @@ describe('switchMapTo', () => { const x = cold( '--a--b--c--d--e--| '); const xsubs = [' ^ ! ', // --a--b--c--d--e--| - ' ^ ! ']; + ' ^ ! ']; const e1 = hot('---------x---------x---------|'); const unsub = ' ! '; const e1subs = '^ ! '; @@ -145,7 +145,7 @@ describe('switchMapTo', () => { const x = cold( '--a--b--c--d--e--| '); const xsubs = [' ^ ! ', // --a--b--c--d--e--| - ' ^ ! ']; + ' ^ ! ']; const e1 = hot('---------x---------x---------|'); const e1subs = '^ ! '; const expected = '-----------a--b--c---a- '; @@ -166,9 +166,9 @@ describe('switchMapTo', () => { const x = cold( '--a--b--c--d--e- '); const xsubs = [' ^ ! ', // --a--b--c--d--e- - ' ^ ']; + ' ^ ']; const e1 = hot('---------x---------y---------| '); - const e1subs = '^ '; + const e1subs = '^ ! '; const expected = '-----------a--b--c---a--b--c--d--e-'; expectObservable(e1.pipe(switchMapTo(x))).toBe(expected); @@ -179,7 +179,7 @@ describe('switchMapTo', () => { it('should handle a synchronous switch to the inner observable', () => { const x = cold( '--a--b--c--d--e--| '); const xsubs = [' (^!) ', - ' ^ ! ']; + ' ^ ! ']; const e1 = hot('---------(xx)----------------|'); const e1subs = '^ !'; const expected = '-----------a--b--c--d--e-----|'; @@ -204,7 +204,7 @@ describe('switchMapTo', () => { it('should switch an inner hot observable', () => { const x = hot('--p-o-o-p---a--b--c--d-| '); const xsubs = [' ^ ! ', - ' ^ ! ']; + ' ^ ! ']; const e1 = hot('---------x---------x---------|'); const e1subs = '^ !'; const expected = '------------a--b--c--d-------|'; @@ -217,7 +217,7 @@ describe('switchMapTo', () => { it('should switch to an inner empty', () => { const x = cold('|'); const xsubs = [' (^!) ', - ' (^!) ']; + ' (^!) ']; const e1 = hot('---------x---------x---------|'); const e1subs = '^ !'; const expected = '-----------------------------|'; @@ -230,9 +230,9 @@ describe('switchMapTo', () => { it('should switch to an inner never', () => { const x = cold('-'); const xsubs = [' ^ ! ', - ' ^ ']; + ' ^ ']; const e1 = hot('---------x---------x---------|'); - const e1subs = '^ '; + const e1subs = '^ !'; const expected = '------------------------------'; expectObservable(e1.pipe(switchMapTo(x))).toBe(expected); diff --git a/spec/operators/zipAll-spec.ts b/spec/operators/zipAll-spec.ts index cc35fe6f3c..376c1fb469 100644 --- a/spec/operators/zipAll-spec.ts +++ b/spec/operators/zipAll-spec.ts @@ -390,7 +390,7 @@ describe('zipAll operator', () => { const y = cold( 'd---e---f---| '); const ysubs = ' ^ !'; const e1 = hot('--x--y--| ', { x: x, y: y }); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '--------u---v---w---|'; const values = { u: ['a', 'd'], @@ -412,7 +412,7 @@ describe('zipAll operator', () => { const z = cold( 'g-h-i-j-k-| '); const zsubs = ' ^ ! '; const e1 = hot('--x------y--------z--------| ', { x: x, y: y, z: z }); - const e1subs = '^ !'; + const e1subs = '^ ! '; const expected = '---------------------------u-v---------|'; const values = { u: ['a', 'c', 'g'], @@ -433,8 +433,8 @@ describe('zipAll operator', () => { const ysubs = ' ^ !'; const z = cold( 'g-h-i-j-k-| '); const zsubs = ' ^ !'; - const e1 = hot('--x---------y--------z--------|', { x: x, y: y, z: z }); - const e1subs = '^ !'; + const e1 = hot('--x---------y--------z--------| ', { x: x, y: y, z: z }); + const e1subs = '^ ! '; const expected = '------------------------------u-v-----#'; const expectedValues = { diff --git a/spec/schedulers/TestScheduler-spec.ts b/spec/schedulers/TestScheduler-spec.ts index 9d15b7b6e8..eeb996d61a 100644 --- a/spec/schedulers/TestScheduler-spec.ts +++ b/spec/schedulers/TestScheduler-spec.ts @@ -313,7 +313,7 @@ describe('TestScheduler', () => { const expected = ' -- 9ms a 9ms b 9ms (c|) '; expectObservable(output).toBe(expected); - expectSubscriptions(input.subscriptions).toBe(' ^- - - - --------------------------!'); + expectSubscriptions(input.subscriptions).toBe(' ^- - - - - !'); }); }); From 5d16ce4ecd6e73dc113dc310cd860f54c05dd218 Mon Sep 17 00:00:00 2001 From: Nicholas Jamieson Date: Fri, 27 Jul 2018 21:59:58 +1000 Subject: [PATCH 3/3] chore(observeOn): fix skipped test Closes #2457 #2459 --- spec/operators/observeOn-spec.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spec/operators/observeOn-spec.ts b/spec/operators/observeOn-spec.ts index 59f8deedfb..ed218db90c 100644 --- a/spec/operators/observeOn-spec.ts +++ b/spec/operators/observeOn-spec.ts @@ -83,7 +83,7 @@ describe('observeOn operator', () => { expectSubscriptions(e1.subscriptions).toBe(sub); }); - xit('should clean up subscriptions created by async scheduling (prevent memory leaks #2244)', (done) => { + it('should clean up subscriptions created by async scheduling (prevent memory leaks #2244)', (done) => { //HACK: Deep introspection to make sure we're cleaning up notifications in scheduling. // as the architecture changes, this test may become brittle. const results: number[] = []; @@ -104,7 +104,7 @@ describe('observeOn operator', () => { .subscribe( x => { const observeOnSubscriber = subscription._subscriptions[0]; - expect(observeOnSubscriber._subscriptions.length).to.equal(2); // 1 for the consumer, and one for the notification + expect(observeOnSubscriber._subscriptions.length).to.equal(2); // one for the consumer, and one for the notification expect(observeOnSubscriber._subscriptions[1].state.notification.kind) .to.equal('N'); expect(observeOnSubscriber._subscriptions[1].state.notification.value) @@ -114,10 +114,11 @@ describe('observeOn operator', () => { err => done(err), () => { // now that the last nexted value is done, there should only be a complete notification scheduled + // the consumer will have been unsubscribed via Subscriber#_parentSubscription const observeOnSubscriber = subscription._subscriptions[0]; - expect(observeOnSubscriber._subscriptions.length).to.equal(2); // 1 for the consumer, one for the complete notification + expect(observeOnSubscriber._subscriptions.length).to.equal(1); // one for the complete notification // only this completion notification should remain. - expect(observeOnSubscriber._subscriptions[1].state.notification.kind) + expect(observeOnSubscriber._subscriptions[0].state.notification.kind) .to.equal('C'); // After completion, the entire _subscriptions list is nulled out anyhow, so we can't test much further than this. expect(results).to.deep.equal([1, 2, 3]);