Skip to content

Commit 692d631

Browse files
committed
feat(testscheduler): support subscriptionMarbles
1 parent d0d79de commit 692d631

File tree

1 file changed

+30
-4
lines changed

1 file changed

+30
-4
lines changed

src/scheduler/TestScheduler.ts

+30-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import { SubscriptionMarbleToken } from '../marbles/SubscriptionMarbleToken';
1111
import { TestMessage } from '../message/TestMessage';
1212
import { TestMessageValue } from '../message/TestMessageValue';
1313

14+
/**
15+
* @internal
16+
*/
1417
class TestScheduler extends VirtualTimeScheduler {
1518
private readonly coldObservables: Array<ColdObservable<any>> = [];
1619
private readonly hotObservables: Array<HotObservable<any>> = [];
@@ -31,13 +34,13 @@ class TestScheduler extends VirtualTimeScheduler {
3134
}
3235

3336
public getMessages<T = string>(observable: Observable<T>, unsubscriptionMarbles: string | null = null) {
34-
const { unsubscribedFrame } = parseSubscriptionMarble(unsubscriptionMarbles);
37+
const { subscribedFrame, unsubscribedFrame } = this.calculateSubscriptionFrame(observable, unsubscriptionMarbles);
38+
3539
const observableMetadata: Array<TestMessage<T | Array<TestMessage<T>>>> = [];
3640
const pushMetadata = (notification: Notification<T | Array<TestMessage<T>>>) =>
3741
observableMetadata.push(new TestMessageValue<T | Array<TestMessage<T>>>(this.frame, notification));
3842

3943
let subscription: Subscription | null = null;
40-
4144
this.schedule(() => {
4245
subscription = observable.subscribe(
4346
(value: T) =>
@@ -49,9 +52,9 @@ class TestScheduler extends VirtualTimeScheduler {
4952
(err: any) => pushMetadata(Notification.createError(err)),
5053
() => pushMetadata(Notification.createComplete())
5154
);
52-
}, 0);
55+
}, subscribedFrame);
5356

54-
if (unsubscribedFrame !== Number.POSITIVE_INFINITY && !!subscription) {
57+
if (unsubscribedFrame !== Number.POSITIVE_INFINITY) {
5558
this.schedule(() => subscription!.unsubscribe(), unsubscribedFrame);
5659
}
5760

@@ -116,6 +119,29 @@ class TestScheduler extends VirtualTimeScheduler {
116119

117120
return innerObservableMetadata;
118121
}
122+
123+
private calculateSubscriptionFrame(observable: Observable<any>, unsubscriptionMarbles: string | null = null) {
124+
const { subscribedFrame, unsubscribedFrame } = parseSubscriptionMarble(unsubscriptionMarbles);
125+
126+
if (subscribedFrame === Number.POSITIVE_INFINITY) {
127+
return { subscribedFrame: 0, unsubscribedFrame };
128+
}
129+
130+
//looks internal of Observable implementation to determine source is hot or cold observable.
131+
//if source is hot, subscription / unsubscription works as specified,
132+
//if source is cold, subscription always triggers start of observable - adjust unsubscription frame as well
133+
let source = observable;
134+
while (!!source) {
135+
if (source instanceof HotObservable) {
136+
return { subscribedFrame, unsubscribedFrame };
137+
} else if (source instanceof ColdObservable) {
138+
return { subscribedFrame: 0, unsubscribedFrame: unsubscribedFrame - subscribedFrame };
139+
}
140+
source = (source as any).source;
141+
}
142+
143+
throw new Error('Cannot detect source observable type');
144+
}
119145
}
120146

121147
export { TestScheduler };

0 commit comments

Comments
 (0)