зеркало из https://github.com/mozilla/gecko-dev.git
250 строки
8.1 KiB
HTML
250 строки
8.1 KiB
HTML
<!DOCTYPE HTML>
|
|
<!-- Any copyright is dedicated to the Public Domain.
|
|
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title><!-- Shadow Parts issue with xul/xbl domparser --></title>
|
|
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
|
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
|
<link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
|
<script>
|
|
const { BrowserTestUtils } = ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
|
|
const DEFAULT_SECTION_NAMES = ["one", "two", "three"];
|
|
|
|
function makeButton({ name, deckId }) {
|
|
let button = document.createElement("button", { is: "named-deck-button" });
|
|
button.setAttribute("name", name);
|
|
button.deckId = deckId;
|
|
button.textContent = name.toUpperCase();
|
|
return button;
|
|
}
|
|
|
|
function makeSection({ name }) {
|
|
let view = document.createElement("section");
|
|
view.setAttribute("name", name);
|
|
view.textContent = name + name;
|
|
return view;
|
|
}
|
|
|
|
function addSection({ name, deck, buttons }) {
|
|
let button = makeButton({ name, deckId: deck.id });
|
|
buttons.appendChild(button);
|
|
let view = makeSection({ name });
|
|
deck.appendChild(view);
|
|
return { button, view };
|
|
}
|
|
|
|
async function runTests({ deck, buttons }) {
|
|
const selectedSlot = deck.shadowRoot.querySelector('slot[name="selected"]');
|
|
const getButtonByName = name => buttons.querySelector(`[name="${name}"]`);
|
|
|
|
function checkState(name, count, empty = false) {
|
|
// Check that the right view is selected.
|
|
is(deck.selectedViewName, name, "The right view is selected");
|
|
|
|
// Verify there's one element in the slot.
|
|
let slottedEls = selectedSlot.assignedElements();
|
|
if (empty) {
|
|
is(slottedEls.length, 0, "The deck is empty");
|
|
} else {
|
|
is(slottedEls.length, 1, "There's one visible view");
|
|
is(
|
|
slottedEls[0].getAttribute("name"),
|
|
name,
|
|
"The correct view is in the slot"
|
|
);
|
|
}
|
|
|
|
// Check that the hidden properties are set.
|
|
let sections = deck.querySelectorAll("section");
|
|
is(sections.length, count, "There are the right number of sections");
|
|
for (let section of sections) {
|
|
let sectionName = section.getAttribute("name");
|
|
if (sectionName == name) {
|
|
is(section.slot, "selected", `${sectionName} is visible`);
|
|
} else {
|
|
is(section.slot, "", `${sectionName} is hidden`);
|
|
}
|
|
}
|
|
|
|
// Check the right button is selected.
|
|
is(buttons.children.length, count, "There are the right number of buttons");
|
|
for (let button of buttons.children) {
|
|
let buttonName = button.getAttribute("name");
|
|
let selected = buttonName == name;
|
|
is(
|
|
button.hasAttribute("selected"),
|
|
selected,
|
|
`${buttonName} is ${selected ? "selected" : "not selected"}`
|
|
);
|
|
}
|
|
}
|
|
|
|
// Check that the first view is selected by default.
|
|
checkState("one", 3);
|
|
|
|
// Switch to the third view.
|
|
info("Switch to section three");
|
|
getButtonByName("three").click();
|
|
checkState("three", 3);
|
|
|
|
// Add a new section, nothing changes.
|
|
info("Add section last");
|
|
let last = addSection({ name: "last", deck, buttons });
|
|
checkState("three", 4);
|
|
|
|
// We can switch to the new section.
|
|
last.button.click();
|
|
info("Switch to section last");
|
|
checkState("last", 4);
|
|
|
|
info("Switch view with selectedViewName");
|
|
let shown = BrowserTestUtils.waitForEvent(deck, "view-changed");
|
|
deck.selectedViewName = "two";
|
|
await shown;
|
|
checkState("two", 4);
|
|
|
|
info("Switch back to the last view to test removing selected view");
|
|
shown = BrowserTestUtils.waitForEvent(deck, "view-changed");
|
|
deck.setAttribute("selected-view", "last");
|
|
await shown;
|
|
checkState("last", 4);
|
|
|
|
// Removing the selected section leaves the selected slot empty.
|
|
info("Remove section last");
|
|
last.button.remove();
|
|
last.view.remove();
|
|
|
|
info("Should not have any selected views");
|
|
checkState("last", 3, true);
|
|
|
|
// Setting a missing view will give a "view-changed" event.
|
|
info("Set view to a missing name");
|
|
let hidden = BrowserTestUtils.waitForEvent(deck, "view-changed");
|
|
deck.selectedViewName = "missing";
|
|
await hidden;
|
|
checkState("missing", 3, true);
|
|
|
|
// Adding the view won't trigger "view-changed", but the view will slotted.
|
|
info("Add the missing view, it should be shown");
|
|
shown = BrowserTestUtils.waitForEvent(selectedSlot, "slotchange");
|
|
let viewChangedEvent = false;
|
|
let viewChangedFn = () => {
|
|
viewChangedEvent = true;
|
|
};
|
|
deck.addEventListener("view-changed", viewChangedFn);
|
|
addSection({ name: "missing", deck, buttons });
|
|
await shown;
|
|
deck.removeEventListener("view-changed", viewChangedFn);
|
|
ok(!viewChangedEvent, "The view-changed event didn't fire");
|
|
checkState("missing", 4);
|
|
}
|
|
|
|
async function setup({ beAsync, first, deckId }) {
|
|
// Make the deck and buttons.
|
|
const deck = document.createElement("named-deck");
|
|
deck.id = deckId;
|
|
for (let name of DEFAULT_SECTION_NAMES) {
|
|
deck.appendChild(makeSection({ name }));
|
|
}
|
|
const buttons = document.createElement("button-group");
|
|
for (let name of DEFAULT_SECTION_NAMES) {
|
|
buttons.appendChild(makeButton({ name, deckId }));
|
|
}
|
|
|
|
let ordered;
|
|
if (first == "deck") {
|
|
ordered = [deck, buttons];
|
|
} else if (first == "buttons") {
|
|
ordered = [buttons, deck];
|
|
} else {
|
|
throw new Error("Invalid order");
|
|
}
|
|
|
|
// Insert them in the specified order, possibly async.
|
|
document.body.appendChild(ordered.shift());
|
|
if (beAsync) {
|
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
}
|
|
document.body.appendChild(ordered.shift());
|
|
|
|
return { deck, buttons };
|
|
}
|
|
|
|
add_task(async function testNamedDeckAndButtons() {
|
|
// Check adding the deck first.
|
|
dump("Running deck first tests synchronously");
|
|
await runTests(await setup({ beAsync: false, first: "deck", deckId: "deck-sync" }));
|
|
dump("Running deck first tests asynchronously");
|
|
await runTests(await setup({ beAsync: true, first: "deck", deckId: "deck-async" }));
|
|
|
|
// Check adding the buttons first.
|
|
dump("Running buttons first tests synchronously");
|
|
await runTests(await setup({ beAsync: false, first: "buttons", deckId: "buttons-sync" }));
|
|
dump("Running buttons first tests asynchronously");
|
|
await runTests(await setup({ beAsync: true, first: "buttons", deckId: "buttons-async" }));
|
|
});
|
|
|
|
add_task(async function testFocusAndClickMixing() {
|
|
const waitForAnimationFrame = () =>
|
|
new Promise(r => requestAnimationFrame(r));
|
|
const sendTab = (e = {}) => {
|
|
synthesizeKey("VK_TAB", e);
|
|
return waitForAnimationFrame();
|
|
};
|
|
|
|
const firstButton = document.createElement("button");
|
|
document.body.append(firstButton);
|
|
|
|
const { deck, buttons: buttonGroup } = await setup({
|
|
beAsync: false,
|
|
first: "buttons",
|
|
deckId: "focus-click-mixing",
|
|
});
|
|
const buttons = buttonGroup.children;
|
|
firstButton.focus();
|
|
const secondButton = document.createElement("button");
|
|
document.body.append(secondButton);
|
|
|
|
await sendTab();
|
|
is(document.activeElement, buttons[0], "first deck button is focused");
|
|
is(deck.selectedViewName, "one", "first view is shown");
|
|
|
|
await sendTab();
|
|
is(document.activeElement, secondButton, "focus moves out of group");
|
|
|
|
await sendTab({ shiftKey: true });
|
|
is(document.activeElement, buttons[0], "focus moves back to first button");
|
|
|
|
// Click on another tab button, this should make it the focusable button.
|
|
synthesizeMouseAtCenter(buttons[1], {});
|
|
await waitForAnimationFrame();
|
|
|
|
is(deck.selectedViewName, "two", "second view is shown");
|
|
|
|
if (document.activeElement != buttons[1]) {
|
|
// On Mac the button isn't focused on click, but it is on Windows/Linux.
|
|
await sendTab();
|
|
}
|
|
is(document.activeElement, buttons[1], "second deck button is focusable");
|
|
|
|
await sendTab();
|
|
is(document.activeElement, secondButton, "focus moved to second plain button");
|
|
|
|
await sendTab({ shiftKey: true });
|
|
is(document.activeElement, buttons[1], "second deck button is focusable");
|
|
|
|
await sendTab({ shiftKey: true });
|
|
is(
|
|
document.activeElement,
|
|
firstButton,
|
|
"next shift-tab moves out of button group"
|
|
);
|
|
});
|
|
</script>
|
|
</head>
|
|
<body>
|
|
</body>
|
|
</html>
|