@uswds/uswds
Version:
Open source UI components and visual style guide for U.S. government websites
161 lines (131 loc) • 5.53 kB
JavaScript
const assert = require("assert");
const fs = require("fs");
const path = require("path");
const modal = require("../index");
const comboBox = require("../../../usa-combo-box/src/index");
const TEMPLATE = fs.readFileSync(path.join(__dirname, "template.html"));
const modalWindowSelector = () => document.querySelector(".usa-modal");
const bodySelector = () => document.body;
const openButton1Selector = () => document.querySelector("#open-button1");
const openButton2Selector = () => document.querySelector("#open-button2");
const comboListSelector = () => document.querySelector("#nestedCB--list");
const tests = [
{ name: "document.body", selector: bodySelector },
{ name: "modal", selector: modalWindowSelector },
];
tests.forEach(({ name, selector: containerSelector }) => {
describe(`Modal window initialized at ${name}`, () => {
const { body } = document;
let closeButton;
let modalWrapper;
let modalWindow;
let openButton1;
let openButton2;
let overlay;
let comboList;
let comboBoxToggleButton;
const isVisible = (el) => el.classList.contains("is-visible");
beforeEach(() => {
body.innerHTML = TEMPLATE;
modal.on(containerSelector());
comboBox.on(containerSelector());
modalWindow = modalWindowSelector();
closeButton = body.querySelector("#close-button");
modalWrapper = body.querySelector(".usa-modal-wrapper");
overlay = body.querySelector(".usa-modal-overlay");
openButton1 = openButton1Selector();
openButton2 = openButton2Selector();
comboList = comboListSelector();
comboBoxToggleButton = body.querySelector(".usa-combo-box__toggle-list");
});
afterEach(() => {
modal.off(containerSelector());
comboBox.off(containerSelector());
body.innerHTML = "";
body.className = "";
});
describe("Builds the modal HTML", () => {
it("creates new parent elements", () => {
assert.ok(modalWindow, "creates inner div");
assert.ok(overlay, "creates the overlay");
assert.ok(modalWrapper, "creates the outer div");
});
it('adds role="dialog" to modal parent', () => {
assert.strictEqual(modalWrapper.getAttribute("role"), "dialog");
});
it("moves aria-labelledby, aria-describedby, and id to the parent", () => {
assert.strictEqual(modalWindow.hasAttribute("aria-describedby"), false);
assert.strictEqual(modalWindow.hasAttribute("aria-labelledby"), false);
assert.strictEqual(modalWindow.hasAttribute("id"), false);
assert.strictEqual(modalWrapper.hasAttribute("aria-describedby"), true);
assert.strictEqual(modalWrapper.hasAttribute("aria-labelledby"), true);
assert.strictEqual(modalWrapper.getAttribute("id"), "modal");
});
it('sets tabindex="-1" to the modal window', () => {
assert.strictEqual(modalWindow.getAttribute("tabindex"), "-1");
});
it("moves the modal to the bottom of the DOM", () => {
assert.strictEqual(
body.lastElementChild.classList.contains("usa-modal-wrapper"),
true,
);
});
it('adds role="button" to any <a> opener, but not <button>', () => {
assert.strictEqual(openButton1.getAttribute("role"), "button");
assert.strictEqual(openButton2.hasAttribute("role"), false);
});
it("adds aria-controls to each opener", () => {
assert.strictEqual(openButton1.getAttribute("aria-controls"), "modal");
assert.strictEqual(openButton2.getAttribute("aria-controls"), "modal");
});
});
describe("When opened", () => {
beforeEach(() => {
openButton1.click();
});
it("makes the modal visible", () => {
assert.strictEqual(isVisible(modalWrapper), true);
});
it("focuses the modal window when opened", () => {
assert.strictEqual(document.activeElement, modalWindow);
});
it("makes all other page content invisible to screen readers", () => {
const activeContent = document.querySelectorAll(
"body > :not([aria-hidden])",
);
assert.strictEqual(activeContent.length, 1);
assert.strictEqual(activeContent[0], modalWrapper);
});
it("Allows event propagation and displays combobox list when toggle is clicked", () => {
comboBoxToggleButton.click();
assert.ok(!comboList.hidden, "should display the combobox option list");
});
});
describe("When closing", () => {
beforeEach(() => {
openButton2.click();
});
it("hides the modal when close button is clicked", () => {
closeButton.click();
assert.strictEqual(isVisible(modalWrapper), false);
});
it("closes the modal when the overlay is clicked", () => {
overlay.click();
assert.strictEqual(isVisible(modalWrapper), false);
});
it("sends focus to the element that opened it", () => {
closeButton.click();
assert.strictEqual(document.activeElement, openButton2);
});
it("restores other page content screen reader visibility", () => {
closeButton.click();
const activeContent = document.querySelectorAll(
"body > :not([aria-hidden])",
);
const staysHidden = document.getElementById("stays-hidden");
assert.strictEqual(activeContent.length, 4);
assert.strictEqual(staysHidden.hasAttribute("aria-hidden"), true);
});
});
});
});