Bug 1460613 - Add keyboard navigation for reveal link in slotted nodes. r=jdescottes,yzen

MozReview-Commit-ID: GAm1bJNcZPz

--HG--
extra : rebase_source : 9d98588cb45c08180cf3ff3ddcc9ba8afd889014
This commit is contained in:
Belén Albeza 2018-07-18 14:17:23 +02:00
Родитель f1e3db10e4
Коммит 738ccdfb90
4 изменённых файлов: 68 добавлений и 11 удалений

Просмотреть файл

@ -24,11 +24,27 @@ const TEST_URL = `data:text/html;charset=utf-8,
});
</script>`;
// Test reveal link with mouse navigation
add_task(async function() {
const checkWithMouse = checkRevealLink.bind(null, clickOnRevealLink);
await testRevealLink(checkWithMouse, checkWithMouse);
});
// Test reveal link with keyboard navigation (Enter and Spacebar keys)
add_task(async function() {
const checkWithEnter = checkRevealLink.bind(null,
keydownOnRevealLink.bind(null, "KEY_Enter"));
const checkWithSpacebar = checkRevealLink.bind(null,
keydownOnRevealLink.bind(null, " "));
await testRevealLink(checkWithEnter, checkWithSpacebar);
});
async function testRevealLink(revealFnFirst, revealFnSecond) {
await enableWebComponents();
const {inspector} = await openInspectorForURL(TEST_URL);
const {markup} = inspector;
const { inspector } = await openInspectorForURL(TEST_URL);
const { markup } = inspector;
info("Find and expand the test-component shadow DOM host.");
const hostFront = await getNodeFront("test-component", inspector);
@ -46,16 +62,16 @@ add_task(async function() {
const slotChildContainers = slotContainer.getChildContainers();
is(slotChildContainers.length, 2, "Expecting 2 slotted children");
await checkRevealLink(inspector, slotChildContainers[0].node);
await revealFnFirst(inspector, slotChildContainers[0].node);
is(inspector.selection.nodeFront.id, "el1", "The right node was selected");
is(hostContainer.getChildContainers()[1].node, inspector.selection.nodeFront);
await checkRevealLink(inspector, slotChildContainers[1].node);
await revealFnSecond(inspector, slotChildContainers[1].node);
is(inspector.selection.nodeFront.id, "el2", "The right node was selected");
is(hostContainer.getChildContainers()[2].node, inspector.selection.nodeFront);
});
}
async function checkRevealLink(inspector, node) {
async function checkRevealLink(actionFn, inspector, node) {
const slottedContainer = inspector.markup.getContainer(node, true);
info("Select the slotted container for the element");
await selectNode(node, inspector, "no-reason", true);
@ -63,8 +79,11 @@ async function checkRevealLink(inspector, node) {
ok(inspector.markup.getSelectedContainer().isSlotted(),
"The selected container is slotted");
const link = slottedContainer.elt.querySelector(".reveal-link");
is(link.getAttribute("role"), "link", "Reveal link has the role=link attribute");
info("Click on the reveal link and wait for the new node to be selected");
await clickOnRevealLink(inspector, slottedContainer);
await actionFn(inspector, slottedContainer);
const selectedFront = inspector.selection.nodeFront;
is(selectedFront, node, "The same node front is still selected");
ok(!inspector.selection.isSlotted(), "The selection is not the slotted version");

Просмотреть файл

@ -723,3 +723,28 @@ async function clickOnRevealLink(inspector, container) {
await onSelection;
}
/**
* Hit `key` on the reveal link in the provided slotted container.
* Will resolve when selection emits "new-node-front".
*/
async function keydownOnRevealLink(key, inspector, container) {
const revealLink = container.elt.querySelector(".reveal-link");
const win = inspector.markup.doc.defaultView;
const root = inspector.markup.getContainer(inspector.markup._rootNode);
root.elt.focus();
// we need to go through a ENTER + TAB key sequence to focus on
// the .reveal-link element with the keyboard
const revealFocused = once(revealLink, "focus");
EventUtils.synthesizeKey("KEY_Enter", {}, win);
EventUtils.synthesizeKey("KEY_Tab", {}, win);
info("Waiting for .reveal-link to be focused");
await revealFocused;
// hit `key` on the .reveal-link
const onSelection = inspector.selection.once("new-node-front");
EventUtils.synthesizeKey(key, {}, win);
await onSelection;
}

Просмотреть файл

@ -34,14 +34,25 @@ SlottedNodeContainer.prototype = extend(MarkupContainer.prototype, {
event.stopPropagation();
},
_revealFromSlot() {
const reason = "reveal-from-slot";
this.markup.inspector.selection.setNodeFront(this.node, { reason });
this.markup.telemetry.scalarSet("devtools.shadowdom.reveal_link_clicked", true);
},
_onKeyDown: function(event) {
const isActionKey = event.code == "Enter" || event.code == "Space";
if (event.target.classList.contains("reveal-link") && isActionKey) {
this._revealFromSlot();
}
},
onContainerClick: async function(event) {
if (!event.target.classList.contains("reveal-link")) {
return;
}
const reason = "reveal-from-slot";
this.markup.inspector.selection.setNodeFront(this.node, { reason });
this.markup.telemetry.scalarSet("devtools.shadowdom.reveal_link_clicked", true);
this._revealFromSlot();
},
isDraggable: function() {

Просмотреть файл

@ -30,8 +30,10 @@ SlottedNodeEditor.prototype = {
this.elt.appendChild(this.tag);
this.revealLink = doc.createElement("span");
this.revealLink.classList.add("reveal-link");
this.revealLink.setAttribute("role", "link");
this.revealLink.setAttribute("tabindex", -1);
this.revealLink.title = INSPECTOR_L10N.getStr("markupView.revealLink.tooltip");
this.revealLink.classList.add("reveal-link");
this.elt.appendChild(this.revealLink);
},