Skip to content

Commit 4b7e52d

Browse files
devversiontinayuangao
authored andcommitted
fix(interactivity-checker): improve robustness of isTabbable (#1950)
* fix(focus-trap): improve robustness * Address feedback * Remove extra blank line. * Address additional feedback * Change timeout delay
1 parent 76a8d79 commit 4b7e52d

File tree

12 files changed

+449
-60
lines changed

12 files changed

+449
-60
lines changed

src/demo-app/demo-app-module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {PortalDemo, ScienceJoke} from './portal/portal-demo';
3535
import {MenuDemo} from './menu/menu-demo';
3636
import {TabsDemo, SunnyTabContent, RainyTabContent, FoggyTabContent} from './tabs/tabs-demo';
3737
import {ProjectionDemo, ProjectionTestComponent} from './projection/projection-demo';
38+
import {PlatformDemo} from './platform/platform-demo';
3839

3940
@NgModule({
4041
imports: [
@@ -86,6 +87,7 @@ import {ProjectionDemo, ProjectionTestComponent} from './projection/projection-d
8687
SunnyTabContent,
8788
RainyTabContent,
8889
FoggyTabContent,
90+
PlatformDemo
8991
],
9092
entryComponents: [
9193
DemoApp,

src/demo-app/demo-app/demo-app.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export class DemoApp {
4747
{name: 'Snack Bar', route: 'snack-bar'},
4848
{name: 'Tabs', route: 'tabs'},
4949
{name: 'Toolbar', route: 'toolbar'},
50-
{name: 'Tooltip', route: 'tooltip'}
50+
{name: 'Tooltip', route: 'tooltip'},
51+
{name: 'Platform', route: 'platform'}
5152
];
5253
}

src/demo-app/demo-app/routes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {TooltipDemo} from '../tooltip/tooltip-demo';
3030
import {SnackBarDemo} from '../snack-bar/snack-bar-demo';
3131
import {ProjectionDemo} from '../projection/projection-demo';
3232
import {TABS_DEMO_ROUTES} from '../tabs/routes';
33+
import {PlatformDemo} from '../platform/platform-demo';
3334

3435
export const DEMO_APP_ROUTES: Routes = [
3536
{path: '', component: Home},
@@ -62,4 +63,5 @@ export const DEMO_APP_ROUTES: Routes = [
6263
{path: 'dialog', component: DialogDemo},
6364
{path: 'tooltip', component: TooltipDemo},
6465
{path: 'snack-bar', component: SnackBarDemo},
66+
{path: 'platform', component: PlatformDemo}
6567
];
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {Component} from '@angular/core';
2+
import {MdPlatform} from '@angular/material';
3+
4+
@Component({
5+
template: `
6+
<p>Is Android: {{ platform.ANDROID }}</p>
7+
<p>Is iOS: {{ platform.IOS }}</p>
8+
<p>Is Firefox: {{ platform.FIREFOX }}</p>
9+
<p>Is Blink: {{ platform.BLINK }}</p>
10+
<p>Is Webkit: {{ platform.WEBKIT }}</p>
11+
<p>Is Trident: {{ platform.TRIDENT }}</p>
12+
<p>Is Edge: {{ platform.EDGE }}</p>
13+
`
14+
})
15+
export class PlatformDemo {
16+
constructor(public platform: MdPlatform) {}
17+
}

src/lib/core/a11y/focus-trap.spec.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@ import {By} from '@angular/platform-browser';
33
import {Component} from '@angular/core';
44
import {FocusTrap} from './focus-trap';
55
import {InteractivityChecker} from './interactivity-checker';
6+
import {MdPlatform} from '../platform/platform';
67

78

89
describe('FocusTrap', () => {
10+
911
describe('with default element', () => {
12+
1013
let fixture: ComponentFixture<FocusTrapTestApp>;
1114
let focusTrapInstance: FocusTrap;
15+
let platform: MdPlatform = new MdPlatform();
1216

1317
beforeEach(async(() => {
1418
TestBed.configureTestingModule({
1519
declarations: [FocusTrap, FocusTrapTestApp],
16-
providers: [InteractivityChecker]
20+
providers: [InteractivityChecker, MdPlatform]
1721
});
1822

1923
TestBed.compileComponents();
@@ -38,8 +42,11 @@ describe('FocusTrap', () => {
3842
// focus event handler directly.
3943
focusTrapInstance.focusLastTabbableElement();
4044

45+
// In iOS button elements are never tabbable, so the last element will be the input.
46+
let lastElement = platform.IOS ? 'input' : 'button';
47+
4148
expect(document.activeElement.nodeName.toLowerCase())
42-
.toBe('button', 'Expected button element to be focused');
49+
.toBe(lastElement, `Expected ${lastElement} element to be focused`);
4350
});
4451
});
4552

@@ -50,7 +57,7 @@ describe('FocusTrap', () => {
5057
beforeEach(async(() => {
5158
TestBed.configureTestingModule({
5259
declarations: [FocusTrap, FocusTrapTargetTestApp],
53-
providers: [InteractivityChecker]
60+
providers: [InteractivityChecker, MdPlatform]
5461
});
5562

5663
TestBed.compileComponents();

src/lib/core/a11y/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import {NgModule, ModuleWithProviders} from '@angular/core';
22
import {FocusTrap} from './focus-trap';
33
import {MdLiveAnnouncer} from './live-announcer';
44
import {InteractivityChecker} from './interactivity-checker';
5+
import {PlatformModule} from '../platform/platform';
56

67
export const A11Y_PROVIDERS = [MdLiveAnnouncer, InteractivityChecker];
78

89
@NgModule({
10+
imports: [PlatformModule],
911
declarations: [FocusTrap],
1012
exports: [FocusTrap],
1113
})

0 commit comments

Comments
 (0)