Skip to content

Commit a5dd5ed

Browse files
committed
delay 1 more macrotask
1 parent a4e15fa commit a5dd5ed

File tree

4 files changed

+56
-57
lines changed

4 files changed

+56
-57
lines changed

src/cdk/dialog/dialog-container.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -270,21 +270,25 @@ export class CdkDialogContainer<C extends DialogConfig = DialogConfig>
270270
break;
271271
case true:
272272
case 'first-tabbable':
273-
let timeoutRef: {};
274273
// TODO(mmalerba): Once hybrid mode is enabled in g3, we can change this to just
275-
// `afterNextRender`.
274+
// `afterNextRender(() => setTimeout(() =>`.
276275
new Promise<void>(r => {
277276
afterNextRender(r, {injector: this._injector});
278-
timeoutRef = setTimeout(r);
279-
}).then(() => {
280-
clearTimeout(timeoutRef as number);
281-
const focusedSuccessfully = this._focusTrap?.focusInitialElement();
282-
// If we weren't able to find a focusable element in the dialog, then focus the dialog
283-
// container instead.
284-
if (!focusedSuccessfully) {
285-
this._focusDialogContainer();
286-
}
287-
});
277+
setTimeout(r);
278+
}).then(() =>
279+
this._ngZone.runOutsideAngular(() =>
280+
// Wait for one more setTimeout in case there are subsequent microtask change detection
281+
// cycles (e.g. from ngModel).
282+
setTimeout(() => {
283+
const focusedSuccessfully = this._focusTrap?.focusInitialElement();
284+
// If we weren't able to find a focusable element in the dialog, then focus the
285+
// dialog container instead.
286+
if (!focusedSuccessfully) {
287+
this._focusDialogContainer();
288+
}
289+
}),
290+
),
291+
);
288292
break;
289293
case 'first-heading':
290294
this._focusByCssSelector('h1, h2, h3, h4, h5, h6, [role="heading"]');

src/cdk/dialog/dialog.spec.ts

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
1+
import {Directionality} from '@angular/cdk/bidi';
2+
import {A, ESCAPE} from '@angular/cdk/keycodes';
3+
import {Overlay, OverlayContainer, ScrollDispatcher} from '@angular/cdk/overlay';
4+
import {_supportsShadowDom} from '@angular/cdk/platform';
15
import {
2-
ComponentFixture,
3-
fakeAsync,
4-
flushMicrotasks,
5-
TestBed,
6-
tick,
7-
flush,
8-
} from '@angular/core/testing';
6+
createKeyboardEvent,
7+
dispatchEvent,
8+
dispatchKeyboardEvent,
9+
} from '@angular/cdk/testing/private';
10+
import {Location} from '@angular/common';
11+
import {SpyLocation} from '@angular/common/testing';
912
import {
1013
ChangeDetectionStrategy,
1114
Component,
1215
ComponentRef,
1316
Directive,
14-
inject,
1517
Inject,
1618
InjectionToken,
1719
Injector,
1820
TemplateRef,
1921
ViewChild,
2022
ViewContainerRef,
2123
ViewEncapsulation,
24+
inject,
2225
} from '@angular/core';
23-
import {By} from '@angular/platform-browser';
24-
import {Location} from '@angular/common';
25-
import {SpyLocation} from '@angular/common/testing';
26-
import {Directionality} from '@angular/cdk/bidi';
27-
import {Overlay, OverlayContainer, ScrollDispatcher} from '@angular/cdk/overlay';
28-
import {A, ESCAPE} from '@angular/cdk/keycodes';
29-
import {_supportsShadowDom} from '@angular/cdk/platform';
3026
import {
31-
dispatchKeyboardEvent,
32-
createKeyboardEvent,
33-
dispatchEvent,
34-
} from '@angular/cdk/testing/private';
27+
ComponentFixture,
28+
TestBed,
29+
fakeAsync,
30+
flush,
31+
flushMicrotasks,
32+
tick,
33+
} from '@angular/core/testing';
34+
import {By} from '@angular/platform-browser';
3535
import {Subject} from 'rxjs';
3636
import {DIALOG_DATA, Dialog, DialogModule, DialogRef} from './index';
3737

