/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /* eslint no-unused-vars: [2, {"vars": "local", "args": "none"}] */ /* import-globals-from head.js */ "use strict"; /** * Helper methods for the HTMLTooltip integration tests. */ const HTML_NS = "http://www.w3.org/1999/xhtml"; const { editableField, } = require("resource://devtools/client/shared/inplace-editor.js"); const { colorUtils } = require("resource://devtools/shared/css/color.js"); /** * Create an inplace editor linked to a span element and click on the span to * to turn to edit mode. * * @param {Object} options * Options passed to the InplaceEditor/editableField constructor. * @param {Document} doc * Document where the span element will be created. * @param {String} textContent * (optional) String that will be used as the text content of the span. */ const createInplaceEditorAndClick = async function (options, doc, textContent) { const span = (options.element = createSpan(doc)); if (textContent) { span.textContent = textContent; } info("Creating an inplace-editor field"); editableField(options); info("Clicking on the inplace-editor field to turn to edit mode"); span.click(); }; /** * Helper to create a span in the provided document. * * @param {Document} doc * Document where the span element will be created. * @return {Element} the created span element. */ function createSpan(doc) { info("Creating a new span element"); const div = doc.createElementNS(HTML_NS, "div"); const span = doc.createElementNS(HTML_NS, "span"); span.setAttribute("tabindex", "0"); span.style.fontSize = "11px"; span.style.display = "inline-block"; span.style.width = "100px"; span.style.border = "1px solid red"; span.style.fontFamily = "monospace"; div.style.height = "100%"; div.style.position = "absolute"; div.appendChild(span); const parent = doc.querySelector("window") || doc.body; parent.appendChild(div); return span; } /** * Test helper simulating a key event in an InplaceEditor and checking that the * autocompletion works as expected. * * @param {Array} testData * - {String} key, the key to send * - {String} completion, the expected value of the auto-completion * - {Number} index, the index of the selected suggestion in the popup * - {Number} total, the total number of suggestions in the popup * - {String} postLabel, the expected post label for the selected suggestion * - {Boolean} colorSwatch, if there is a swatch of color expected to be visible * @param {InplaceEditor} editor * The InplaceEditor instance being tested */ async function testCompletion( [key, completion, index, total, postLabel, colorSwatch], editor ) { info("Pressing key " + key); info("Expecting " + completion); let onVisibilityChange = null; const open = total > 0; if (editor.popup.isOpen != open) { onVisibilityChange = editor.popup.once( open ? "popup-opened" : "popup-closed" ); } let onSuggest; if (/(left|right|back_space|escape)/gi.test(key)) { info("Adding event listener for right|back_space|escape keys"); onSuggest = once(editor.input, "keypress"); } else { info("Waiting for after-suggest event on the editor"); onSuggest = editor.once("after-suggest"); } info("Synthesizing key " + key); EventUtils.synthesizeKey(key, {}, editor.input.defaultView); await onSuggest; await onVisibilityChange; await waitForTime(5); info("Checking the state"); if (completion !== null) { is(editor.input.value, completion, "Correct value is autocompleted"); } if (postLabel) { const selectedItem = editor.popup.getItems()[index]; const selectedElement = editor.popup.elements.get(selectedItem); ok( selectedElement.textContent.includes(postLabel), "Selected popup element contains the expected post-label" ); // Determines if there is a color swatch attached to the label // and if the color swatch's background color matches the post label const swatchSpan = selectedElement.getElementsByClassName( "autocomplete-swatch autocomplete-colorswatch" ); if (colorSwatch) { Assert.strictEqual( swatchSpan.length, 1, "Displayed the expected color swatch" ); const color = new colorUtils.CssColor( swatchSpan[0].style.backgroundColor ); const swatchColor = color.rgba; const postColor = new colorUtils.CssColor(postLabel).rgba; Assert.equal( swatchColor, postColor, "Color swatch matches postLabel value" ); } else { Assert.strictEqual( swatchSpan.length, 0, "As expected no swatches were available" ); } } if (total === 0) { ok(!(editor.popup && editor.popup.isOpen), "Popup is closed"); } else { ok(editor.popup.isOpen, "Popup is open"); is(editor.popup.getItems().length, total, "Number of suggestions match"); is(editor.popup.selectedIndex, index, "Expected item is selected"); } }