browser_jsterm_completion_bracket.js (7836B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 // Tests that code completion works properly with `[` 5 6 "use strict"; 7 8 const TEST_URI = `data:text/html;charset=utf8,<!DOCTYPE html><p>test [ completion. 9 <script> 10 window.testObject = Object.create(null, Object.getOwnPropertyDescriptors({ 11 bar: 0, 12 dataTest: 1, 13 "data-test": 2, 14 'da"ta"test': 3, 15 "da\`ta\`test": 4, 16 "da'ta'test": 5, 17 "DATA-TEST": 6, 18 "DAT_\\\\a\\"'\`\${0}\\u0000\\b\\t\\n\\f\\r\\ude80\\ud83d\\ud83d\\ude80_TEST": 7, 19 })); 20 </script>`; 21 22 add_task(async function () { 23 await pushPref("devtools.editor.autoclosebrackets", false); 24 const hud = await openNewTabAndConsole(TEST_URI); 25 await testInputs(hud, false); 26 await testCompletionTextUpdateOnPopupNavigate(hud, false); 27 await testAcceptCompletionExistingClosingBracket(hud); 28 29 info("Test again with autoclosebracket set to true"); 30 await pushPref("devtools.editor.autoclosebrackets", true); 31 const hudAutoclose = await openNewTabAndConsole(TEST_URI); 32 await testInputs(hudAutoclose, true); 33 await testCompletionTextUpdateOnPopupNavigate(hudAutoclose, true); 34 await testAcceptCompletionExistingClosingBracket(hudAutoclose); 35 }); 36 37 async function testInputs(hud, autocloseEnabled) { 38 const tests = [ 39 { 40 description: "Check that the popup is opened when typing `[`", 41 input: "window.testObject[", 42 expectedItems: [ 43 `"bar"`, 44 `"da'ta'test"`, 45 `"da\\"ta\\"test"`, 46 `"da\`ta\`test"`, 47 `"data-test"`, 48 `"dataTest"`, 49 `"DAT_\\\\a\\"'\`\${0}\\u0000\\b\\t\\n\\f\\r\\ude80\\ud83d🚀_TEST"`, 50 `"DATA-TEST"`, 51 ], 52 expectedCompletionText: autocloseEnabled ? "" : `"bar"]`, 53 expectedInputAfterCompletion: `window.testObject["bar"]`, 54 }, 55 { 56 description: "Test that the list can be filtered even without quote", 57 input: "window.testObject[d", 58 expectedItems: [ 59 `"da'ta'test"`, 60 `"da\\"ta\\"test"`, 61 `"da\`ta\`test"`, 62 `"data-test"`, 63 `"dataTest"`, 64 `"DAT_\\\\a\\"'\`\${0}\\u0000\\b\\t\\n\\f\\r\\ude80\\ud83d🚀_TEST"`, 65 `"DATA-TEST"`, 66 ], 67 expectedCompletionText: autocloseEnabled ? "" : `a'ta'test"]`, 68 expectedInputAfterCompletion: `window.testObject["da'ta'test"]`, 69 }, 70 { 71 description: "Test filtering with quote and string", 72 input: `window.testObject["d`, 73 expectedItems: [ 74 `"da'ta'test"`, 75 `"da\\"ta\\"test"`, 76 `"da\`ta\`test"`, 77 `"data-test"`, 78 `"dataTest"`, 79 `"DAT_\\\\a\\"'\`\${0}\\u0000\\b\\t\\n\\f\\r\\ude80\\ud83d🚀_TEST"`, 80 `"DATA-TEST"`, 81 ], 82 expectedCompletionText: autocloseEnabled ? "" : `a'ta'test"]`, 83 expectedInputAfterCompletion: `window.testObject["da'ta'test"]`, 84 }, 85 { 86 description: "Test filtering with simple quote and string", 87 input: `window.testObject['d`, 88 expectedItems: [ 89 `'da"ta"test'`, 90 `'da\\'ta\\'test'`, 91 `'da\`ta\`test'`, 92 `'data-test'`, 93 `'dataTest'`, 94 `'DAT_\\\\a"\\'\`\${0}\\u0000\\b\\t\\n\\f\\r\\ude80\\ud83d🚀_TEST'`, 95 `'DATA-TEST'`, 96 ], 97 expectedCompletionText: autocloseEnabled ? "" : `a"ta"test']`, 98 expectedInputAfterCompletion: `window.testObject['da"ta"test']`, 99 }, 100 { 101 description: "Test filtering with template literal and string", 102 input: "window.testObject[`d", 103 expectedItems: [ 104 "`da'ta'test`", 105 '`da"ta"test`', 106 "`da\\`ta\\`test`", 107 "`data-test`", 108 "`dataTest`", 109 "`DAT_\\\\a\"'\\`\\${0}\\u0000\\b\\t\\n\\f\\r\\ude80\\ud83d🚀_TEST`", 110 "`DATA-TEST`", 111 ], 112 expectedCompletionText: autocloseEnabled ? "" : "a'ta'test`]", 113 expectedInputAfterCompletion: "window.testObject[`da'ta'test`]", 114 }, 115 { 116 description: "Test that filtering is case insensitive", 117 input: "window.testObject[data-t", 118 expectedItems: [`"data-test"`, `"DATA-TEST"`], 119 expectedCompletionText: autocloseEnabled ? "" : `est"]`, 120 expectedInputAfterCompletion: `window.testObject["data-test"]`, 121 }, 122 { 123 description: 124 "Test that filtering without quote displays the popup when there's only 1 match", 125 input: "window.testObject[DATA-", 126 expectedItems: [`"DATA-TEST"`], 127 expectedCompletionText: autocloseEnabled ? "" : `TEST"]`, 128 expectedInputAfterCompletion: `window.testObject["DATA-TEST"]`, 129 }, 130 ]; 131 132 for (const test of tests) { 133 await testInput(hud, test); 134 } 135 } 136 137 async function testInput( 138 hud, 139 { 140 description, 141 input, 142 expectedItems, 143 expectedCompletionText, 144 expectedInputAfterCompletion, 145 } 146 ) { 147 const { jsterm } = hud; 148 const { autocompletePopup } = jsterm; 149 150 info(`${description} - test popup opening`); 151 const onPopUpOpen = autocompletePopup.once("popup-opened"); 152 EventUtils.sendString(input); 153 await onPopUpOpen; 154 155 ok( 156 hasExactPopupLabels(autocompletePopup, expectedItems), 157 `${description} - popup has expected item, in expected order` 158 ); 159 checkInputCompletionValue( 160 hud, 161 expectedCompletionText, 162 `${description} - completeNode has expected value` 163 ); 164 165 info(`${description} - test accepting completion`); 166 const onPopupClose = autocompletePopup.once("popup-closed"); 167 EventUtils.synthesizeKey("KEY_Tab"); 168 await onPopupClose; 169 checkInputValueAndCursorPosition( 170 hud, 171 expectedInputAfterCompletion + "|", 172 `${description} - input was completed as expected` 173 ); 174 checkInputCompletionValue(hud, "", `${description} - completeNode is empty`); 175 176 setInputValue(hud, ""); 177 } 178 179 async function testCompletionTextUpdateOnPopupNavigate(hud, autocloseEnabled) { 180 const { jsterm } = hud; 181 const { autocompletePopup } = jsterm; 182 183 info( 184 "Test that navigating the popup list update the completionText as expected" 185 ); 186 const onPopUpOpen = autocompletePopup.once("popup-opened"); 187 const input = `window.testObject[data`; 188 EventUtils.sendString(input); 189 await onPopUpOpen; 190 191 ok( 192 hasExactPopupLabels(autocompletePopup, [ 193 `"data-test"`, 194 `"dataTest"`, 195 `"DATA-TEST"`, 196 ]), 197 `popup has expected items, in expected order` 198 ); 199 checkInputCompletionValue( 200 hud, 201 autocloseEnabled ? "" : `-test"]`, 202 `completeNode has expected value` 203 ); 204 205 EventUtils.synthesizeKey("KEY_ArrowDown"); 206 checkInputCompletionValue( 207 hud, 208 autocloseEnabled ? "" : `Test"]`, 209 `completeNode has expected value` 210 ); 211 212 EventUtils.synthesizeKey("KEY_ArrowDown"); 213 checkInputCompletionValue( 214 hud, 215 autocloseEnabled ? "" : `-TEST"]`, 216 `completeNode has expected value` 217 ); 218 219 const onPopupClose = autocompletePopup.once("popup-closed"); 220 EventUtils.synthesizeKey("KEY_Tab"); 221 await onPopupClose; 222 checkInputValueAndCursorPosition( 223 hud, 224 `window.testObject["DATA-TEST"]|`, 225 `input was completed as expected after navigating the popup` 226 ); 227 } 228 229 async function testAcceptCompletionExistingClosingBracket(hud) { 230 const { jsterm } = hud; 231 const { autocompletePopup } = jsterm; 232 233 info( 234 "Check that accepting completion when there's a closing bracket does not append " + 235 "another closing bracket" 236 ); 237 await setInputValueForAutocompletion(hud, "window.testObject[]", -1); 238 const onPopUpOpen = autocompletePopup.once("popup-opened"); 239 EventUtils.sendString(`"b`); 240 await onPopUpOpen; 241 ok( 242 hasExactPopupLabels(autocompletePopup, [`"bar"`]), 243 `popup has expected item` 244 ); 245 246 const onPopupClose = autocompletePopup.once("popup-closed"); 247 EventUtils.synthesizeKey("KEY_Tab"); 248 await onPopupClose; 249 checkInputValueAndCursorPosition( 250 hud, 251 `window.testObject["bar"]|`, 252 `input was completed as expected, without adding a closing bracket` 253 ); 254 }