@@ -282,17 +282,20 @@ describe('Dialog', () => {
282282
const spy = jasmine.createSpy('backdropClick spy');
283283
dialogRef.backdropClick.subscribe(spy);
284284
viewContainerFixture.detectChanges();
285+
flush();
285286

286287
const backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
287288

288289
backdrop.click();
289290
viewContainerFixture.detectChanges();
291+
flush();
290292
expect(spy).toHaveBeenCalledTimes(1);
291293

292294
// Additional clicks after the dialog has closed should not be emitted
293295
dialogRef.disableClose = false;
294296
backdrop.click();
295297
viewContainerFixture.detectChanges();
298+
flush();
296299
expect(spy).toHaveBeenCalledTimes(1);
297300
}));
298301

@@ -303,6 +306,7 @@ describe('Dialog', () => {
303306
dialogRef.keydownEvents.subscribe(spy);
304307

305308
viewContainerFixture.detectChanges();
309+
flush();
306310

307311
let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement;
308312
let container = overlayContainerElement.querySelector('cdk-dialog-container') as HTMLElement;
@@ -757,9 +761,11 @@ describe('Dialog', () => {
757761
fakeAsync(() => {
758762
const templateInjectFixture = TestBed.createComponent(TemplateInjectorParentComponent);
759763
templateInjectFixture.detectChanges();
764+
flush();
760765

761766
dialog.open(templateInjectFixture.componentInstance.templateRef);
762767
templateInjectFixture.detectChanges();
768+
flush();
763769

764770
expect(templateInjectFixture.componentInstance.innerComponentValue).toBe(
765771
'hello from parent component',
@@ -840,7 +846,7 @@ describe('Dialog', () => {
840846
});
841847

842848
viewContainerFixture.detectChanges();
843-
flushMicrotasks();
849+
flush();
844850

845851
expect(document.activeElement!.tagName)
846852
.withContext('Expected first tabbable element (input) in the dialog to be focused.')
@@ -910,17 +916,15 @@ describe('Dialog', () => {
910916

911917
let dialogRef = dialog.open(PizzaMsg, {viewContainerRef: testViewContainerRef});
912918

913-
flushMicrotasks();
914919
viewContainerFixture.detectChanges();
915-
flushMicrotasks();
920+
flush();
916921

917922
expect(document.activeElement!.id).not.toBe(
918923
'dialog-trigger',
919924
'Expected the focus to change when dialog was opened.',
920925
);
921926

922927
dialogRef.close();
923-
flushMicrotasks();
924928
viewContainerFixture.detectChanges();
925929
flush();
926930

@@ -939,18 +943,18 @@ describe('Dialog', () => {
939943
viewContainerFixture.destroy();
940944
const fixture = TestBed.createComponent(ShadowDomComponent);
941945
fixture.detectChanges();
946+
flush();
942947
const button = fixture.debugElement.query(By.css('button'))!.nativeElement;
943948

944949
button.focus();
945950

946951
const dialogRef = dialog.open(PizzaMsg);
947-
flushMicrotasks();
948952
fixture.detectChanges();
949-
flushMicrotasks();
953+
flush();
950954

951955
const spy = spyOn(button, 'focus').and.callThrough();
952956
dialogRef.close();
953-
flushMicrotasks();
957+
flush();
954958
fixture.detectChanges();
955959
tick(500);
956960

@@ -994,7 +998,7 @@ describe('Dialog', () => {
994998
dialog.open(DialogWithoutFocusableElements);
995999

9961000
viewContainerFixture.detectChanges();
997-
flushMicrotasks();
1001+
flush();
9981002

9991003
expect(document.activeElement!.tagName.toLowerCase())
10001004
.withContext('Expected dialog container to be focused.')
@@ -1013,14 +1017,12 @@ describe('Dialog', () => {
10131017
restoreFocus: false,
10141018
});
10151019

1016-
flushMicrotasks();
10171020
viewContainerFixture.detectChanges();
1018-
flushMicrotasks();
1021+
flush();
10191022

10201023
expect(document.activeElement!.id).not.toBe('dialog-trigger');
10211024

10221025
dialogRef.close();
1023-
flushMicrotasks();
10241026
viewContainerFixture.detectChanges();
10251027
flush();
10261028

src/material/bottom-sheet/bottom-sheet.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import {OverlayContainer, ScrollStrategy} from '@angular/cdk/overlay';
44
import {_supportsShadowDom} from '@angular/cdk/platform';
55
import {ViewportRuler} from '@angular/cdk/scrolling';
66
import {
7-
dispatchKeyboardEvent,
87
createKeyboardEvent,
98
dispatchEvent,
9+
dispatchKeyboardEvent,
1010
} from '@angular/cdk/testing/private';
1111
import {Location} from '@angular/common';
1212
import {SpyLocation} from '@angular/common/testing';
@@ -23,11 +23,11 @@ import {
2323
} from '@angular/core';
2424
import {
2525
ComponentFixture,
26+
TestBed,
2627
fakeAsync,
2728
flush,
2829
flushMicrotasks,
2930
inject,
30-
TestBed,
3131
tick,
3232
} from '@angular/core/testing';
3333
import {By} from '@angular/platform-browser';
@@ -640,7 +640,7 @@ describe('MatBottomSheet', () => {
640640
});
641641

642642
viewContainerFixture.detectChanges();
643-
flushMicrotasks();
643+
flush();
644644

645645
expect(document.activeElement!.tagName)
646646
.withContext('Expected first tabbable element (input) in the dialog to be focused.')

src/material/dialog/dialog.spec.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,9 +1276,8 @@ describe('MDC-based MatDialog', () => {
12761276

12771277
let dialogRef = dialog.open(PizzaMsg, {viewContainerRef: testViewContainerRef});
12781278

1279-
flushMicrotasks();
12801279
viewContainerFixture.detectChanges();
1281-
flushMicrotasks();
1280+
flush();
12821281

12831282
expect(document.activeElement!.id).not.toBe(
12841283
'dialog-trigger',
@@ -1291,7 +1290,6 @@ describe('MDC-based MatDialog', () => {
12911290
'Expected the focus not to have changed before the animation finishes.',
12921291
);
12931292

1294-
flushMicrotasks();
12951293
viewContainerFixture.detectChanges();
12961294
tick(500);
12971295

@@ -1310,18 +1308,17 @@ describe('MDC-based MatDialog', () => {
13101308
viewContainerFixture.destroy();
13111309
const fixture = TestBed.createComponent(ShadowDomComponent);
13121310
fixture.detectChanges();
1311+
flush();
13131312
const button = fixture.debugElement.query(By.css('button'))!.nativeElement;
13141313

13151314
button.focus();
13161315

13171316
const dialogRef = dialog.open(PizzaMsg);
1318-
flushMicrotasks();
13191317
fixture.detectChanges();
1320-
flushMicrotasks();
1318+
flush();
13211319

13221320
const spy = spyOn(button, 'focus').and.callThrough();
13231321
dialogRef.close();
1324-
flushMicrotasks();
13251322
fixture.detectChanges();
13261323
tick(500);
13271324

@@ -1539,17 +1536,15 @@ describe('MDC-based MatDialog', () => {
15391536
restoreFocus: false,
15401537
});
15411538

1542-
flushMicrotasks();
15431539
viewContainerFixture.detectChanges();
1544-
flushMicrotasks();
1540+
flush();
15451541

15461542
expect(document.activeElement!.id).not.toBe(
15471543
'dialog-trigger',
15481544
'Expected the focus to change when dialog was opened.',
15491545
);
15501546

15511547
dialogRef.close();
1552-
flushMicrotasks();
15531548
viewContainerFixture.detectChanges();
15541549
tick(500);
15551550

@@ -1574,9 +1569,8 @@ describe('MDC-based MatDialog', () => {
15741569

15751570
const dialogRef = dialog.open(PizzaMsg, {viewContainerRef: testViewContainerRef});
15761571

1577-
flushMicrotasks();
15781572
viewContainerFixture.detectChanges();
1579-
flushMicrotasks();
1573+
flush();
15801574

15811575
expect(document.activeElement!.id).not.toBe(
15821576
'dialog-trigger',
@@ -1591,7 +1585,6 @@ describe('MDC-based MatDialog', () => {
15911585
.withContext('Expected focus to be on the alternate button.')
15921586
.toBe('other-button');
15931587

1594-
flushMicrotasks();
15951588
viewContainerFixture.detectChanges();
15961589
flush();
15971590

0 commit comments

Comments
 (0)