/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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 =
`
Header
`;
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;
}