Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 5c5ca1a

Browse files
vikermanmhevery
authored andcommitted
feat(spec): add an option to FakeAsyncTestZoneSpec to flush periodic timers (#857)
A flush with flushPeriodic set to true will flush till all the pending timers in the queue have been visited atleast once.
1 parent eca04b0 commit 5c5ca1a

File tree

2 files changed

+82
-8
lines changed

2 files changed

+82
-8
lines changed

Diff for: lib/zone-spec/fake-async-test.ts

+24-7
Original file line numberDiff line numberDiff line change
@@ -91,22 +91,39 @@
9191
this._currentTime = finalTime;
9292
}
9393

94-
flush(limit: number = 20): number {
94+
flush(limit: number = 20, flushPeriodic = false): number {
9595
const startTime = this._currentTime;
9696
let count = 0;
97+
let seenTimers: number[] = [];
9798
while (this._schedulerQueue.length > 0) {
9899
count++;
99100
if (count > limit) {
100101
throw new Error(
101102
'flush failed after reaching the limit of ' + limit +
102103
' tasks. Does your code use a polling timeout?');
103104
}
104-
// If the only remaining tasks are periodic, finish flushing.
105-
if (!(this._schedulerQueue.filter(task => !task.isPeriodic && !task.isRequestAnimationFrame)
106-
.length)) {
107-
break;
105+
if (!flushPeriodic) {
106+
// flush only non-periodic timers.
107+
// If the only remaining tasks are periodic(or requestAnimationFrame), finish flushing.
108+
if (this._schedulerQueue.filter(task => !task.isPeriodic && !task.isRequestAnimationFrame)
109+
.length === 0) {
110+
break;
111+
}
112+
} else {
113+
// flushPeriodic has been requested.
114+
// Stop when all timer id-s have been seen at least once.
115+
if (this._schedulerQueue
116+
.filter(
117+
task =>
118+
seenTimers.indexOf(task.id) === -1 || this._currentTime === task.endTime)
119+
.length === 0) {
120+
break;
121+
}
108122
}
109123
let current = this._schedulerQueue.shift();
124+
if (seenTimers.indexOf(current.id) === -1) {
125+
seenTimers.push(current.id);
126+
}
110127
this._currentTime = current.endTime;
111128
let retval = current.func.apply(global, current.args);
112129
if (!retval) {
@@ -254,10 +271,10 @@
254271
flushErrors();
255272
}
256273

257-
flush(limit?: number): number {
274+
flush(limit?: number, flushPeriodic?: boolean): number {
258275
FakeAsyncTestZoneSpec.assertInZone();
259276
this.flushMicrotasks();
260-
let elapsed = this._scheduler.flush(limit);
277+
let elapsed = this._scheduler.flush(limit, flushPeriodic);
261278
if (this._lastError !== null) {
262279
this._resetLastErrorAndThrow();
263280
}

Diff for: test/zone-spec/fake-async-test.spec.ts

+58-1
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ describe('FakeAsyncTestZoneSpec', () => {
502502
'flush failed after reaching the limit of 20 tasks. Does your code use a polling timeout?');
503503
});
504504

505-
it('accepts a custom limit', function() {
505+
it('accepts a custom limit', () => {
506506
expect(() => {
507507
fakeAsyncTestZone.run(() => {
508508
let z = 0;
@@ -521,6 +521,42 @@ describe('FakeAsyncTestZoneSpec', () => {
521521
.toThrowError(
522522
'flush failed after reaching the limit of 10 tasks. Does your code use a polling timeout?');
523523
});
524+
525+
it('can flush periodic timers if flushPeriodic is true', () => {
526+
fakeAsyncTestZone.run(() => {
527+
let x = 0;
528+
529+
setInterval(() => {
530+
x++;
531+
}, 10);
532+
533+
let elapsed = testZoneSpec.flush(20, true);
534+
535+
expect(elapsed).toEqual(10);
536+
expect(x).toEqual(1);
537+
});
538+
});
539+
540+
it('can flush multiple periodic timers if flushPeriodic is true', () => {
541+
fakeAsyncTestZone.run(() => {
542+
let x = 0;
543+
let y = 0;
544+
545+
setInterval(() => {
546+
x++;
547+
}, 10);
548+
549+
setInterval(() => {
550+
y++;
551+
}, 100);
552+
553+
let elapsed = testZoneSpec.flush(20, true);
554+
555+
expect(elapsed).toEqual(100);
556+
expect(x).toEqual(10);
557+
expect(y).toEqual(1);
558+
});
559+
});
524560
});
525561

526562
describe('outside of FakeAsync Zone', () => {
@@ -578,6 +614,27 @@ describe('FakeAsyncTestZoneSpec', () => {
578614
expect(ran).toEqual(false);
579615
});
580616
});
617+
it('is not flushed when flushPeriodic is false', () => {
618+
let ran = false;
619+
fakeAsyncTestZone.run(() => {
620+
requestAnimationFrame(() => {
621+
ran = true;
622+
});
623+
testZoneSpec.flush(20);
624+
expect(ran).toEqual(false);
625+
});
626+
});
627+
it('is flushed when flushPeriodic is true', () => {
628+
let ran = false;
629+
fakeAsyncTestZone.run(() => {
630+
requestAnimationFrame(() => {
631+
ran = true;
632+
});
633+
const elapsed = testZoneSpec.flush(20, true);
634+
expect(elapsed).toEqual(16);
635+
expect(ran).toEqual(true);
636+
});
637+
});
581638
}));
582639
});
583640
});

0 commit comments

Comments
 (0)