Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTML: Sequential focus navigation with shadow dom #17523

Merged
merged 4 commits into from
Aug 15, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,14 @@
// <div #belowSlot tabindex=-1>
// <div #belowHost tabindex=0>

async_test(async (t) => {
promise_test(() => {
let elementsInFlatTreeOrder;
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
elementsInFlatTreeOrder = prepareDOM(document.body, false);
setTabIndex(elementsInFlatTreeOrder, -1);
setTabIndex([aboveHost, host, belowHost], 0);
resetFocus();
const expectedOrder = [aboveHost, host, belowHost];
for (let el of expectedOrder) {
await navigateFocusForward();
let focused = host.shadowRoot.activeElement ? host.shadowRoot.activeElement : document.activeElement;
t.step(() => { assert_equals(focused, el) });
}
t.done();
}, "Order when all tabindex=0 is and delegatesFocus = false");
return assertFocusOrder([aboveHost, host, belowHost]);
}, "Order when all elements in shadow tree has negative tabindex");
</script>
</body>
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// <div #belowSlot tabindex=0>
// <div #belowHost tabindex=0>

async_test(async (t) => {
promise_test(() => {
let elementsInFlatTreeOrder;
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
elementsInFlatTreeOrder = prepareDOM(document.body, false);
Expand All @@ -31,13 +31,7 @@
// Focus should move first according to flat tree order to #aboveHost and #host, then into #host's focus scope.
// It will then move to #slottedBelow because #slotBelow has tabindex=1 (though we actually won't focus on the slot),
// and then back to #host's focus scope again, finally getting out to the document focus scope.
const expectedOrder = [aboveHost, host, slottedBelow, aboveSlot, slottedAbove, belowSlot, belowHost];
for (let el of expectedOrder) {
await navigateFocusForward();
let focused = host.shadowRoot.activeElement ? host.shadowRoot.activeElement : document.activeElement;
t.step(() => { assert_equals(focused, el) });
}
t.done();
return assertFocusOrder([aboveHost, host, slottedBelow, aboveSlot, slottedAbove, belowSlot, belowHost]);
}, "Order when all tabindex=0, except for one slot that has tabindex=1");
</script>
</body>
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// <div #belowSlot tabindex=2>
// <div #belowHost tabindex=3>

async_test(async (t) => {
promise_test(() => {
let elementsInFlatTreeOrder;
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
elementsInFlatTreeOrder = prepareDOM(document.body, false);
Expand All @@ -30,13 +30,7 @@
setTabIndex([aboveHost, host, belowHost], 3);
setTabIndex([slottedAbove, slottedBelow], 4);
resetFocus();
const expectedOrder = [aboveHost, host, slottedAbove, slottedBelow, aboveSlot, belowSlot, belowHost];
for (let el of expectedOrder) {
await navigateFocusForward();
let focused = host.shadowRoot.activeElement ? host.shadowRoot.activeElement : document.activeElement;
t.step(() => { assert_equals(focused, el) });
}
t.done();
return assertFocusOrder([aboveHost, host, slottedAbove, slottedBelow, aboveSlot, belowSlot, belowHost]);
}, "Order with various tabindex values");
</script>
</body>
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,14 @@
// <div #belowSlot tabindex=0>
// <div #belowHost tabindex=0>

async_test(async (t) => {
promise_test(() => {
let elementsInFlatTreeOrder;
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] = elementsInFlatTreeOrder = prepareDOM(document.body, true);
setTabIndex(elementsInFlatTreeOrder, 0);
resetFocus();
// Focus should move in flat tree order since every one of them has tabindex ==0,
// but doesn't include slots and #host.
const expectedOrder = elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow && el !== host));
for (let el of expectedOrder) {
await navigateFocusForward();
let focused = host.shadowRoot.activeElement ? host.shadowRoot.activeElement : document.activeElement;
t.step(() => { assert_equals(focused, el) });
}
t.done();
return assertFocusOrder(elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow && el !== host)));
}, "Order when all tabindex=0 is and delegatesFocus = true");
</script>
</body>
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,15 @@
// <div #belowSlot tabindex=0>
// <div #belowHost tabindex=0>

async_test(async (t) => {
promise_test(() => {
let elementsInFlatTreeOrder;
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
elementsInFlatTreeOrder = prepareDOM(document.body, false);
setTabIndex(elementsInFlatTreeOrder, 0);
host.tabIndex = -1;
resetFocus();
// Focus willl only move within the focus navigation scope of the document (not going to get into #host).
const expectedOrder = [aboveHost, belowHost];
for (let el of expectedOrder) {
await navigateFocusForward();
let focused = host.shadowRoot.activeElement ? host.shadowRoot.activeElement : document.activeElement;
t.step(() => { assert_equals(focused, el) });
}
t.done();
return assertFocusOrder([aboveHost, belowHost]);
}, "Order when all tabindex=0 except for host, which has tabindex=-1");
</script>
</body>
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// <div #belowSlot tabindex=0>
// <div #belowHost tabindex=0>

async_test(async (t) => {
promise_test(() => {
let elementsInFlatTreeOrder;
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
elementsInFlatTreeOrder = prepareDOM(document.body, false);
Expand All @@ -31,13 +31,7 @@
// Focus should move in flat tree order since every one of them has tabindex ==0,
// but doesn't include #slot since it's not rendered and #host since its tabindex is not set
// (but #host is considered as 0 in focus scope navigation, keeping the flat tree order for the shadow root's descendants).
const expectedOrder = elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow && el !== host));
for (let el of expectedOrder) {
await navigateFocusForward();
let focused = host.shadowRoot.activeElement ? host.shadowRoot.activeElement : document.activeElement;
t.step(() => { assert_equals(focused, el) });
}
t.done();
return assertFocusOrder(elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow && el !== host)));
}, "Order when all tabindex=0 except host (tabindex not set)");
</script>
</body>
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// <div #belowSlot tabindex=0>
// <div #belowHost tabindex=0>

async_test(async (t) => {
promise_test(() => {
let elementsInFlatTreeOrder;
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
elementsInFlatTreeOrder = prepareDOM(document.body, false);
Expand All @@ -31,13 +31,7 @@
// Focus should move first to #host because it has tabindex=1, and then to the contents of its scope
// (e.g. the contents of its shadow tree) in flat tree order, and then outside to the document scope
// again (aboveHost & belowHost).
const expectedOrder = [host, aboveSlot, slottedAbove, slottedBelow, belowSlot, aboveHost, belowHost];
for (let el of expectedOrder) {
await navigateFocusForward();
let focused = host.shadowRoot.activeElement ? host.shadowRoot.activeElement : document.activeElement;
t.step(() => { assert_equals(focused, el) });
}
t.done();
return assertFocusOrder([host, aboveSlot, slottedAbove, slottedBelow, belowSlot, aboveHost, belowHost]);
}, "Order when all tabindex=0 except for host, which has tabindex=1");
</script>
</body>
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,15 @@
// <div #belowSlot tabindex=0>
// <div #belowHost tabindex=0>

async_test(async (t) => {
promise_test(() => {
let elementsInFlatTreeOrder;
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
elementsInFlatTreeOrder = prepareDOM(document.body, false);
setTabIndex(elementsInFlatTreeOrder, 0);
resetFocus();
// Focus should move in flat tree order since every one of them has tabindex ==0,
// Focus should move in flat tree order since every one of them has tabindex==0,
// but doesn't include slots.
const expectedOrder = elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow));
for (let el of expectedOrder) {
await navigateFocusForward();
let focused = host.shadowRoot.activeElement ? host.shadowRoot.activeElement : document.activeElement;
t.step(() => { assert_equals(focused, el) });
}
t.done();
return assertFocusOrder(elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow)));
}, "Order when all tabindex=0 is and delegatesFocus = false");
</script>
</body>
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function prepareDOM(container, delegatesFocus) {
const aboveHost = document.createElement("div");
aboveHost.innerText = "aboveHost";
const host = document.createElement("div");
host.id = "host";
const slottedBelow = document.createElement("div");
slottedBelow.innerText = "slotted below";
slottedBelow.slot = "below";
Expand Down Expand Up @@ -69,3 +70,14 @@ function navigateFocusForward() {
return test_driver.send_keys(document.body, "\ue004");
}

function assertFocusOrder(expectedOrder) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return new Promise isn't needed here. Just make the whole function async, and then put the loop body inside the function:

async function assertFocusOrder(expectedOrder) {
  let shadowRoot = document.getElementById("host").shadowRoot;
  for (let el of expectedOrder) {
    await navigateFocusForward();
    let focused = shadowRoot.activeElement ? shadowRoot.activeElement : document.activeElement;
    assert_equals(focused, el);
  }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh awesome, thanks :D

let shadowRoot = document.getElementById("host").shadowRoot;
return new Promise(async (resolve, reject) => {
for (let el of expectedOrder) {
await navigateFocusForward();
let focused = shadowRoot.activeElement ? shadowRoot.activeElement : document.activeElement;
assert_equals(focused, el);
}
resolve();
});
}