From 16c03c0f38491444942fb165f1e8e2c7651d1494 Mon Sep 17 00:00:00 2001 From: Michael Giambalvo Date: Fri, 20 Jul 2018 13:24:31 -0700 Subject: [PATCH] fix(core): In Testability.whenStable update callback, pass more complete (#25010) data about tasks. When building a list of pending tasks for callers of whenStable(), Testability will copy data about the task into a new object, in order to avoid leaking references to tasks. This change copies more properties from Tasks into the list of pending tasks, as well as a reference to Task.data to give callers more information about the tasks that are pending. Specifically, this also copies runCount and task ID, which are needed in order for callers to know when a given task is repeating. PR Close #25010 --- packages/core/src/testability/testability.ts | 18 ++++++++++-------- .../core/test/testability/testability_spec.ts | 10 +++++----- .../e2e_test/testability_example_spec.ts | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/core/src/testability/testability.ts b/packages/core/src/testability/testability.ts index 664ffd11a5..b92cd8af4f 100644 --- a/packages/core/src/testability/testability.ts +++ b/packages/core/src/testability/testability.ts @@ -25,10 +25,15 @@ export declare interface PublicTestability { // Angular internal, not intended for public API. export interface PendingMacrotask { source: string; - isPeriodic: boolean; - delay?: number; creationLocation: Error; - xhr?: XMLHttpRequest; + runCount?: number; + data: TaskData; +} + +export interface TaskData { + target?: XMLHttpRequest; + delay?: number; + isPeriodic?: boolean; } // Angular internal, not intended for public API. @@ -152,17 +157,14 @@ export class Testability implements PublicTestability { return []; } + // Copy the tasks data so that we don't leak tasks. return this.taskTrackingZone.macroTasks.map((t: Task) => { return { source: t.source, - isPeriodic: t.data.isPeriodic, - delay: t.data.delay, // From TaskTrackingZone: // https://github.com/angular/zone.js/blob/master/lib/zone-spec/task-tracking.ts#L40 creationLocation: (t as any).creationLocation as Error, - // Added by Zones for XHRs - // https://github.com/angular/zone.js/blob/master/lib/browser/browser.ts#L133 - xhr: (t.data as any).target + data: t.data }; }); } diff --git a/packages/core/test/testability/testability_spec.ts b/packages/core/test/testability/testability_spec.ts index 7004eeabce..6acd7884f3 100644 --- a/packages/core/test/testability/testability_spec.ts +++ b/packages/core/test/testability/testability_spec.ts @@ -143,9 +143,9 @@ class MockNgZone extends NgZone { const tasks = execute.calls.mostRecent().args[1] as PendingMacrotask[]; expect(tasks.length).toEqual(1); - expect(tasks[0].delay).toEqual(1000); + expect(tasks[0].data.delay).toEqual(1000); expect(tasks[0].source).toEqual('setTimeout'); - expect(tasks[0].isPeriodic).toEqual(false); + expect(tasks[0].data.isPeriodic).toEqual(false); clearTimeout(id); })); @@ -207,11 +207,11 @@ class MockNgZone extends NgZone { expect(execute).toHaveBeenCalled(); const update1 = updateCallback.calls.all()[0].args[0] as PendingMacrotask[]; - expect(update1[0].delay).toEqual(500); + expect(update1[0].data.delay).toEqual(500); const update2 = updateCallback.calls.all()[1].args[0] as PendingMacrotask[]; - expect(update2[0].delay).toEqual(500); - expect(update2[1].delay).toEqual(300); + expect(update2[0].data.delay).toEqual(500); + expect(update2[1].data.delay).toEqual(300); })); it('cancels the done callback if the update callback returns true', fakeAsync(() => { diff --git a/packages/examples/core/testability/ts/whenStable/e2e_test/testability_example_spec.ts b/packages/examples/core/testability/ts/whenStable/e2e_test/testability_example_spec.ts index a913d8c75c..544914552b 100644 --- a/packages/examples/core/testability/ts/whenStable/e2e_test/testability_example_spec.ts +++ b/packages/examples/core/testability/ts/whenStable/e2e_test/testability_example_spec.ts @@ -30,7 +30,7 @@ describe('testability example', () => { browser.driver.executeAsyncScript(waitWithResultScript).then((result: any[]) => { let pendingTask = result[0]; - expect(pendingTask.delay).toEqual(5000); + expect(pendingTask.data.delay).toEqual(5000); expect(pendingTask.source).toEqual('setTimeout'); expect(element(by.css('.status')).getText()).not.toContain('done'); done();