diff options
Diffstat (limited to 'devtools/client/shared/components/test/chrome/test_searchbox-with-autocomplete.html')
-rw-r--r-- | devtools/client/shared/components/test/chrome/test_searchbox-with-autocomplete.html | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/devtools/client/shared/components/test/chrome/test_searchbox-with-autocomplete.html b/devtools/client/shared/components/test/chrome/test_searchbox-with-autocomplete.html new file mode 100644 index 0000000000..110d5640c1 --- /dev/null +++ b/devtools/client/shared/components/test/chrome/test_searchbox-with-autocomplete.html @@ -0,0 +1,301 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<!DOCTYPE html> +<html> +<!-- +Test the searchbox and autocomplete-popup components +--> +<head> + <meta charset="utf-8"> + <title>SearchBox component test</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> +</head> +<body> +<script src="head.js"></script> +<script> +"use strict"; +window.onload = async function () { + /** + * Takes a DOMNode with its children as list items, + * Typically UL > LI and each item's text value is + * compared with the reference item's value as a test + * + * @params {Node} - Node to be compared + * @reference {array} - Reference array for comparison. The selected index is + * highlighted as a single element array ie. ["[abc]", "ab", "abcPQR"], + * Here the element "abc" is highlighted + */ + function compareAutocompleteList(list, reference) { + const delimiter = " - "; + const observedList = [...list.children].map(el => { + return el.classList.contains("autocomplete-selected") + ? `[${el.textContent}]` + : el.textContent + }); + is(observedList.join(delimiter), reference.join(delimiter), + "Autocomplete items are rendered as expected"); + } + + function compareCursorPosition(initialElement) { + const initialPosition = initialElement.selectionStart; + return (element) => { + is(element.selectionStart, initialPosition, "Input cursor position is not changed"); + } + } + + const React = browserRequire("devtools/client/shared/vendor/react"); + const SearchBox = React.createFactory( + browserRequire("devtools/client/shared/components/SearchBox") + ); + const { component, $ } = await createComponentTest(SearchBox, { + type: "search", + autocompleteProvider: (filter) => { + const baseList = [ + "foo", + "BAR", + "baZ", + "abc", + "pqr", + "xyz", + "ABC", + "a1", + "a2", + "a3", + "a4", + "a5", + ]; + if (!filter) { + return []; + } + + const tokens = filter.split(/\s+/g); + const lastToken = tokens[tokens.length - 1]; + const previousTokens = tokens.slice(0, tokens.length - 1); + + if (!lastToken) { + return []; + } + + return baseList + .filter((item) => { + return item.toLowerCase().startsWith(lastToken.toLowerCase()) + && item.toLowerCase() !== lastToken.toLowerCase(); + }) + .sort() + .map(item => ({ + value: [...previousTokens, item].join(" "), + displayValue: item, + })); + }, + onChange: () => null, + }); + + async function testSearchBoxWithAutocomplete() { + ok(!$(".devtools-autocomplete-popup"), "Autocomplete list not visible"); + + $(".devtools-searchinput").focus(); + await forceRender(component); // Wait for state update + ok(!$(".devtools-autocomplete-popup"), "Autocomplete list not visible"); + + sendString("a"); + await forceRender(component); + + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "[ABC]", + "a1", + "a2", + "a3", + "a4", + "a5", + "abc", + ]); + + // Blur event + $(".devtools-searchinput").blur(); + await forceRender(component); + ok(!component.state.focused, "focused state was properly set"); + ok(!$(".devtools-autocomplete-popup"), "Autocomplete list removed from DOM"); + } + + async function testKeyEventsWithAutocomplete() { + // Clear the initial input + $(".devtools-searchinput").focus(); + const cursorPositionIsNotChanged = compareCursorPosition($(".devtools-searchinput")); + + // ArrowDown + synthesizeKey("KEY_ArrowDown"); + await forceRender(component); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "ABC", + "[a1]", + "a2", + "a3", + "a4", + "a5", + "abc", + ]); + ok($(".devtools-autocomplete-listbox .autocomplete-item:nth-child(2)") + .className.includes("autocomplete-selected"), + "Selection class applied"); + + // A double ArrowUp should roll back to the bottom of the list + synthesizeKey("KEY_ArrowUp"); + synthesizeKey("KEY_ArrowUp"); + await forceRender(component); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "ABC", + "a1", + "a2", + "a3", + "a4", + "a5", + "[abc]", + ]); + cursorPositionIsNotChanged($(".devtools-searchinput")); + + // PageDown should take -5 places up + synthesizeKey("KEY_PageUp"); + await forceRender(component); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "ABC", + "[a1]", + "a2", + "a3", + "a4", + "a5", + "abc", + ]); + cursorPositionIsNotChanged($(".devtools-searchinput")); + + // PageDown should take +5 places down + synthesizeKey("KEY_PageDown"); + await forceRender(component); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "ABC", + "a1", + "a2", + "a3", + "a4", + "a5", + "[abc]", + ]); + cursorPositionIsNotChanged($(".devtools-searchinput")); + + // Home should take to the top of the list + synthesizeKey("KEY_Home"); + await forceRender(component); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "[ABC]", + "a1", + "a2", + "a3", + "a4", + "a5", + "abc", + ]); + cursorPositionIsNotChanged($(".devtools-searchinput")); + + // End should take to the bottom of the list + synthesizeKey("KEY_End"); + await forceRender(component); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "ABC", + "a1", + "a2", + "a3", + "a4", + "a5", + "[abc]", + ]); + cursorPositionIsNotChanged($(".devtools-searchinput")); + + // Key down in existing state should rollover to the top + synthesizeKey("KEY_ArrowDown"); + await forceRender(component); + // Tab should select the component and hide popup + synthesizeKey("KEY_Tab"); + await forceRender(component); + is(component.state.value, "ABC", "Tab hit selects the item"); + ok(!$(".devtools-autocomplete-popup"), "Tab hit hides the popup"); + + // Activate popup by removing a key + synthesizeKey("KEY_Backspace"); + await forceRender(component); + ok($(".devtools-autocomplete-popup"), "Popup is up"); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "[ABC]", + "abc" + ]); + + // Enter key selection + synthesizeKey("KEY_ArrowUp"); + await forceRender(component); + synthesizeKey("KEY_Enter"); + is(component.state.value, "abc", "Enter selection"); + ok(!$(".devtools-autocomplete-popup"), "Enter/Return hides the popup"); + + // Escape should remove the autocomplete component + synthesizeKey("KEY_Backspace"); + await forceRender(component); + synthesizeKey("KEY_Escape"); + await forceRender(component); + ok(!$(".devtools-autocomplete-popup"), + "Autocomplete list removed from DOM on Escape"); + } + + async function testMouseEventsWithAutocomplete() { + $(".devtools-searchinput").focus(); + await setState(component, { + value: "", + focused: true, + }); + await forceRender(component); + + // ArrowDown + synthesizeKey("KEY_ArrowDown"); + await forceRender(component); + synthesizeMouseAtCenter($(".devtools-searchinput"), {}, window); + await forceRender(component); + is(component.state.focused, true, "Component should now be focused"); + + sendString("pq"); + await forceRender(component); + synthesizeMouseAtCenter( + $(".devtools-autocomplete-listbox .autocomplete-item:nth-child(1)"), + {}, window + ); + await forceRender(component); + is(component.state.value, "pqr", "Mouse click selects the item."); + ok(!$(".devtools-autocomplete-popup"), "Mouse click on item hides the popup"); + } + + async function testTokenizedAutocomplete() { + // Test for string "pqr ab" which should show list of ABC, abc + sendString(" ab"); + await forceRender(component); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "[ABC]", + "abc" + ]); + + // Select the first element, value now should be "pqr ABC" + synthesizeMouseAtCenter( + $(".devtools-autocomplete-listbox .autocomplete-item:nth-child(1)"), + {}, window + ); + is(component.state.value, "pqr ABC", "Post Tokenization value selection"); + } + + add_task(async function () { + await testSearchBoxWithAutocomplete(); + await testKeyEventsWithAutocomplete(); + await testMouseEventsWithAutocomplete(); + await testTokenizedAutocomplete(); + }); +}; +</script> +</body> +</html> |