diff options
Diffstat (limited to 'testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/focus-after-close.html')
-rw-r--r-- | testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/focus-after-close.html | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/focus-after-close.html b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/focus-after-close.html new file mode 100644 index 0000000000..93baf65cf6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/interactive-elements/the-dialog-element/focus-after-close.html @@ -0,0 +1,229 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width,initial-scale=1"> +<title>Test focus is moved to the previously focused element when dialog is closed</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<body> +<input /> +<dialog> + <button id="button1">This is a button1</button> + <button id="button2">This is a button2</button> + <button id="button3">This is a button3</button> +</dialog> +<script> + +// Test focus is moved to the previously focused element +function test_move_to_previously_focused(showModal) { + const input = document.querySelector("input"); + input.focus(); + const dialog = document.querySelector("dialog"); + if (showModal) { + dialog.showModal(); + } else { + dialog.show(); + } + dialog.close(); + + assert_equals(document.activeElement, input); +} + +// Test focus is moved to the previously focused element with some complex dialog usage +async function test_move_to_previously_focused_with_complex_dialog_usage(showModal) { + const input = document.querySelector("input"); + input.focus(); + const dialog = document.querySelector("dialog"); + if (showModal) { + dialog.showModal(); + } else { + dialog.show(); + } + + const button1 = document.getElementById("button1"); + const button2 = document.getElementById("button2"); + const button3 = document.getElementById("button3"); + + await test_driver.click(button1); + await test_driver.click(button2); + await test_driver.click(button3); + + dialog.close(); + + assert_equals(document.activeElement, input); +} + +// Test focus is moved to the previously focused element even if that element moved in between +function test_element_move_in_between_show_close(showModal) { + const input = document.querySelector("input"); + input.focus(); + const dialog = document.querySelector("dialog"); + + assert_equals(input.nextElementSibling, dialog, "Element is in correct position"); + + if (showModal) { + dialog.showModal(); + } else { + dialog.show(); + } + + document.body.appendChild(input); + assert_not_equals(input.nextElementSibling, dialog, "Element should have moved"); + + dialog.close(); + assert_equals(document.activeElement, input, "Focus should be restored to previously focused input"); + + // Clean up + document.body.insertBefore(input, dialog); +} + +// Test focus is moved to the previously focused element even if that element moved to shadow root in between +function test_element_move_to_shadow_root_in_between_show_close(showModal) { + const input = document.querySelector("input"); + input.focus(); + const dialog = document.querySelector("dialog"); + + assert_equals(input.nextElementSibling, dialog, "Element is in correct position"); + + if (showModal) { + dialog.showModal(); + } else { + dialog.show(); + } + + const shadowHost = document.createElement("div"); + const shadowRoot = shadowHost.attachShadow({mode: "open"}); + shadowRoot.appendChild(input); + document.body.appendChild(shadowHost); + + assert_not_equals(input.nextElementSibling, dialog, "Element should have moved"); + + dialog.close(); + assert_equals(shadowRoot.activeElement, input, "Focus should be restored to previously focused input"); + assert_equals(document.activeElement, shadowHost, "document.activeElement should be previously focused input's shadow DOM host"); + + // Clean up + document.body.insertBefore(input, dialog); + shadowHost.remove(); +} + +// Test focus is moved to <body> if the previously focused +// element can't be focused +function test_move_to_body_if_fails(showModal) { + const input = document.querySelector("input"); + input.focus(); + const dialog = document.querySelector("dialog"); + if (showModal) { + dialog.showModal(); + } else { + dialog.show(); + } + dialog.close(); + input.remove(); + assert_equals(document.activeElement, document.body); + + // Clean up + document.body.insertBefore(input, dialog); +} + +// Test focus is moved to shadow host if the previously +// focused element is a shadow node. +function test_move_to_shadow_host(showModal) { + const shadowHost = document.createElement("div"); + + const shadowRoot = shadowHost.attachShadow({mode: "open"}); + shadowRoot.appendChild(document.createElement("input")); + + document.body.appendChild(shadowHost); + const inputElement = shadowRoot.querySelector("input"); + inputElement.focus(); + + assert_equals(document.activeElement, shadowHost); + assert_equals(shadowRoot.activeElement, inputElement); + + const dialog = document.querySelector("dialog"); + if (showModal) { + dialog.showModal(); + } else { + dialog.show(); + } + dialog.close(); + + assert_equals(document.activeElement, shadowHost); + assert_equals(shadowRoot.activeElement, inputElement); + + // Clean up + shadowHost.remove(); +} + +// Test moving the focus doesn't scroll the viewport +async function test_move_focus_dont_scroll_viewport(showModal) { + const outViewPortButton = document.createElement("button"); + outViewPortButton.style.top = (window.innerHeight + 10).toString() + "px"; + outViewPortButton.style.position = "absolute"; + document.body.appendChild(outViewPortButton); + + await new Promise(resolve => { + document.addEventListener("scroll", resolve, { once: true }); + outViewPortButton.focus(); + }); + + // Since the outViewPortButton is focused, so the viewport should be + // scrolled to it + assert_true(document.documentElement.scrollTop > 0 ); + + const dialog = document.querySelector("dialog"); + if (showModal) { + dialog.showModal(); + } else { + dialog.show(); + } + + window.scrollTo(0, 0); + assert_equals(document.documentElement.scrollTop, 0); + + dialog.close(); + assert_equals(document.documentElement.scrollTop, 0); + + assert_equals(document.activeElement, outViewPortButton); +} + +test(() => { + test_move_to_previously_focused(true); + test_move_to_previously_focused(false); +}, "Focus should be moved to the previously focused element (Simple dialog usage)"); + +promise_test(async () => { + await test_move_to_previously_focused_with_complex_dialog_usage(true); + await test_move_to_previously_focused_with_complex_dialog_usage(false); +}, "Focus should be moved to the previously focused element (Complex dialog usage)"); + +test(() => { + test_element_move_in_between_show_close(true); + test_element_move_in_between_show_close(false); +}, "Focus should be moved to the previously focused element even if it has moved in between show/close"); + +test(() => { + test_element_move_to_shadow_root_in_between_show_close(true); + test_element_move_to_shadow_root_in_between_show_close(false); +}, "Focus should be moved to the previously focused element even if it has moved to shadow DOM root in between show/close"); + +test(() => { + test_move_to_body_if_fails(true); + test_move_to_body_if_fails(false); +}, "Focus should be moved to the body if the previously focused element is removed"); + +test(() => { + test_move_to_shadow_host(true); + test_move_to_shadow_host(false); +}, "Focus should be moved to the shadow DOM host if the previouly focused element is a shadow DOM node"); + +promise_test(async () => { + await test_move_focus_dont_scroll_viewport(true); + await test_move_focus_dont_scroll_viewport(false); +}, "Focus should not scroll if the previously focused element is outside the viewport"); +</script> +</body> |