131 lines
5.1 KiB
JavaScript
131 lines
5.1 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
// Test the behaviour of the CSS autocomplete for CSS value displayed on
|
|
// multiple lines. Expected behavior is:
|
|
// - UP/DOWN should navigate in the input and not increment/decrement numbers
|
|
// - typing a new value should still trigger the autocomplete
|
|
// - UP/DOWN when the autocomplete popup is displayed should cycle through
|
|
// suggestions
|
|
|
|
const LONG_CSS_VALUE =
|
|
"transparent linear-gradient(0deg, blue 0%, white 5%, red 10%, blue 15%, " +
|
|
"white 20%, red 25%, blue 30%, white 35%, red 40%, blue 45%, white 50%, " +
|
|
"red 55%, blue 60%, white 65%, red 70%, blue 75%, white 80%, red 85%, " +
|
|
"blue 90%, white 95% ) repeat scroll 0% 0%";
|
|
|
|
const EXPECTED_CSS_VALUE = LONG_CSS_VALUE.replace("95%", "95%, red");
|
|
|
|
const TEST_URI =
|
|
`<style>
|
|
.title {
|
|
background: ${LONG_CSS_VALUE};
|
|
}
|
|
</style>
|
|
<h1 class=title>Header</h1>`;
|
|
|
|
add_task(function* () {
|
|
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
|
let { inspector, view} = yield openRuleView();
|
|
|
|
info("Selecting the test node");
|
|
yield selectNode("h1", inspector);
|
|
|
|
info("Focusing the property editable field");
|
|
let rule = getRuleViewRuleEditor(view, 1).rule;
|
|
let prop = rule.textProps[0];
|
|
|
|
// Calculate offsets to click in the middle of the first box quad.
|
|
let rect = prop.editor.valueSpan.getBoundingClientRect();
|
|
let firstQuad = prop.editor.valueSpan.getBoxQuads()[0];
|
|
// For a multiline value, the first quad left edge is not aligned with the
|
|
// bounding rect left edge. The offsets expected by focusEditableField are
|
|
// relative to the bouding rectangle, so we need to translate the x-offset.
|
|
let x = firstQuad.bounds.left - rect.left + firstQuad.bounds.width / 2;
|
|
// The first quad top edge is aligned with the bounding top edge, no
|
|
// translation needed here.
|
|
let y = firstQuad.bounds.height / 2;
|
|
|
|
info("Focusing the css property editable value");
|
|
let editor = yield focusEditableField(view, prop.editor.valueSpan, x, y);
|
|
|
|
info("Moving the caret next to a number");
|
|
let pos = editor.input.value.indexOf("0deg") + 1;
|
|
editor.input.setSelectionRange(pos, pos);
|
|
is(editor.input.value[editor.input.selectionStart - 1], "0",
|
|
"Input caret is after a 0");
|
|
|
|
info("Check that UP/DOWN navigates in the input, even when next to a number");
|
|
EventUtils.synthesizeKey("VK_DOWN", {}, view.styleWindow);
|
|
ok(editor.input.selectionStart !== pos, "Input caret moved");
|
|
is(editor.input.value, LONG_CSS_VALUE, "Input value was not decremented.");
|
|
|
|
info("Move the caret to the end of the gradient definition.");
|
|
pos = editor.input.value.indexOf("95%") + 3;
|
|
editor.input.setSelectionRange(pos, pos);
|
|
|
|
info("Sending \", re\" to the editable field.");
|
|
for (let key of ", re") {
|
|
yield synthesizeKeyForAutocomplete(key, editor, view.styleWindow);
|
|
}
|
|
|
|
info("Check the autocomplete can still be displayed.");
|
|
ok(editor.popup && editor.popup.isOpen, "Autocomplete popup is displayed.");
|
|
is(editor.popup.selectedIndex, 0,
|
|
"Autocomplete has an item selected by default");
|
|
|
|
let item = editor.popup.getItemAtIndex(editor.popup.selectedIndex);
|
|
is(item.label, "rebeccapurple",
|
|
"Check autocomplete displays expected value.");
|
|
|
|
info("Check autocomplete suggestions can be cycled using UP/DOWN arrows.");
|
|
|
|
yield synthesizeKeyForAutocomplete("VK_DOWN", editor, view.styleWindow);
|
|
ok(editor.popup.selectedIndex, 1, "Using DOWN cycles autocomplete values.");
|
|
yield synthesizeKeyForAutocomplete("VK_DOWN", editor, view.styleWindow);
|
|
ok(editor.popup.selectedIndex, 2, "Using DOWN cycles autocomplete values.");
|
|
yield synthesizeKeyForAutocomplete("VK_UP", editor, view.styleWindow);
|
|
is(editor.popup.selectedIndex, 1, "Using UP cycles autocomplete values.");
|
|
item = editor.popup.getItemAtIndex(editor.popup.selectedIndex);
|
|
is(item.label, "red", "Check autocomplete displays expected value.");
|
|
|
|
info("Select the background-color suggestion with a mouse click.");
|
|
let onRuleviewChanged = view.once("ruleview-changed");
|
|
let onSuggest = editor.once("after-suggest");
|
|
|
|
let node = editor.popup._list.childNodes[editor.popup.selectedIndex];
|
|
EventUtils.synthesizeMouseAtCenter(node, {}, editor.popup._window);
|
|
|
|
view.throttle.flush();
|
|
yield onSuggest;
|
|
yield onRuleviewChanged;
|
|
|
|
is(editor.input.value, EXPECTED_CSS_VALUE,
|
|
"Input value correctly autocompleted");
|
|
|
|
info("Press ESCAPE to leave the input.");
|
|
onRuleviewChanged = view.once("ruleview-changed");
|
|
EventUtils.synthesizeKey("VK_ESCAPE", {}, view.styleWindow);
|
|
yield onRuleviewChanged;
|
|
});
|
|
|
|
/**
|
|
* Send the provided key to the currently focused input of the provided window.
|
|
* Wait for the editor to emit "after-suggest" to make sure the autocompletion
|
|
* process is finished.
|
|
*
|
|
* @param {String} key
|
|
* The key to send to the input.
|
|
* @param {InplaceEditor} editor
|
|
* The inplace editor which owns the focused input.
|
|
* @param {Window} win
|
|
* Window in which the key event will be dispatched.
|
|
*/
|
|
function* synthesizeKeyForAutocomplete(key, editor, win) {
|
|
let onSuggest = editor.once("after-suggest");
|
|
EventUtils.synthesizeKey(key, {}, win);
|
|
yield onSuggest;
|
|
}
|