helper_style_attr_test_runner.js (4797B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* eslint no-unused-vars: [2, {"vars": "local"}] */ 5 /* import-globals-from head.js */ 6 "use strict"; 7 8 /** 9 * Perform an style attribute edition and autocompletion test in the test 10 * url, for #node14. Test data should be an 11 * array of arrays structured as follows : 12 * [ 13 * what key to press, 14 * expected input box value after keypress, 15 * expected input.selectionStart, 16 * expected input.selectionEnd, 17 * is popup expected to be open ? 18 * ] 19 * 20 * The test will start by adding a new attribute on the node, and then send each 21 * key specified in the testData. The last item of this array should leave the 22 * new attribute editor, either by committing or cancelling the edit. 23 * 24 * @param {InspectorPanel} inspector 25 * @param {Array} testData 26 * Array of arrays representing the characters to type for the new 27 * attribute as well as the expected state at each step 28 */ 29 async function runStyleAttributeAutocompleteTests(inspector, testData) { 30 info("Expand all markup nodes"); 31 await inspector.markup.expandAll(); 32 33 info("Select #node14"); 34 const container = await focusNode("#node14", inspector); 35 36 info("Focus and open the new attribute inplace-editor"); 37 const attr = container.editor.newAttr; 38 attr.focus(); 39 EventUtils.sendKey("return", inspector.panelWin); 40 const editor = inplaceEditor(attr); 41 42 for (let i = 0; i < testData.length; i++) { 43 const data = testData[i]; 44 45 // Skip empty key. 46 if (!data.length) { 47 continue; 48 } 49 50 // Expect a markupmutation event at the last iteration since that's when the 51 // attribute is actually created. 52 const onMutation = 53 i === testData.length - 1 ? inspector.once("markupmutation") : null; 54 55 info(`Entering test data ${i}: ${data[0]}, expecting: [${data[1]}]`); 56 await enterData(data, editor, inspector); 57 58 info(`Test data ${i} entered. Checking state.`); 59 await checkData(data, editor, inspector); 60 61 await onMutation; 62 } 63 64 // Undoing the action will remove the new attribute, so make sure to wait for 65 // the markupmutation event here again. 66 const onMutation = inspector.once("markupmutation"); 67 while (inspector.markup.undo.canUndo()) { 68 await undoChange(inspector); 69 } 70 await onMutation; 71 } 72 73 /** 74 * Process a test data entry. 75 * 76 * @param {Array} data 77 * test data - click or key - to enter 78 * @param {InplaceEditor} editor 79 * @param {InspectorPanel} inspector 80 * @return {Promise} promise that will resolve when the test data has been 81 * applied 82 */ 83 function enterData(data, editor, inspector) { 84 const key = data[0]; 85 86 if (/^click_[0-9]+$/.test(key)) { 87 const suggestionIndex = parseInt(key.split("_")[1], 10); 88 return clickOnSuggestion(suggestionIndex, editor); 89 } 90 91 return sendKey(key, editor, inspector); 92 } 93 94 function clickOnSuggestion(index, editor) { 95 return new Promise(resolve => { 96 info("Clicking on item " + index + " in the list"); 97 editor.once("after-suggest", () => executeSoon(resolve)); 98 editor.popup.list.childNodes[index].click(); 99 }); 100 } 101 102 function sendKey(key, editor, inspector) { 103 return new Promise(resolve => { 104 if (/(down|left|right|back_space|return)/gi.test(key)) { 105 info("Adding event listener for down|left|right|back_space|return keys"); 106 editor.input.addEventListener("keypress", function onKeypress() { 107 if (editor.input) { 108 editor.input.removeEventListener("keypress", onKeypress); 109 } 110 executeSoon(resolve); 111 }); 112 } else { 113 editor.once("after-suggest", () => executeSoon(resolve)); 114 } 115 116 EventUtils.synthesizeKey(key, {}, inspector.panelWin); 117 }); 118 } 119 120 /** 121 * Verify that the inplace editor is in the expected state for the provided 122 * test data. 123 */ 124 async function checkData(data, editor, inspector) { 125 const [, completion, selStart, selEnd, popupOpen] = data; 126 127 if (selEnd != -1) { 128 is(editor.input.value, completion, "Completed value is correct"); 129 is( 130 editor.input.selectionStart, 131 selStart, 132 "Selection start position is correct" 133 ); 134 is(editor.input.selectionEnd, selEnd, "Selection end position is correct"); 135 is( 136 editor.popup.isOpen, 137 popupOpen, 138 "Popup is " + (popupOpen ? "open" : "closed") 139 ); 140 } else { 141 const nodeFront = await getNodeFront("#node14", inspector); 142 const container = getContainerForNodeFront(nodeFront, inspector); 143 const attr = container.editor.attrElements 144 .get("style") 145 .querySelector(".editable"); 146 is( 147 attr.textContent, 148 completion, 149 "Correct value is persisted after pressing Enter" 150 ); 151 } 152 }