/* 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/. */ /* eslint no-unused-vars: [2, {"vars": "local"}] */ /* import-globals-from head.js */ "use strict"; /** * Perform an style attribute edition and autocompletion test in the test * url, for #node14. Test data should be an * array of arrays structured as follows : * [ * what key to press, * expected input box value after keypress, * expected input.selectionStart, * expected input.selectionEnd, * is popup expected to be open ? * ] * * The test will start by adding a new attribute on the node, and then send each * key specified in the testData. The last item of this array should leave the * new attribute editor, either by committing or cancelling the edit. * * @param {InspectorPanel} inspector * @param {Array} testData * Array of arrays representing the characters to type for the new * attribute as well as the expected state at each step */ async function runStyleAttributeAutocompleteTests(inspector, testData) { info("Expand all markup nodes"); await inspector.markup.expandAll(); info("Select #node14"); const container = await focusNode("#node14", inspector); info("Focus and open the new attribute inplace-editor"); const attr = container.editor.newAttr; attr.focus(); EventUtils.sendKey("return", inspector.panelWin); const editor = inplaceEditor(attr); for (let i = 0; i < testData.length; i++) { const data = testData[i]; // Skip empty key. if (!data.length) { continue; } // Expect a markupmutation event at the last iteration since that's when the // attribute is actually created. const onMutation = i === testData.length - 1 ? inspector.once("markupmutation") : null; info(`Entering test data ${i}: ${data[0]}, expecting: [${data[1]}]`); await enterData(data, editor, inspector); info(`Test data ${i} entered. Checking state.`); await checkData(data, editor, inspector); await onMutation; } // Undoing the action will remove the new attribute, so make sure to wait for // the markupmutation event here again. const onMutation = inspector.once("markupmutation"); while (inspector.markup.undo.canUndo()) { await undoChange(inspector); } await onMutation; } /** * Process a test data entry. * * @param {Array} data * test data - click or key - to enter * @param {InplaceEditor} editor * @param {InspectorPanel} inspector * @return {Promise} promise that will resolve when the test data has been * applied */ function enterData(data, editor, inspector) { const key = data[0]; if (/^click_[0-9]+$/.test(key)) { const suggestionIndex = parseInt(key.split("_")[1], 10); return clickOnSuggestion(suggestionIndex, editor); } return sendKey(key, editor, inspector); } function clickOnSuggestion(index, editor) { return new Promise(resolve => { info("Clicking on item " + index + " in the list"); editor.once("after-suggest", () => executeSoon(resolve)); editor.popup.list.childNodes[index].click(); }); } function sendKey(key, editor, inspector) { return new Promise(resolve => { if (/(down|left|right|back_space|return)/gi.test(key)) { info("Adding event listener for down|left|right|back_space|return keys"); editor.input.addEventListener("keypress", function onKeypress() { if (editor.input) { editor.input.removeEventListener("keypress", onKeypress); } executeSoon(resolve); }); } else { editor.once("after-suggest", () => executeSoon(resolve)); } EventUtils.synthesizeKey(key, {}, inspector.panelWin); }); } /** * Verify that the inplace editor is in the expected state for the provided * test data. */ async function checkData(data, editor, inspector) { const [, completion, selStart, selEnd, popupOpen] = data; if (selEnd != -1) { is(editor.input.value, completion, "Completed value is correct"); is( editor.input.selectionStart, selStart, "Selection start position is correct" ); is(editor.input.selectionEnd, selEnd, "Selection end position is correct"); is( editor.popup.isOpen, popupOpen, "Popup is " + (popupOpen ? "open" : "closed") ); } else { const nodeFront = await getNodeFront("#node14", inspector); const container = getContainerForNodeFront(nodeFront, inspector); const attr = container.editor.attrElements .get("style") .querySelector(".editable"); is( attr.textContent, completion, "Correct value is persisted after pressing Enter" ); } }