Skip to content

Commit d068bc9

Browse files
baizulinbenlesh
authored andcommitted
fix(VirtualTimeScheduler): rework flush so it won't lose actions (#4433)
* fix(VirtualTimeScheduler): rework flush so it won't lose actions Previously VirtualTimeScheduler.flush would lose the action that was on a verge of maxFrames limit which rendered testing of observables that are ticking indefinitely impossible. After the fix the user can set maxFrames, flush, make assertions and repeat the process as many times as needed. * fix(VirtualTimeScheduler): address PR #4433 notes
1 parent f28955f commit d068bc9

File tree

2 files changed

+59
-9
lines changed

2 files changed

+59
-9
lines changed

spec/schedulers/VirtualTimeScheduler-spec.ts

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { expect } from 'chai';
2-
import * as Rx from 'rxjs/Rx';
3-
import { SchedulerAction, Subscription, VirtualAction, VirtualTimeScheduler } from 'rxjs';
2+
import { SchedulerAction, VirtualAction, VirtualTimeScheduler } from 'rxjs';
43

54
/** @test {VirtualTimeScheduler} */
65
describe('VirtualTimeScheduler', () => {
@@ -67,7 +66,7 @@ describe('VirtualTimeScheduler', () => {
6766
let count = 0;
6867
const expected = [100, 200, 300];
6968

70-
v.schedule<string>(function(this: SchedulerAction<string>, state: string) {
69+
v.schedule<string>(function (this: SchedulerAction<string>, state: string) {
7170
if (++count === 3) {
7271
return;
7372
}
@@ -82,12 +81,60 @@ describe('VirtualTimeScheduler', () => {
8281

8382
it('should not execute virtual actions that have been rescheduled before flush', () => {
8483
const v = new VirtualTimeScheduler();
85-
let messages: string[] = [];
86-
let action: VirtualAction<string> = <VirtualAction<string>> v.schedule(function(state: string) {
87-
messages.push(state);
88-
}, 10, 'first message');
89-
action = <VirtualAction<string>> action.schedule('second message' , 10);
84+
const messages: string[] = [];
85+
86+
const action: VirtualAction<string> = <VirtualAction<string>> v.schedule(
87+
state => messages.push(state),
88+
10,
89+
'first message'
90+
);
91+
92+
action.schedule('second message', 10);
9093
v.flush();
94+
9195
expect(messages).to.deep.equal(['second message']);
9296
});
97+
98+
it('should execute only those virtual actions that fall into the maxFrames timespan', function () {
99+
const MAX_FRAMES = 50;
100+
const v = new VirtualTimeScheduler(VirtualAction, MAX_FRAMES);
101+
const messages: string[] = ['first message', 'second message', 'third message'];
102+
103+
const actualMessages: string[] = [];
104+
105+
messages.forEach((message, index) => {
106+
v.schedule(
107+
(state: string) => actualMessages.push(state),
108+
index * MAX_FRAMES,
109+
message
110+
);
111+
});
112+
113+
v.flush();
114+
115+
expect(actualMessages).to.deep.equal(['first message', 'second message']);
116+
expect(v.actions.map(a => a.state)).to.deep.equal(['third message']);
117+
});
118+
119+
it('should pick up actions execution where it left off after reaching previous maxFrames limit', function () {
120+
const MAX_FRAMES = 50;
121+
const v = new VirtualTimeScheduler(VirtualAction, MAX_FRAMES);
122+
const messages: string[] = ['first message', 'second message', 'third message'];
123+
124+
const actualMessages: string[] = [];
125+
126+
messages.forEach((message, index) => {
127+
v.schedule(
128+
state => actualMessages.push(state),
129+
index * MAX_FRAMES,
130+
message
131+
);
132+
});
133+
134+
v.flush();
135+
v.maxFrames = 2 * MAX_FRAMES;
136+
v.flush();
137+
138+
expect(actualMessages).to.deep.equal(messages);
139+
});
93140
});

src/internal/scheduler/VirtualTimeScheduler.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ export class VirtualTimeScheduler extends AsyncScheduler {
2525
const {actions, maxFrames} = this;
2626
let error: any, action: AsyncAction<any>;
2727

28-
while ((action = actions.shift()) && (this.frame = action.delay) <= maxFrames) {
28+
while ((action = actions[0]) && action.delay <= maxFrames) {
29+
actions.shift();
30+
this.frame = action.delay;
31+
2932
if (error = action.execute(action.state, action.delay)) {
3033
break;
3134
}

0 commit comments

Comments
 (0)