@@ -7,14 +7,7 @@ import {
77 ViewChildren ,
88 ChangeDetectionStrategy ,
99} from '@angular/core' ;
10- import {
11- ComponentFixture ,
12- TestBed ,
13- fakeAsync ,
14- flush ,
15- tick ,
16- waitForAsync ,
17- } from '@angular/core/testing' ;
10+ import { ComponentFixture , TestBed , waitForAsync } from '@angular/core/testing' ;
1811import { By } from '@angular/platform-browser' ;
1912import {
2013 createMouseEvent ,
@@ -87,6 +80,12 @@ describe('Menu', () => {
8780 } ) ;
8881
8982 describe ( 'menu aim' , ( ) => {
83+ // TODO(crisbeto): update the component to clear timeouts on destroy.
84+ // Give some time for timeouts to be cleaned up.
85+ afterEach ( async ( ) => {
86+ await wait ( 350 ) ;
87+ } ) ;
88+
9089 /** A coordinate in the browser window */
9190 type Point = { x : number ; y : number } ;
9291
@@ -189,13 +188,13 @@ describe('Menu', () => {
189188 *
190189 * @return the number of elements the mouse entered into.
191190 */
192- function hover ( from : Point , to : Point , inMenu : HTMLElement , duration : number ) {
191+ async function hover ( from : Point , to : Point , inMenu : HTMLElement , duration : number ) {
193192 const getNextPoint = getNextPointIterator ( from , to ) ;
194193
195194 let currentPoint : Point | null = from ;
196195 let currElement = getElementAt ( currentPoint ) ;
197196
198- const timeout = duration / ( to . x - from . x ) ;
197+ const timeout = duration / Math . abs ( to . x - from . x ) ;
199198
200199 let numEnters = 0 ;
201200 while ( currentPoint ) {
@@ -209,7 +208,9 @@ describe('Menu', () => {
209208 fixture . detectChanges ( ) ;
210209 }
211210 currentPoint = getNextPoint ( ) ;
212- tick ( timeout ) ;
211+ if ( timeout > 0 ) {
212+ await wait ( timeout ) ;
213+ }
213214 }
214215 return numEnters ;
215216 }
@@ -231,31 +232,31 @@ describe('Menu', () => {
231232 } ;
232233 }
233234
234- it ( 'should close the edit menu when hovering directly down from the edit menu trigger to the print item without waiting' , fakeAsync ( ( ) => {
235+ it ( 'should close the edit menu when hovering directly down from the edit menu trigger to the print item without waiting' , async ( ) => {
235236 openFileMenu ( ) ;
236237 openMenuOnHover ( nativeEditTrigger ! ) ;
237238 const editPosition = nativeEditTrigger ! . getBoundingClientRect ( ) ;
238239 const printPosition = nativeFileButtons ! [ 4 ] . getBoundingClientRect ( ) ;
239240
240- const numEnterEvents = hover (
241+ const numEnterEvents = await hover (
241242 { x : editPosition . x , y : editPosition . y + 1 } ,
242243 { x : printPosition . x + 5 , y : printPosition . y + 1 } ,
243244 nativeMenus [ 0 ] ,
244- 100 ,
245+ 0 ,
245246 ) ;
246247 detectChanges ( ) ;
247248
248249 expect ( numEnterEvents ) . toBe ( 4 ) ;
249250 expect ( nativeMenus . length ) . toBe ( 1 ) ;
250- } ) ) ;
251+ } ) ;
251252
252- it ( 'should close the edit menu after moving towards submenu and stopping' , fakeAsync ( ( ) => {
253+ it ( 'should close the edit menu after moving towards submenu and stopping' , async ( ) => {
253254 openFileMenu ( ) ;
254255 openMenuOnHover ( nativeEditTrigger ! ) ;
255256 const editPosition = nativeEditTrigger ! . getBoundingClientRect ( ) ;
256257 const sharePosition = nativeShareTrigger ! . getBoundingClientRect ( ) ;
257258
258- const numEnters = hover (
259+ const numEnters = await hover (
259260 {
260261 x : editPosition . x + editPosition . width / 2 ,
261262 y : editPosition . y + editPosition . height - 10 ,
@@ -265,44 +266,43 @@ describe('Menu', () => {
265266 y : sharePosition . y + sharePosition . height - 10 ,
266267 } ,
267268 nativeMenus [ 0 ] ,
268- 100 ,
269+ 0 ,
269270 ) ;
270- tick ( 2000 ) ;
271+ await wait ( 2100 ) ;
271272 detectChanges ( ) ;
272273
273274 expect ( numEnters ) . toBe ( 1 ) ;
274275 expect ( nativeMenus . length ) . toBe ( 2 ) ;
275276 expect ( nativeMenus [ 1 ] . id ) . toBe ( 'share_menu' ) ;
276- } ) ) ;
277+ } ) ;
277278
278- it ( 'should not close the edit submenu when hovering into its items in time' , fakeAsync ( ( ) => {
279+ it ( 'should not close the edit submenu when hovering into its items in time' , async ( ) => {
279280 openFileMenu ( ) ;
280281 openMenuOnHover ( nativeEditTrigger ! ) ;
281282 const editPosition = nativeEditTrigger ! . getBoundingClientRect ( ) ;
282283 const pastePosition = nativeEditButtons ! [ 4 ] . getBoundingClientRect ( ) ;
283284
284- const numEnters = hover ( editPosition , pastePosition , nativeMenus [ 0 ] , 100 ) ;
285+ const numEnters = await hover ( editPosition , pastePosition , nativeMenus [ 0 ] , 0 ) ;
285286 detectChanges ( ) ;
286- flush ( ) ;
287+ await fixture . whenStable ( ) ;
287288
288289 expect ( numEnters ) . toBeGreaterThan ( 2 ) ;
289290 expect ( nativeMenus . length ) . toBe ( 2 ) ;
290291 expect ( nativeMenus [ 1 ] . id ) . toBe ( 'edit_menu' ) ;
291- } ) ) ;
292+ } ) ;
292293
293- it ( 'should close the edit menu when hovering into its items slowly' , fakeAsync ( ( ) => {
294+ it ( 'should close the edit menu when hovering into its items slowly' , async ( ) => {
294295 openFileMenu ( ) ;
295296 openMenuOnHover ( nativeEditTrigger ! ) ;
296297 const editPosition = nativeEditTrigger ! . getBoundingClientRect ( ) ;
297298 const pastePosition = nativeEditButtons ! [ 4 ] . getBoundingClientRect ( ) ;
298299
299- const numEnters = hover ( editPosition , pastePosition , nativeMenus [ 0 ] , 4000 ) ;
300+ const numEnters = await hover ( editPosition , pastePosition , nativeMenus [ 0 ] , 1100 ) ;
300301 detectChanges ( ) ;
301- flush ( ) ;
302302
303303 expect ( numEnters ) . toBeGreaterThan ( 2 ) ;
304304 expect ( nativeMenus . length ) . toBe ( 1 ) ;
305- } ) ) ;
305+ } ) ;
306306 } ) ;
307307
308308 describe ( 'with rtl layout and menu at bottom of page moving up and left' , ( ) => {
@@ -383,13 +383,13 @@ describe('Menu', () => {
383383 *
384384 * @return the number of elements the mouse entered into.
385385 */
386- function hover ( from : Point , to : Point , inMenu : HTMLElement , duration : number ) {
386+ async function hover ( from : Point , to : Point , inMenu : HTMLElement , duration : number ) {
387387 const getNextPoint = getNextPointIterator ( from , to ) ;
388388
389389 let currPoint : Point | null = from ;
390390 let currElement = getElementAt ( currPoint ) ;
391391
392- const timeout = duration / ( to . x - from . x ) ;
392+ const timeout = duration / Math . abs ( to . x - from . x ) ;
393393
394394 let numEnters = 0 ;
395395 while ( currPoint ) {
@@ -403,7 +403,9 @@ describe('Menu', () => {
403403 fixture . detectChanges ( ) ;
404404 }
405405 currPoint = getNextPoint ( ) ;
406- tick ( timeout ) ;
406+ if ( timeout ) {
407+ await wait ( timeout ) ;
408+ }
407409 }
408410 return numEnters ;
409411 }
@@ -425,66 +427,63 @@ describe('Menu', () => {
425427 } ;
426428 }
427429
428- it ( 'should close the edit menu when hovering directly up from the edit menu trigger to the print item without waiting' , fakeAsync ( ( ) => {
430+ it ( 'should close the edit menu when hovering directly up from the edit menu trigger to the print item without waiting' , async ( ) => {
429431 openFileMenu ( ) ;
430432 openMenuOnHover ( nativeEditTrigger ! ) ;
431- tick ( ) ;
432433
433434 const editPosition = nativeEditTrigger ! . getBoundingClientRect ( ) ;
434435 const printPosition = nativeFileButtons ! [ 0 ] . getBoundingClientRect ( ) ;
435436
436- const numEnterEvents = hover (
437+ const numEnterEvents = await hover (
437438 { x : editPosition . x + editPosition . width / 2 , y : editPosition . y + 5 } ,
438439 { x : printPosition . x + 10 , y : printPosition . y - 10 } ,
439440 nativeMenus [ 0 ] ,
440- 100 ,
441+ 0 ,
441442 ) ;
442443 detectChanges ( ) ;
443- flush ( ) ;
444444
445445 expect ( numEnterEvents ) . toBe ( 4 ) ;
446446 expect ( nativeMenus . length ) . toBe ( 1 ) ;
447- } ) ) ;
447+ } ) ;
448448
449- it ( 'should close the edit menu after moving towards submenu and stopping' , fakeAsync ( ( ) => {
449+ it ( 'should close the edit menu after moving towards submenu and stopping' , async ( ) => {
450450 openFileMenu ( ) ;
451451 openMenuOnHover ( nativeEditTrigger ! ) ;
452452 const editPosition = nativeEditTrigger ! . getBoundingClientRect ( ) ;
453453 const sharePosition = nativeShareTrigger ! . getBoundingClientRect ( ) ;
454454
455- const numEnters = hover (
455+ const numEnters = await hover (
456456 { x : editPosition . x + editPosition . width / 2 , y : editPosition . y + 5 } ,
457457 {
458458 x : sharePosition . x + 10 ,
459459 y : sharePosition . y + 10 ,
460460 } ,
461461 nativeMenus [ 0 ] ,
462- 100 ,
462+ 0 ,
463463 ) ;
464- tick ( 2000 ) ;
464+ await wait ( 2100 ) ;
465465 detectChanges ( ) ;
466466
467467 expect ( numEnters ) . toBe ( 1 ) ;
468468 expect ( nativeMenus . length ) . toBe ( 2 ) ;
469469 expect ( nativeMenus [ 1 ] . id ) . toBe ( 'share_menu' ) ;
470- } ) ) ;
470+ } ) ;
471471
472- it ( 'should not close the edit submenu when hovering into its items in time' , fakeAsync ( ( ) => {
472+ it ( 'should not close the edit submenu when hovering into its items in time' , async ( ) => {
473473 openFileMenu ( ) ;
474474 openMenuOnHover ( nativeEditTrigger ! ) ;
475- tick ( ) ;
476475
477476 const editPosition = nativeEditTrigger ! . getBoundingClientRect ( ) ;
478477 const undoPosition = nativeEditButtons ! [ 0 ] . getBoundingClientRect ( ) ;
479478
480- const numEnters = hover ( editPosition , undoPosition , nativeMenus [ 0 ] , 100 ) ;
479+ const numEnters = await hover ( editPosition , undoPosition , nativeMenus [ 0 ] , 0 ) ;
481480 detectChanges ( ) ;
482- flush ( ) ;
481+ await fixture . whenStable ( ) ;
483482
484483 expect ( numEnters ) . toBeGreaterThan ( 2 ) ;
485484 expect ( nativeMenus . length ) . toBe ( 2 ) ;
486485 expect ( nativeMenus [ 1 ] . id ) . toBe ( 'edit_menu' ) ;
487- } ) ) ;
486+ } ) ;
488487 } ) ;
489488 } ) ;
490489
@@ -518,6 +517,10 @@ describe('Menu', () => {
518517 } ) ;
519518} ) ;
520519
520+ function wait ( milliseconds : number ) {
521+ return new Promise ( resolve => setTimeout ( resolve , milliseconds ) ) ;
522+ }
523+
521524@Component ( {
522525 template : `
523526 <div cdkMenuBar>
0 commit comments