| <!DOCTYPE html> |
| <html> |
| <body> |
| |
| <h1>Test that Accessory bar next/previous buttons work on inputs which is not assigned to any slot in shadow tree</h1> |
| <p>To manually test, do following steps.</p> |
| <ol> |
| <li>Focus the 1st of input, then Accessory bar will shown.</li> |
| <li>Press "next" icon 4 times.</li> |
| <li>Press "prev" icon 4 times.</li> |
| <li>It should traverse focusable elements in the increasing numerical order and reverse the order of them.</li> |
| </ol> |
| |
| <input id="first" tabindex="1" onfocus="logOnFocus(this)" |
| placeholder="0. First sequentially input element outside shadow trees" /> |
| |
| <div id="host-with-negative-tabindex" tabindex="-1">Should not focus: Shadow host with a negative tabindex but not input element</div> |
| |
| <div id="host-with-no-tabindex"> |
| <input id="host-with-no-tabindex" |
| onfocus="logOnFocus(this)" |
| placeholder="Should not focus: input element having no tabindex in a element having no tabindex but will not assigned to slot" /> |
| </div> |
| |
| <div id="host-with-positive-tabindex" tabindex="2"> |
| <div> |
| <input id="input-in-host-with-positive-tabindex-negative" |
| tabindex="-1" |
| onfocus="logOnFocus(this)" |
| placeholder="Should not focus: input element having a negative tabindex in a element having a positive tabindex" /> |
| </div> |
| <div> |
| <input id="input-in-host-with-positive-tabindex" |
| tabindex="0" |
| onfocus="logOnFocus(this)" |
| placeholder="3. input element having tabindex=1 in a element having a positive tabindex" /> |
| </div> |
| <div> |
| <input id="input-in-host-with-positive-tabindex-positive" |
| tabindex="1" |
| onfocus="logOnFocus(this)" |
| placeholder="2. input element having a positive tabindex in a element having a positive tabindex" /> |
| </div> |
| </div> |
| |
| <div id="closed-shadow-tree-host"> |
| <input id="inpunt-descendants-of-closed-shadow-tree-host" |
| onfocus="logOnFocus(this)" |
| placeholder="6. input element in closed shadow tree host" /> |
| </div> |
| |
| <nest-input-holder></nest-input-holder> |
| |
| <input id="last" tabindex="0" onfocus="logOnFocus(this)" |
| placeholder="10. Last sequentially input element outside shadow trees" /> |
| |
| <div id="description"></div> |
| <div id="console"></div> |
| <pre id="log"></pre> |
| <script src="../../../resources/js-test.js"></script> |
| <script src="../../../resources/ui-helper.js"></script> |
| <script> |
| |
| document.getElementById('host-with-negative-tabindex').attachShadow({ mode: 'open' }).innerHTML = ` |
| <input tabindex="0" |
| onfocus="logOnFocus(this)" |
| placeholder="Should not focus: input element having tabindex=0 in a shadow tree host having negative tabindex"/> |
| `; |
| |
| document.getElementById('host-with-no-tabindex').attachShadow({ mode: 'open' }).innerHTML = ` |
| <input tabindex="0" |
| onfocus="logOnFocus(this)" |
| placeholder="5. input element having a positive tabindex in a shadow tree host which does not tabindex"/> |
| `; |
| |
| document.getElementById('host-with-positive-tabindex').attachShadow({ mode: 'open' }).innerHTML = ` |
| <slot></slot> |
| <div> |
| <input tabindex="0" |
| onfocus="logOnFocus(this)" |
| placeholder="4. input element having tabindex=0 in a shadow tree host having a positive tabindex"/> |
| </div> |
| <div> |
| <input tabindex="-1" |
| onfocus="logOnFocus(this)" |
| placeholder="Should not focus: input element having negatibe tabindex in a shadow tree host having a positive tabindex"/> |
| </div> |
| <div> |
| <input tabindex="1" |
| onfocus="logOnFocus(this)" |
| placeholder="1. input element having a positive tabindex in a shadow tree host having a positive tabindex"/> |
| </div> |
| `; |
| |
| document.getElementById('closed-shadow-tree-host').attachShadow({ mode: 'closed' }).innerHTML = ` |
| <slot></slot> |
| `; |
| |
| class InputHolder extends HTMLElement { |
| constructor() { |
| super(); |
| |
| this.attachShadow({ mode: 'open' }) |
| .innerHTML = '<p><input onfocus="logOnFocus(this)" placeholder=""/></p>'; |
| } |
| } |
| customElements.define('input-holder', InputHolder); |
| |
| class NestInputHolder extends HTMLElement { |
| constructor() { |
| super(); |
| |
| this.attachShadow({ mode: 'open' }) |
| .innerHTML = ` |
| <input onfocus="logOnFocus(this)" placeholder='7. input element before nested custom element having shadow tree' /> |
| <input-holder></input-holder> |
| <input onfocus="logOnFocus(this)" placeholder='9. input element after nested custom element having shadow tree'/> |
| `; |
| this.shadowRoot.querySelector('input-holder') |
| .shadowRoot.querySelector('input').setAttribute('placeholder', '8. input element in nested shadow tree'); |
| } |
| } |
| customElements.define('nest-input-holder', NestInputHolder); |
| |
| function logOnFocus(element) { |
| document.getElementById('log').textContent += element.getAttribute('placeholder') + '\n'; |
| } |
| |
| function testCase(documentOrShadowRoot, inputGetter) { |
| const inputElement = inputGetter(documentOrShadowRoot); |
| return { |
| documentOrShadowRoot, |
| inputElement, |
| }; |
| } |
| |
| async function runTest() { |
| const hostWithPositiveTabIndexShadowRoot = document.getElementById('host-with-positive-tabindex').shadowRoot; |
| const nestInputHolderShadowRoot = document.querySelector('nest-input-holder').shadowRoot; |
| |
| const stack = [ |
| testCase(document, (_) => document.getElementById('first')), |
| |
| testCase(hostWithPositiveTabIndexShadowRoot, |
| (shadowRoot) => shadowRoot.querySelector('input[tabindex="1"]')), |
| |
| testCase(document, (_) => document.getElementById('input-in-host-with-positive-tabindex-positive')), |
| |
| testCase(document, (_) => document.getElementById('input-in-host-with-positive-tabindex')), |
| |
| testCase(hostWithPositiveTabIndexShadowRoot, |
| (shadowRoot) => shadowRoot.querySelector('input[tabindex="0"]')), |
| |
| testCase(document.getElementById('host-with-no-tabindex').shadowRoot, |
| (shadowRoot) => shadowRoot.querySelector('input[tabindex="0"]')), |
| |
| testCase(document, (_) => document.getElementById('inpunt-descendants-of-closed-shadow-tree-host')), |
| |
| testCase(nestInputHolderShadowRoot, |
| (shadowRoot) => shadowRoot.querySelector('input:nth-child(1)')), |
| |
| testCase(nestInputHolderShadowRoot.querySelector('input-holder').shadowRoot, |
| (shadowRoot) => shadowRoot.querySelector('input')), |
| |
| testCase(nestInputHolderShadowRoot, |
| (shadowRoot) => shadowRoot.querySelector('input:nth-last-child(1)')), |
| |
| testCase(document, (_) => document.getElementById('last')), |
| ]; |
| |
| { |
| const firstElement = stack[0].inputElement; |
| debug('activate 0th input'); |
| await UIHelper.activateElement(firstElement); |
| debug('activated 0th input'); |
| } |
| |
| for (let i = 1, l = stack.length; i < l; ++i) { |
| const { documentOrShadowRoot, inputElement, } = stack[i]; |
| |
| debug(`forward to ${String(i)}th input`); |
| await UIHelper.moveToNextByKeyboardAccessoryBar(); |
| const activeElement = documentOrShadowRoot.activeElement; |
| debug(`documentOrShadowRoot.activeElement's placeholder attribute: ${activeElement.getAttribute('placeholder')}`); |
| shouldBe(() => activeElement.getAttribute('placeholder'), () => inputElement.getAttribute('placeholder')); |
| } |
| |
| debug('focus has moved to the last element and will move to the first reversely'); |
| |
| for (let i = stack.length - 2; -1 < i; --i) { |
| debug(`back to ${String(i)}th input`); |
| await UIHelper.moveToPrevByKeyboardAccessoryBar(); |
| const { documentOrShadowRoot, inputElement, } = stack[i]; |
| const activeElement = documentOrShadowRoot.activeElement; |
| debug(`documentOrShadowRoot.activeElement's placeholder attribute: ${activeElement.getAttribute('placeholder')}`); |
| shouldBe(() => activeElement.getAttribute('placeholder'), () => inputElement.getAttribute('placeholder')); |
| } |
| } |
| |
| if (window.testRunner) { |
| description(`Test that Accessory bar next/previous buttons work on inputs which is not assigned to any slot in shadow tree`); |
| const run = runTest().catch((e) => debug(`FAIL: \`${e}\``)); |
| UIHelper.wait(run); |
| } else |
| document.getElementById('console').style.display = 'none'; |
| |
| </script> |
| </body> |
| </html> |