lion/packages/overlays/test/ManagedGlobalOverlayController.test.js
Thomas Allmer 224f794a1e feat(overlays): align Overlays API + add DynamicOverlay
Co-authored-by: Gerjan van Geest <Gerjan.van.Geest@ing.com>
Co-authored-by: Thijs Louisse <Thijs.Louisse@ing.com>"
2019-09-25 11:39:38 +02:00

281 lines
8 KiB
JavaScript

import { expect, html } from '@open-wc/testing';
import { GlobalOverlayController } from '../src/GlobalOverlayController.js';
import { overlays } from '../src/overlays.js';
function getRootNode() {
return document.querySelector('.global-overlays');
}
function getRenderedContainers() {
const rootNode = getRootNode();
return rootNode ? Array.from(rootNode.children) : [];
}
function getRenderedContainer(index) {
return getRenderedContainers()[index];
}
function getRenderedOverlay(index) {
const container = getRenderedContainer(index);
return container ? container.children[0] : null;
}
function cleanup() {
document.body.removeAttribute('style');
overlays.teardown();
}
describe('Managed GlobalOverlayController', () => {
afterEach(cleanup);
describe('hasBackdrop', () => {
it('adds and stacks backdrops if .hasBackdrop is enabled', async () => {
const ctrl0 = overlays.add(
new GlobalOverlayController({
hasBackdrop: true,
contentTemplate: () => html`
<p>Content0</p>
`,
}),
);
await ctrl0.show();
expect(ctrl0.backdropNode).to.have.class('global-overlays__backdrop');
const ctrl1 = overlays.add(
new GlobalOverlayController({
hasBackdrop: false,
contentTemplate: () => html`
<p>Content1</p>
`,
}),
);
await ctrl1.show();
expect(ctrl0.backdropNode).to.have.class('global-overlays__backdrop');
expect(ctrl1.backdropNode).to.be.undefined;
const ctrl2 = overlays.add(
new GlobalOverlayController({
hasBackdrop: true,
contentTemplate: () => html`
<p>Content2</p>
`,
}),
);
await ctrl2.show();
expect(ctrl0.backdropNode).to.have.class('global-overlays__backdrop');
expect(ctrl1.backdropNode).to.be.undefined;
expect(ctrl2.backdropNode).to.have.class('global-overlays__backdrop');
});
});
describe('isBlocking', () => {
it('prevents showing of other overlays', async () => {
const ctrl0 = overlays.add(
new GlobalOverlayController({
isBlocking: false,
contentTemplate: () => html`
<p>Content0</p>
`,
}),
);
await ctrl0.show();
const ctrl1 = overlays.add(
new GlobalOverlayController({
isBlocking: false,
contentTemplate: () => html`
<p>Content1</p>
`,
}),
);
await ctrl1.show();
const ctrl2 = overlays.add(
new GlobalOverlayController({
isBlocking: true,
contentTemplate: () => html`
<p>Content2</p>
`,
}),
);
await ctrl2.show();
const ctrl3 = overlays.add(
new GlobalOverlayController({
isBlocking: false,
contentTemplate: () => html`
<p>Content3</p>
`,
}),
);
await ctrl3.show();
expect(getRenderedOverlay(0)).to.not.be.displayed;
expect(getRenderedOverlay(1)).to.not.be.displayed;
expect(getRenderedOverlay(2)).to.be.displayed;
expect(getRenderedOverlay(3)).to.not.be.displayed;
});
it('keeps backdrop status when used in combination with blocking', async () => {
const ctrl0 = overlays.add(
new GlobalOverlayController({
isBlocking: false,
hasBackdrop: true,
contentTemplate: () => html`
<p>Content0</p>
`,
}),
);
await ctrl0.show();
const ctrl1 = overlays.add(
new GlobalOverlayController({
isBlocking: false,
hasBackdrop: true,
contentTemplate: () => html`
<p>Content1</p>
`,
}),
);
await ctrl1.show();
await ctrl1.hide();
expect(ctrl0.hasActiveBackdrop).to.be.true;
expect(ctrl1.hasActiveBackdrop).to.be.false;
await ctrl1.show();
expect(ctrl0.hasActiveBackdrop).to.be.true;
expect(ctrl1.hasActiveBackdrop).to.be.true;
});
});
describe('trapsKeyboardFocus (for a11y)', () => {
it('adds attributes inert and aria-hidden="true" on all siblings of rootNode if an overlay is shown', async () => {
const ctrl = overlays.add(
new GlobalOverlayController({
trapsKeyboardFocus: true,
contentTemplate: () => html`
<p>Content</p>
`,
}),
);
const sibling1 = document.createElement('div');
const sibling2 = document.createElement('div');
document.body.insertBefore(sibling1, getRootNode());
document.body.appendChild(sibling2);
await ctrl.show();
[sibling1, sibling2].forEach(sibling => {
expect(sibling).to.have.attribute('aria-hidden', 'true');
expect(sibling).to.have.attribute('inert');
});
expect(getRenderedOverlay(0).hasAttribute('aria-hidden')).to.be.false;
expect(getRenderedOverlay(0).hasAttribute('inert')).to.be.false;
await ctrl.hide();
[sibling1, sibling2].forEach(sibling => {
expect(sibling).to.not.have.attribute('aria-hidden');
expect(sibling).to.not.have.attribute('inert');
});
// cleanup
document.body.removeChild(sibling1);
document.body.removeChild(sibling2);
});
/**
* style.userSelect:
* - chrome: 'none'
* - rest: undefined
*
* style.pointerEvents:
* - chrome: auto
* - IE11: visiblePainted
*/
it('disables pointer events and selection on inert elements', async () => {
const ctrl = overlays.add(
new GlobalOverlayController({
trapsKeyboardFocus: true,
contentTemplate: () => html`
<p>Content</p>
`,
}),
);
// show+hide are needed to create a root node
await ctrl.show();
await ctrl.hide();
const sibling1 = document.createElement('div');
const sibling2 = document.createElement('div');
document.body.insertBefore(sibling1, getRootNode());
document.body.appendChild(sibling2);
await ctrl.show();
[sibling1, sibling2].forEach(sibling => {
expect(window.getComputedStyle(sibling).userSelect).to.be.oneOf(['none', undefined]);
expect(window.getComputedStyle(sibling).pointerEvents).to.equal('none');
});
expect(window.getComputedStyle(getRenderedOverlay(0)).userSelect).to.be.oneOf([
'auto',
undefined,
]);
expect(window.getComputedStyle(getRenderedOverlay(0)).pointerEvents).to.be.oneOf([
'auto',
'visiblePainted',
]);
await ctrl.hide();
[sibling1, sibling2].forEach(sibling => {
expect(window.getComputedStyle(sibling).userSelect).to.be.oneOf(['auto', undefined]);
expect(window.getComputedStyle(sibling).pointerEvents).to.be.oneOf([
'auto',
'visiblePainted',
]);
});
// cleanup
document.body.removeChild(sibling1);
document.body.removeChild(sibling2);
});
it('keeps focus within overlay with multiple overlays with all traps on true', async () => {
const ctrl0 = overlays.add(
new GlobalOverlayController({
trapsKeyboardFocus: true,
contentTemplate: () => html`
<div>
<input id="input0" /><button id="button0">Button0</button><a id="a0">Link0</a>
</div>
`,
}),
);
const ctrl1 = overlays.add(
new GlobalOverlayController({
trapsKeyboardFocus: true,
contentTemplate: () => html`
<div>
<input id="input1" /><button id="button1">Button1</button><a id="a1">Link1</a>
</div>
`,
}),
);
await ctrl0.show();
await ctrl1.show();
expect(ctrl0.hasActiveTrapsKeyboardFocus).to.be.false;
expect(ctrl1.hasActiveTrapsKeyboardFocus).to.be.true;
await ctrl1.hide();
expect(ctrl0.hasActiveTrapsKeyboardFocus).to.be.true;
expect(ctrl1.hasActiveTrapsKeyboardFocus).to.be.false;
});
});
});