Skip to content

Commit 6129999

Browse files
Westbrook JohnsonWestbrook
authored andcommitted
test(overlay): extend overlay type coverage
1 parent 51623fc commit 6129999

File tree

5 files changed

+132
-20
lines changed

5 files changed

+132
-20
lines changed

karma.conf.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ module.exports = (config) => {
5454
coverageIstanbulReporter: {
5555
thresholds: {
5656
global: {
57-
statements: 97,
58-
branches: 93,
59-
functions: 97,
60-
lines: 97,
57+
statements: 98,
58+
branches: 94,
59+
functions: 98,
60+
lines: 98,
6161
},
6262
},
6363
},

packages/overlay/src/active-overlay.css

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@ sp-theme,
4949
#contents {
5050
display: inline-block;
5151
pointer-events: none;
52-
animation-duration: var(--spectrum-global-animation-duration-200);
53-
animation-timing-function: var(--spectrum-global-animation-ease-out);
52+
animation-duration: var(--spectrum-global-animation-duration-200, 160ms);
53+
animation-timing-function: var(
54+
--spectrum-global-animation-ease-out,
55+
ease-out
56+
);
5457
opacity: 1;
5558
visibility: visible;
5659
}

packages/overlay/src/overlay-stack.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export class OverlayStack {
4040
private overlayHolder!: HTMLElement;
4141

4242
private initTabTrapping(): void {
43+
/* istanbul ignore if */
4344
if (this.document.body.shadowRoot) {
4445
this.canTabTrap = false;
4546
return;
@@ -87,6 +88,7 @@ export class OverlayStack {
8788
}
8889

8990
private startTabTrapping(): void {
91+
/* istanbul ignore if */
9092
if (!this.canTabTrap) {
9193
return;
9294
}
@@ -95,6 +97,7 @@ export class OverlayStack {
9597
}
9698

9799
private stopTabTrapping(): void {
100+
/* istanbul ignore if */
98101
if (!this.canTabTrap) {
99102
return;
100103
}

packages/overlay/test/overlay-trigger.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ describe('Overlay Trigger', () => {
601601
const mouseEnter = new MouseEvent('mouseenter');
602602
const mouseLeave = new MouseEvent('mouseleave');
603603
triggerShadowDiv.dispatchEvent(mouseEnter);
604+
await nextFrame();
604605
triggerShadowDiv.dispatchEvent(mouseLeave);
605606

606607
await waitUntil(

packages/overlay/test/overlay.test.ts

Lines changed: 119 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ import {
2424
waitUntil,
2525
} from '@open-wc/testing';
2626

27+
const keyboardEvent = (code: string, shiftKey = false): KeyboardEvent =>
28+
new KeyboardEvent('keydown', {
29+
bubbles: true,
30+
composed: true,
31+
cancelable: true,
32+
code,
33+
shiftKey,
34+
});
35+
const tabEvent = keyboardEvent('Tab');
36+
const shiftTabEvent = keyboardEvent('Tab', true);
37+
2738
describe('Overlays', () => {
2839
let testDiv!: HTMLDivElement;
2940
let openOverlays: (() => void)[] = [];
@@ -124,11 +135,13 @@ describe('Overlays', () => {
124135

125136
expect(button).to.exist;
126137

127-
Overlay.open(button, 'click', outerPopover, {
128-
delayed: false,
129-
placement,
130-
offset: 10,
131-
});
138+
openOverlays.push(
139+
await Overlay.open(button, 'click', outerPopover, {
140+
delayed: false,
141+
placement,
142+
offset: 10,
143+
})
144+
);
132145

133146
// Wait for the DOM node to be stolen and reparented into the overlay
134147
await waitForPredicate(
@@ -198,10 +211,12 @@ describe('Overlays', () => {
198211

199212
expect(button).to.exist;
200213

201-
await Overlay.open(button, 'click', outerPopover, {
202-
delayed: true,
203-
offset: 10,
204-
});
214+
openOverlays.push(
215+
await Overlay.open(button, 'click', outerPopover, {
216+
delayed: true,
217+
offset: 10,
218+
})
219+
);
205220

206221
// Wait for the DOM node to be stolen and reparented into the overlay
207222
await waitUntil(
@@ -357,11 +372,13 @@ describe('Overlays', () => {
357372

358373
const dialog = el.querySelector('sp-dialog') as Dialog;
359374

360-
Overlay.open(el, 'click', dialog, {
361-
delayed: false,
362-
placement: 'bottom',
363-
offset: 10,
364-
});
375+
openOverlays.push(
376+
await Overlay.open(el, 'click', dialog, {
377+
delayed: false,
378+
placement: 'bottom',
379+
offset: 10,
380+
})
381+
);
365382

366383
await waitUntil(
367384
() =>
@@ -379,4 +396,92 @@ describe('Overlays', () => {
379396
'content is returned'
380397
);
381398
});
399+
400+
it('closes an inline overlay when tabbing past the content', async () => {
401+
const el = await fixture<HTMLDivElement>(html`
402+
<div>
403+
<button class="trigger">Trigger</button>
404+
<div class="content">
405+
<input />
406+
</div>
407+
</div>
408+
`);
409+
410+
const trigger = el.querySelector('.trigger') as HTMLElement;
411+
const content = el.querySelector('.content') as HTMLElement;
412+
413+
openOverlays.push(await Overlay.open(trigger, 'inline', content, {}));
414+
415+
await waitUntil(
416+
() => !!el.querySelector('span[tabindex="-1"]'),
417+
'returnFocusElement available'
418+
);
419+
420+
const overlays = document.querySelectorAll('active-overlay');
421+
const overlay = overlays[0];
422+
423+
expect(overlay).to.not.be.undefined;
424+
425+
trigger.dispatchEvent(tabEvent);
426+
427+
await waitUntil(
428+
() => !!el.querySelector('span[tabindex="-1"]'),
429+
'returnFocusElement persists on forward tab'
430+
);
431+
432+
content.dispatchEvent(shiftTabEvent);
433+
434+
expect(document.activeElement === overlay.returnFocusElement).to.be
435+
.true;
436+
437+
content.dispatchEvent(tabEvent);
438+
439+
await waitUntil(
440+
() => el.querySelector('span[tabindex="-1"]') === null,
441+
'returnFocusElement no longer available'
442+
);
443+
});
444+
445+
it('closes an inline overlay when tabbing before the trigger', async () => {
446+
const el = await fixture<HTMLDivElement>(html`
447+
<div>
448+
<button class="trigger">Trigger</button>
449+
<div class="content">
450+
<label>
451+
Content in an inline overlay.
452+
<input />
453+
</label>
454+
</div>
455+
</div>
456+
`);
457+
458+
const trigger = el.querySelector('.trigger') as HTMLElement;
459+
const content = el.querySelector('.content') as HTMLElement;
460+
461+
openOverlays.push(await Overlay.open(trigger, 'inline', content, {}));
462+
463+
await waitUntil(
464+
() => !!el.querySelector('span[tabindex="-1"]'),
465+
'returnFocusElement available'
466+
);
467+
468+
const overlays = document.querySelectorAll('active-overlay');
469+
const overlay = overlays[0];
470+
471+
await elementUpdated(overlay);
472+
473+
trigger.dispatchEvent(tabEvent);
474+
475+
await waitUntil(
476+
() => !!el.querySelector('span[tabindex="-1"]'),
477+
'returnFocusElement persists on forward tab'
478+
);
479+
480+
trigger.dispatchEvent(shiftTabEvent);
481+
482+
await waitUntil(
483+
() => el.querySelector('span[tabindex="-1"]') === null,
484+
'returnFocusElement no longer available'
485+
);
486+
});
382487
});

0 commit comments

Comments
 (0)