diff --git a/src/cdk/menu/menu-bar.spec.ts b/src/cdk/menu/menu-bar.spec.ts
index 65d453664df1..3b47dbaa2978 100644
--- a/src/cdk/menu/menu-bar.spec.ts
+++ b/src/cdk/menu/menu-bar.spec.ts
@@ -1,4 +1,4 @@
-import {ComponentFixture, fakeAsync, TestBed, tick, waitForAsync} from '@angular/core/testing';
+import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {
Component,
ElementRef,
@@ -149,15 +149,15 @@ describe('MenuBar', () => {
expect(document.activeElement).toEqual(menuBarNativeItems[menuBarNativeItems.length - 1]);
});
- it('should focus the edit MenuItem on E, D character keys', fakeAsync(() => {
+ it('should focus the edit MenuItem on E, D character keys', async () => {
focusMenuBar();
dispatchKeyboardEvent(nativeMenuBar, 'keydown', E);
dispatchKeyboardEvent(nativeMenuBar, 'keydown', D);
- tick(500);
+ await wait(600);
detectChanges();
expect(document.activeElement).toEqual(menuBarNativeItems[1]);
- }));
+ });
it(
'should toggle and wrap when cycling the right/left arrow keys on menu bar ' +
@@ -450,16 +450,16 @@ describe('MenuBar', () => {
expect(nativeMenus.length).toBe(0);
});
- it('should focus share MenuItem on S, H character key press', fakeAsync(() => {
+ it('should focus share MenuItem on S, H character key press', async () => {
openFileMenu();
dispatchKeyboardEvent(nativeMenus[0], 'keydown', S);
dispatchKeyboardEvent(nativeMenus[0], 'keydown', H);
- tick(500);
+ await wait(600);
detectChanges();
expect(document.activeElement).toEqual(fileMenuNativeItems[1]);
- }));
+ });
it('should handle keyboard actions if initial menu is opened programmatically', () => {
fixture.debugElement
@@ -1062,6 +1062,10 @@ describe('MenuBar', () => {
});
});
+function wait(milliseconds: number) {
+ return new Promise(resolve => setTimeout(resolve, milliseconds));
+}
+
@Component({
template: `
diff --git a/src/cdk/menu/menu-trigger.spec.ts b/src/cdk/menu/menu-trigger.spec.ts
index 97cf33e795c3..4c249a9787df 100644
--- a/src/cdk/menu/menu-trigger.spec.ts
+++ b/src/cdk/menu/menu-trigger.spec.ts
@@ -7,7 +7,7 @@ import {
ViewChildren,
ChangeDetectionStrategy,
} from '@angular/core';
-import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
+import {ComponentFixture, TestBed} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {dispatchKeyboardEvent} from '../../cdk/testing/private';
import {CdkMenu} from './menu';
@@ -522,20 +522,19 @@ describe('MenuTrigger', () => {
});
});
- it('should focus the first item when opening on click', fakeAsync(() => {
+ it('should focus the first item when opening on click', () => {
const fixture = TestBed.createComponent(TriggersWithSameMenuDifferentMenuBars);
fixture.detectChanges();
fixture.componentInstance.nativeTriggers.first.nativeElement.click();
fixture.detectChanges();
- tick();
const firstItem =
fixture.componentInstance.nativeMenus.first.nativeElement.querySelector('.cdk-menu-item');
expect(firstItem).toBeTruthy();
expect(document.activeElement).toBe(firstItem);
- }));
+ });
});
@Component({
diff --git a/src/cdk/menu/menu.spec.ts b/src/cdk/menu/menu.spec.ts
index 4155fee591d2..8bfd26e24c95 100644
--- a/src/cdk/menu/menu.spec.ts
+++ b/src/cdk/menu/menu.spec.ts
@@ -7,14 +7,7 @@ import {
ViewChildren,
ChangeDetectionStrategy,
} from '@angular/core';
-import {
- ComponentFixture,
- TestBed,
- fakeAsync,
- flush,
- tick,
- waitForAsync,
-} from '@angular/core/testing';
+import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {
createMouseEvent,
@@ -87,6 +80,12 @@ describe('Menu', () => {
});
describe('menu aim', () => {
+ // TODO(crisbeto): update the component to clear timeouts on destroy.
+ // Give some time for timeouts to be cleaned up.
+ afterEach(async () => {
+ await wait(350);
+ });
+
/** A coordinate in the browser window */
type Point = {x: number; y: number};
@@ -189,13 +188,13 @@ describe('Menu', () => {
*
* @return the number of elements the mouse entered into.
*/
- function hover(from: Point, to: Point, inMenu: HTMLElement, duration: number) {
+ async function hover(from: Point, to: Point, inMenu: HTMLElement, duration: number) {
const getNextPoint = getNextPointIterator(from, to);
let currentPoint: Point | null = from;
let currElement = getElementAt(currentPoint);
- const timeout = duration / (to.x - from.x);
+ const timeout = duration / Math.abs(to.x - from.x);
let numEnters = 0;
while (currentPoint) {
@@ -209,7 +208,9 @@ describe('Menu', () => {
fixture.detectChanges();
}
currentPoint = getNextPoint();
- tick(timeout);
+ if (timeout > 0) {
+ await wait(timeout);
+ }
}
return numEnters;
}
@@ -231,31 +232,31 @@ describe('Menu', () => {
};
}
- it('should close the edit menu when hovering directly down from the edit menu trigger to the print item without waiting', fakeAsync(() => {
+ it('should close the edit menu when hovering directly down from the edit menu trigger to the print item without waiting', async () => {
openFileMenu();
openMenuOnHover(nativeEditTrigger!);
const editPosition = nativeEditTrigger!.getBoundingClientRect();
const printPosition = nativeFileButtons![4].getBoundingClientRect();
- const numEnterEvents = hover(
+ const numEnterEvents = await hover(
{x: editPosition.x, y: editPosition.y + 1},
{x: printPosition.x + 5, y: printPosition.y + 1},
nativeMenus[0],
- 100,
+ 0,
);
detectChanges();
expect(numEnterEvents).toBe(4);
expect(nativeMenus.length).toBe(1);
- }));
+ });
- it('should close the edit menu after moving towards submenu and stopping', fakeAsync(() => {
+ it('should close the edit menu after moving towards submenu and stopping', async () => {
openFileMenu();
openMenuOnHover(nativeEditTrigger!);
const editPosition = nativeEditTrigger!.getBoundingClientRect();
const sharePosition = nativeShareTrigger!.getBoundingClientRect();
- const numEnters = hover(
+ const numEnters = await hover(
{
x: editPosition.x + editPosition.width / 2,
y: editPosition.y + editPosition.height - 10,
@@ -265,44 +266,43 @@ describe('Menu', () => {
y: sharePosition.y + sharePosition.height - 10,
},
nativeMenus[0],
- 100,
+ 0,
);
- tick(2000);
+ await wait(2100);
detectChanges();
expect(numEnters).toBe(1);
expect(nativeMenus.length).toBe(2);
expect(nativeMenus[1].id).toBe('share_menu');
- }));
+ });
- it('should not close the edit submenu when hovering into its items in time', fakeAsync(() => {
+ it('should not close the edit submenu when hovering into its items in time', async () => {
openFileMenu();
openMenuOnHover(nativeEditTrigger!);
const editPosition = nativeEditTrigger!.getBoundingClientRect();
const pastePosition = nativeEditButtons![4].getBoundingClientRect();
- const numEnters = hover(editPosition, pastePosition, nativeMenus[0], 100);
+ const numEnters = await hover(editPosition, pastePosition, nativeMenus[0], 0);
detectChanges();
- flush();
+ await fixture.whenStable();
expect(numEnters).toBeGreaterThan(2);
expect(nativeMenus.length).toBe(2);
expect(nativeMenus[1].id).toBe('edit_menu');
- }));
+ });
- it('should close the edit menu when hovering into its items slowly', fakeAsync(() => {
+ it('should close the edit menu when hovering into its items slowly', async () => {
openFileMenu();
openMenuOnHover(nativeEditTrigger!);
const editPosition = nativeEditTrigger!.getBoundingClientRect();
const pastePosition = nativeEditButtons![4].getBoundingClientRect();
- const numEnters = hover(editPosition, pastePosition, nativeMenus[0], 4000);
+ const numEnters = await hover(editPosition, pastePosition, nativeMenus[0], 1100);
detectChanges();
- flush();
expect(numEnters).toBeGreaterThan(2);
expect(nativeMenus.length).toBe(1);
- }));
+ });
});
describe('with rtl layout and menu at bottom of page moving up and left', () => {
@@ -383,13 +383,13 @@ describe('Menu', () => {
*
* @return the number of elements the mouse entered into.
*/
- function hover(from: Point, to: Point, inMenu: HTMLElement, duration: number) {
+ async function hover(from: Point, to: Point, inMenu: HTMLElement, duration: number) {
const getNextPoint = getNextPointIterator(from, to);
let currPoint: Point | null = from;
let currElement = getElementAt(currPoint);
- const timeout = duration / (to.x - from.x);
+ const timeout = duration / Math.abs(to.x - from.x);
let numEnters = 0;
while (currPoint) {
@@ -403,7 +403,9 @@ describe('Menu', () => {
fixture.detectChanges();
}
currPoint = getNextPoint();
- tick(timeout);
+ if (timeout) {
+ await wait(timeout);
+ }
}
return numEnters;
}
@@ -425,66 +427,63 @@ describe('Menu', () => {
};
}
- it('should close the edit menu when hovering directly up from the edit menu trigger to the print item without waiting', fakeAsync(() => {
+ it('should close the edit menu when hovering directly up from the edit menu trigger to the print item without waiting', async () => {
openFileMenu();
openMenuOnHover(nativeEditTrigger!);
- tick();
const editPosition = nativeEditTrigger!.getBoundingClientRect();
const printPosition = nativeFileButtons![0].getBoundingClientRect();
- const numEnterEvents = hover(
+ const numEnterEvents = await hover(
{x: editPosition.x + editPosition.width / 2, y: editPosition.y + 5},
{x: printPosition.x + 10, y: printPosition.y - 10},
nativeMenus[0],
- 100,
+ 0,
);
detectChanges();
- flush();
expect(numEnterEvents).toBe(4);
expect(nativeMenus.length).toBe(1);
- }));
+ });
- it('should close the edit menu after moving towards submenu and stopping', fakeAsync(() => {
+ it('should close the edit menu after moving towards submenu and stopping', async () => {
openFileMenu();
openMenuOnHover(nativeEditTrigger!);
const editPosition = nativeEditTrigger!.getBoundingClientRect();
const sharePosition = nativeShareTrigger!.getBoundingClientRect();
- const numEnters = hover(
+ const numEnters = await hover(
{x: editPosition.x + editPosition.width / 2, y: editPosition.y + 5},
{
x: sharePosition.x + 10,
y: sharePosition.y + 10,
},
nativeMenus[0],
- 100,
+ 0,
);
- tick(2000);
+ await wait(2100);
detectChanges();
expect(numEnters).toBe(1);
expect(nativeMenus.length).toBe(2);
expect(nativeMenus[1].id).toBe('share_menu');
- }));
+ });
- it('should not close the edit submenu when hovering into its items in time', fakeAsync(() => {
+ it('should not close the edit submenu when hovering into its items in time', async () => {
openFileMenu();
openMenuOnHover(nativeEditTrigger!);
- tick();
const editPosition = nativeEditTrigger!.getBoundingClientRect();
const undoPosition = nativeEditButtons![0].getBoundingClientRect();
- const numEnters = hover(editPosition, undoPosition, nativeMenus[0], 100);
+ const numEnters = await hover(editPosition, undoPosition, nativeMenus[0], 0);
detectChanges();
- flush();
+ await fixture.whenStable();
expect(numEnters).toBeGreaterThan(2);
expect(nativeMenus.length).toBe(2);
expect(nativeMenus[1].id).toBe('edit_menu');
- }));
+ });
});
});
@@ -518,6 +517,10 @@ describe('Menu', () => {
});
});
+function wait(milliseconds: number) {
+ return new Promise(resolve => setTimeout(resolve, milliseconds));
+}
+
@Component({
template: `