summaryrefslogtreecommitdiffstats
path: root/devtools/client/inspector/markup/test/helper_style_attr_test_runner.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/client/inspector/markup/test/helper_style_attr_test_runner.js151
1 files changed, 151 insertions, 0 deletions
diff --git a/devtools/client/inspector/markup/test/helper_style_attr_test_runner.js b/devtools/client/inspector/markup/test/helper_style_attr_test_runner.js
new file mode 100644
index 0000000000..029651cf74
--- /dev/null
+++ b/devtools/client/inspector/markup/test/helper_style_attr_test_runner.js
@@ -0,0 +1,151 @@
+/* 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"
+ );
+ }
+}