browser_editor_find_again.js (5982B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const L10N = new LocalizationHelper( 7 "devtools/client/locales/sourceeditor.properties" 8 ); 9 10 const { OS } = Services.appinfo; 11 12 // On linux, getting immediately the selection's range here fails, returning 13 const FIND_KEY = L10N.getStr("find.key"); 14 const FINDNEXT_KEY = L10N.getStr("findNext.key"); 15 const FINDPREV_KEY = L10N.getStr("findPrev.key"); 16 // the replace's key with the appropriate modifiers based on OS 17 const REPLACE_KEY = 18 OS == "Darwin" 19 ? L10N.getStr("replaceAllMac.key") 20 : L10N.getStr("replaceAll.key"); 21 22 // values like it's not selected – even if the selection is visible. 23 // For the record, setting the selection's range immediately doesn't have 24 // any effect. 25 // It's like the <input> is not ready yet. 26 // Therefore, we trigger the UI focus event to the <input>, waiting for the 27 // response. 28 // Using a timeout could also work, but that is more precise, ensuring also 29 // the execution of the listeners added to the <input>'s focus. 30 const dispatchAndWaitForFocus = target => 31 new Promise(resolve => { 32 target.addEventListener( 33 "focus", 34 function () { 35 resolve(target); 36 }, 37 { once: true } 38 ); 39 40 target.dispatchEvent(new UIEvent("focus")); 41 }); 42 43 function openSearchBox(ed) { 44 const edDoc = ed.container.contentDocument; 45 const edWin = edDoc.defaultView; 46 47 let input = edDoc.querySelector("input[type=search]"); 48 ok(!input, "search box closed"); 49 50 // The editor needs the focus to properly receive the `synthesizeKey` 51 ed.focus(); 52 53 synthesizeKeyShortcut(FINDNEXT_KEY, edWin); 54 input = edDoc.querySelector("input[type=search]"); 55 ok(input, "find again command key opens the search box"); 56 } 57 58 function testFindAgain(ed, inputLine, expectCursor, isFindPrev = false) { 59 const edDoc = ed.container.contentDocument; 60 const edWin = edDoc.defaultView; 61 62 const input = edDoc.querySelector("input[type=search]"); 63 input.value = inputLine; 64 65 // Ensure the input has the focus before send the key – necessary on Linux, 66 // it seems that during the tests can be lost 67 input.focus(); 68 69 if (isFindPrev) { 70 synthesizeKeyShortcut(FINDPREV_KEY, edWin); 71 } else { 72 synthesizeKeyShortcut(FINDNEXT_KEY, edWin); 73 } 74 75 ch( 76 ed.getCursor(), 77 expectCursor, 78 "find: " + inputLine + " expects cursor: " + expectCursor.toSource() 79 ); 80 } 81 82 const testSearchBoxTextIsSelected = async function (ed) { 83 const edDoc = ed.container.contentDocument; 84 const edWin = edDoc.defaultView; 85 86 let input = edDoc.querySelector("input[type=search]"); 87 ok(input, "search box is opened"); 88 89 // Ensure the input has the focus before send the key – necessary on Linux, 90 // it seems that during the tests can be lost 91 input.focus(); 92 93 // Close search box 94 EventUtils.synthesizeKey("VK_ESCAPE", {}, edWin); 95 96 input = edDoc.querySelector("input[type=search]"); 97 ok(!input, "search box is closed"); 98 99 // Re-open the search box 100 synthesizeKeyShortcut(FIND_KEY, edWin); 101 102 input = edDoc.querySelector("input[type=search]"); 103 ok(input, "find command key opens the search box"); 104 105 await dispatchAndWaitForFocus(input); 106 107 let { selectionStart, selectionEnd, value } = input; 108 109 ok( 110 selectionStart === 0 && selectionEnd === value.length, 111 "search box's text is selected when re-opened" 112 ); 113 114 // Removing selection 115 input.setSelectionRange(0, 0); 116 117 synthesizeKeyShortcut(FIND_KEY, edWin); 118 119 ({ selectionStart, selectionEnd } = input); 120 121 ok( 122 selectionStart === 0 && selectionEnd === value.length, 123 "search box's text is selected when find key is pressed" 124 ); 125 126 // Close search box 127 EventUtils.synthesizeKey("VK_ESCAPE", {}, edWin); 128 }; 129 130 const testReplaceBoxTextIsSelected = async function (ed) { 131 const edDoc = ed.container.contentDocument; 132 const edWin = edDoc.defaultView; 133 134 let input = edDoc.querySelector(".CodeMirror-dialog > input"); 135 ok(!input, "dialog box with replace is closed"); 136 137 // The editor needs the focus to properly receive the `synthesizeKey` 138 ed.focus(); 139 140 synthesizeKeyShortcut(REPLACE_KEY, edWin); 141 142 input = edDoc.querySelector(".CodeMirror-dialog > input"); 143 ok(input, "dialog box with replace is opened"); 144 145 input.value = "line 5"; 146 147 // Ensure the input has the focus before send the key – necessary on Linux, 148 // it seems that during the tests can be lost 149 input.focus(); 150 151 await dispatchAndWaitForFocus(input); 152 153 let { selectionStart, selectionEnd, value } = input; 154 155 ok( 156 !(selectionStart === 0 && selectionEnd === value.length), 157 "Text in dialog box is not selected" 158 ); 159 160 synthesizeKeyShortcut(REPLACE_KEY, edWin); 161 162 ({ selectionStart, selectionEnd } = input); 163 164 ok( 165 selectionStart === 0 && selectionEnd === value.length, 166 "dialog box's text is selected when replace key is pressed" 167 ); 168 169 // Close dialog box 170 EventUtils.synthesizeKey("VK_ESCAPE", {}, edWin); 171 }; 172 173 add_task(async function () { 174 const { ed, win } = await setup(); 175 176 ed.setText( 177 [ 178 "// line 1", 179 "// line 2", 180 "// line 3", 181 "// line 4", 182 "// line 5", 183 ].join("\n") 184 ); 185 186 await promiseWaitForFocus(); 187 188 openSearchBox(ed); 189 190 const testVectors = [ 191 // Starting here expect data needs to get updated for length changes to 192 // "textLines" above. 193 ["line", { line: 0, ch: 7 }], 194 ["line", { line: 1, ch: 8 }], 195 ["line", { line: 2, ch: 9 }], 196 ["line", { line: 3, ch: 10 }], 197 ["line", { line: 4, ch: 11 }], 198 ["ne 3", { line: 2, ch: 11 }], 199 ["line 1", { line: 0, ch: 9 }], 200 // Testing find prev 201 ["line", { line: 4, ch: 11 }, true], 202 ["line", { line: 3, ch: 10 }, true], 203 ["line", { line: 2, ch: 9 }, true], 204 ["line", { line: 1, ch: 8 }, true], 205 ["line", { line: 0, ch: 7 }, true], 206 ]; 207 208 for (const v of testVectors) { 209 await testFindAgain(ed, ...v); 210 } 211 212 await testSearchBoxTextIsSelected(ed); 213 214 await testReplaceBoxTextIsSelected(ed); 215 216 teardown(ed, win); 217 });