browser_inspector_search-suggests-pseudo.js (5403B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 "use strict"; 4 5 // Test that the selector-search input proposes pseudo elements 6 7 const TEST_URL = `<h1>Hello</h1>`; 8 9 add_task(async function () { 10 const { inspector } = await openInspectorForURL( 11 "data:text/html;charset=utf-8," + encodeURI(TEST_URL) 12 ); 13 14 const TESTS = [ 15 { 16 input: ":", 17 // we don't want to test the exact items that are suggested, as the test would fail 18 // when new pseudo are added in the platform. 19 // Only includes some items that should be suggested (`included`), 20 // and some that should not be (`notIncluded`) 21 suggestions: { 22 included: [":active", ":empty", ":focus"], 23 notIncluded: ["::selection", "::marker"], 24 }, 25 inputAfterAcceptingSuggestion: ":active", 26 }, 27 { 28 // For now we don't support searching for pseudo element (Bug 1097991), 29 // so the list should be empty 30 input: "::", 31 suggestions: { 32 included: [], 33 }, 34 }, 35 { 36 input: "h1:", 37 suggestions: { 38 included: ["h1:active", "h1:empty", "h1:focus"], 39 notIncluded: ["h1::selection", "h1::marker"], 40 }, 41 inputAfterAcceptingSuggestion: "h1:active", 42 }, 43 { 44 input: "h1:not", 45 suggestions: { 46 included: ["h1:not("], 47 notIncluded: ["h1:nth-child("], 48 }, 49 inputAfterAcceptingSuggestion: "h1:not(", 50 }, 51 { 52 input: "h1:empty:", 53 suggestions: { 54 included: ["h1:empty:active", "h1:empty:empty", "h1:empty:focus"], 55 notIncluded: ["h1::selection", "h1::marker"], 56 }, 57 inputAfterAcceptingSuggestion: "h1:empty:active", 58 }, 59 { 60 input: "h1:empty:no", 61 suggestions: { 62 included: ["h1:empty:not("], 63 notIncluded: ["h1:empty:nth-child("], 64 }, 65 inputAfterAcceptingSuggestion: "h1:empty:not(", 66 }, 67 { 68 input: "body > h1:", 69 suggestions: { 70 included: ["body > h1:active", "body > h1:empty", "body > h1:focus"], 71 notIncluded: ["body > h1::selection", "body > h1::marker"], 72 }, 73 inputAfterAcceptingSuggestion: "body > h1:active", 74 }, 75 { 76 input: "body > h1:no", 77 suggestions: { 78 included: ["body > h1:not("], 79 notIncluded: ["body > h1:nth-child("], 80 }, 81 inputAfterAcceptingSuggestion: "body > h1:not(", 82 }, 83 ]; 84 85 info("Focus the search box"); 86 await focusSearchBoxUsingShortcut(inspector.panelWin); 87 88 const searchInputEl = inspector.panelWin.document.getElementById( 89 "inspector-searchbox" 90 ); 91 const { searchPopup } = inspector.searchSuggestions; 92 93 for (const { input, suggestions, inputAfterAcceptingSuggestion } of TESTS) { 94 info(`Checking suggestions for "${input}"`); 95 96 const onPopupOpened = searchPopup.once("popup-opened"); 97 // the query for getting suggestions is not throttled and is fired for every char 98 // being typed, so we avoid using EventUtils.sendString for the whole input to avoid 99 // dealing with multiple events. Instead, put the value directly in the input, and only 100 // type the last char. 101 const onProcessingDone = 102 inspector.searchSuggestions.once("processing-done"); 103 searchInputEl.value = input.substring(0, input.length - 1); 104 EventUtils.sendChar(input.at(-1), inspector.panelWin); 105 info("Wait for search query to complete"); 106 await onProcessingDone; 107 108 const actualSuggestions = Array.from( 109 searchPopup.list.querySelectorAll("li") 110 ).map(li => li.textContent); 111 112 if (!suggestions.included.length) { 113 const res = await Promise.race([ 114 onPopupOpened, 115 wait(1000).then(() => "TIMEOUT"), 116 ]); 117 is(res, "TIMEOUT", "popup did not open"); 118 } else { 119 await onPopupOpened; 120 ok(true, "suggestions popup opened"); 121 } 122 123 for (const expectedLabel of suggestions.included) { 124 ok( 125 actualSuggestions.some(s => s === expectedLabel), 126 `"${expectedLabel}" is in the list of suggestions for "${input}" (full list: ${JSON.stringify(actualSuggestions)})` 127 ); 128 } 129 130 for (const unexpectedLabel of suggestions.notIncluded || []) { 131 ok( 132 !actualSuggestions.some(s => s === unexpectedLabel), 133 `"${unexpectedLabel}" is not in the list of suggestions for "${input}"` 134 ); 135 } 136 137 if (inputAfterAcceptingSuggestion) { 138 info("Press tab to fill the search input with the first suggestion"); 139 const onSuggestionAccepted = 140 inspector.searchSuggestions.once("processing-done"); 141 const onPopupClosed = searchPopup.once("popup-closed"); 142 EventUtils.synthesizeKey("VK_TAB", {}, inspector.panelWin); 143 await onSuggestionAccepted; 144 await onPopupClosed; 145 146 is( 147 searchInputEl.value, 148 inputAfterAcceptingSuggestion, 149 "input has expected value after accepting suggestion" 150 ); 151 } 152 153 info("Clear the input"); 154 const onSearchCleared = inspector.search.once("search-cleared"); 155 const onEmptySearchSuggestionProcessingDone = 156 inspector.searchSuggestions.once("processing-done"); 157 158 // select the whole input and hit backspace to clear it 159 searchInputEl.setSelectionRange(0, searchInputEl.value.length); 160 EventUtils.synthesizeKey("VK_BACK_SPACE", {}, inspector.panelWin); 161 await onSearchCleared; 162 await onEmptySearchSuggestionProcessingDone; 163 } 164 });