tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_rules_completion-new-property_multiline.js (5355B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // Test the behaviour of the CSS autocomplete for CSS value displayed on
      7 // multiple lines. Expected behavior is:
      8 // - UP/DOWN should navigate in the input and not increment/decrement numbers
      9 // - typing a new value should still trigger the autocomplete
     10 // - UP/DOWN when the autocomplete popup is displayed should cycle through
     11 //   suggestions
     12 
     13 const LONG_CSS_VALUE =
     14  "transparent linear-gradient(0deg, blue 0%, white 5%, red 10%, blue 15%, " +
     15  "white 20%, red 25%, blue 30%, white 35%, red 40%, blue 45%, white 50%, " +
     16  "red 55%, blue 60%, white 65%, red 70%, blue 75%, white 80%, red 85%, " +
     17  "blue 90%, white 95% ) repeat scroll 0% 0%";
     18 
     19 const EXPECTED_CSS_VALUE = LONG_CSS_VALUE.replace("95%", "95%, red");
     20 
     21 const TEST_URI = `<style>
     22    .title {
     23      background: ${LONG_CSS_VALUE};
     24    }
     25  </style>
     26  <h1 class=title>Header</h1>`;
     27 
     28 add_task(async function () {
     29  await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
     30  const { inspector, view } = await openRuleView();
     31 
     32  info("Selecting the test node");
     33  await selectNode("h1", inspector);
     34 
     35  info("Focusing the property editable field");
     36  const prop = getTextProperty(view, 1, { background: LONG_CSS_VALUE });
     37 
     38  // Calculate offsets to click in the middle of the first box quad.
     39  const rect = prop.editor.valueSpan.getBoundingClientRect();
     40  const firstQuadBounds = prop.editor.valueSpan.getBoxQuads()[0].getBounds();
     41  // For a multiline value, the first quad left edge is not aligned with the
     42  // bounding rect left edge. The offsets expected by focusEditableField are
     43  // relative to the bouding rectangle, so we need to translate the x-offset.
     44  const x = firstQuadBounds.left - rect.left + firstQuadBounds.width / 2;
     45  // The first quad top edge is aligned with the bounding top edge, no
     46  // translation needed here.
     47  const y = firstQuadBounds.height / 2;
     48 
     49  info("Focusing the css property editable value");
     50  const editor = await focusEditableField(view, prop.editor.valueSpan, x, y);
     51 
     52  info("Moving the caret next to a number");
     53  let pos = editor.input.value.indexOf("0deg") + 1;
     54  editor.input.setSelectionRange(pos, pos);
     55  is(
     56    editor.input.value[editor.input.selectionStart - 1],
     57    "0",
     58    "Input caret is after a 0"
     59  );
     60 
     61  info("Check that UP/DOWN navigates in the input, even when next to a number");
     62  EventUtils.synthesizeKey("VK_DOWN", {}, view.styleWindow);
     63  Assert.notStrictEqual(editor.input.selectionStart, pos, "Input caret moved");
     64  is(editor.input.value, LONG_CSS_VALUE, "Input value was not decremented.");
     65 
     66  info("Move the caret to the end of the gradient definition.");
     67  pos = editor.input.value.indexOf("95%") + 3;
     68  editor.input.setSelectionRange(pos, pos);
     69 
     70  info('Sending ", re" to the editable field.');
     71  for (const key of ", re") {
     72    await synthesizeKeyForAutocomplete(key, editor, view.styleWindow);
     73  }
     74 
     75  info("Check the autocomplete can still be displayed.");
     76  ok(editor.popup && editor.popup.isOpen, "Autocomplete popup is displayed.");
     77  is(
     78    editor.popup.selectedIndex,
     79    0,
     80    "Autocomplete has an item selected by default"
     81  );
     82 
     83  let item = editor.popup.getItemAtIndex(editor.popup.selectedIndex);
     84  is(
     85    item.label,
     86    "rebeccapurple",
     87    "Check autocomplete displays expected value."
     88  );
     89 
     90  info("Check autocomplete suggestions can be cycled using UP/DOWN arrows.");
     91 
     92  await synthesizeKeyForAutocomplete("VK_DOWN", editor, view.styleWindow);
     93  is(editor.popup.selectedIndex, 1, "Using DOWN cycles autocomplete values.");
     94  await synthesizeKeyForAutocomplete("VK_DOWN", editor, view.styleWindow);
     95  is(editor.popup.selectedIndex, 2, "Using DOWN cycles autocomplete values.");
     96  await synthesizeKeyForAutocomplete("VK_UP", editor, view.styleWindow);
     97  is(editor.popup.selectedIndex, 1, "Using UP cycles autocomplete values.");
     98  item = editor.popup.getItemAtIndex(editor.popup.selectedIndex);
     99  is(item.label, "red", "Check autocomplete displays expected value.");
    100 
    101  info("Select the background-color suggestion with a mouse click.");
    102  let onRuleviewChanged = view.once("ruleview-changed");
    103  const onSuggest = editor.once("after-suggest");
    104 
    105  const node = editor.popup.list.childNodes[editor.popup.selectedIndex];
    106  EventUtils.synthesizeMouseAtCenter(node, {}, node.ownerGlobal);
    107 
    108  view.debounce.flush();
    109  await onSuggest;
    110  await onRuleviewChanged;
    111 
    112  is(
    113    editor.input.value,
    114    EXPECTED_CSS_VALUE,
    115    "Input value correctly autocompleted"
    116  );
    117 
    118  info("Press ESCAPE to leave the input.");
    119  onRuleviewChanged = view.once("ruleview-changed");
    120  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.styleWindow);
    121  await onRuleviewChanged;
    122 });
    123 
    124 /**
    125 * Send the provided key to the currently focused input of the provided window.
    126 * Wait for the editor to emit "after-suggest" to make sure the autocompletion
    127 * process is finished.
    128 *
    129 * @param {string} key
    130 *        The key to send to the input.
    131 * @param {InplaceEditor} editor
    132 *        The inplace editor which owns the focused input.
    133 * @param {Window} win
    134 *        Window in which the key event will be dispatched.
    135 */
    136 async function synthesizeKeyForAutocomplete(key, editor, win) {
    137  const onSuggest = editor.once("after-suggest");
    138  EventUtils.synthesizeKey(key, {}, win);
    139  await onSuggest;
    140 }