summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/components/test/chrome/test_searchbox-with-autocomplete.html
diff options
context:
space:
mode:
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.html301
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>