/* -*- indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {LocalizationHelper} = require("devtools/shared/l10n");
const L10N = new LocalizationHelper("devtools/client/locales/sourceeditor.properties");
const { OS } = Services.appinfo;
// On linux, getting immediately the selection's range here fails, returning
const FIND_KEY = L10N.getStr("find.key");
const FINDNEXT_KEY = L10N.getStr("findNext.key");
const FINDPREV_KEY = L10N.getStr("findPrev.key");
// the replace's key with the appropriate modifiers based on OS
const REPLACE_KEY = OS == "Darwin" ? L10N.getStr("replaceAllMac.key") : L10N.getStr("replaceAll.key");
// values like it's not selected – even if the selection is visible.
// For the record, setting the selection's range immediately doesn't have
// any effect.
// It's like the is not ready yet.
// Therefore, we trigger the UI focus event to the , waiting for the
// response.
// Using a timeout could also work, but that is more precise, ensuring also
// the execution of the listeners added to the 's focus.
const dispatchAndWaitForFocus = (target) => new Promise((resolve) => {
target.addEventListener("focus", function listener() {
target.removeEventListener("focus", listener);
resolve(target);
});
target.dispatchEvent(new UIEvent("focus"));
});
function openSearchBox(ed) {
let edDoc = ed.container.contentDocument;
let edWin = edDoc.defaultView;
let input = edDoc.querySelector("input[type=search]");
ok(!input, "search box closed");
// The editor needs the focus to properly receive the `synthesizeKey`
ed.focus();
synthesizeKeyShortcut(FINDNEXT_KEY, edWin);
input = edDoc.querySelector("input[type=search]");
ok(input, "find again command key opens the search box");
}
function testFindAgain(ed, inputLine, expectCursor, isFindPrev = false) {
let edDoc = ed.container.contentDocument;
let edWin = edDoc.defaultView;
let input = edDoc.querySelector("input[type=search]");
input.value = inputLine;
// Ensure the input has the focus before send the key – necessary on Linux,
// it seems that during the tests can be lost
input.focus();
if (isFindPrev) {
synthesizeKeyShortcut(FINDPREV_KEY, edWin);
} else {
synthesizeKeyShortcut(FINDNEXT_KEY, edWin);
}
ch(ed.getCursor(), expectCursor,
"find: " + inputLine + " expects cursor: " + expectCursor.toSource());
}
const testSearchBoxTextIsSelected = Task.async(function* (ed) {
let edDoc = ed.container.contentDocument;
let edWin = edDoc.defaultView;
let input = edDoc.querySelector("input[type=search]");
ok(input, "search box is opened");
// Ensure the input has the focus before send the key – necessary on Linux,
// it seems that during the tests can be lost
input.focus();
// Close search box
EventUtils.synthesizeKey("VK_ESCAPE", {}, edWin);
input = edDoc.querySelector("input[type=search]");
ok(!input, "search box is closed");
// Re-open the search box
synthesizeKeyShortcut(FIND_KEY, edWin);
input = edDoc.querySelector("input[type=search]");
ok(input, "find command key opens the search box");
yield dispatchAndWaitForFocus(input);
let { selectionStart, selectionEnd, value } = input;
ok(selectionStart === 0 && selectionEnd === value.length,
"search box's text is selected when re-opened");
// Removing selection
input.setSelectionRange(0, 0);
synthesizeKeyShortcut(FIND_KEY, edWin);
({ selectionStart, selectionEnd } = input);
ok(selectionStart === 0 && selectionEnd === value.length,
"search box's text is selected when find key is pressed");
// Close search box
EventUtils.synthesizeKey("VK_ESCAPE", {}, edWin);
});
const testReplaceBoxTextIsSelected = Task.async(function* (ed) {
let edDoc = ed.container.contentDocument;
let edWin = edDoc.defaultView;
let input = edDoc.querySelector(".CodeMirror-dialog > input");
ok(!input, "dialog box with replace is closed");
// The editor needs the focus to properly receive the `synthesizeKey`
ed.focus();
synthesizeKeyShortcut(REPLACE_KEY, edWin);
input = edDoc.querySelector(".CodeMirror-dialog > input");
ok(input, "dialog box with replace is opened");
input.value = "line 5";
// Ensure the input has the focus before send the key – necessary on Linux,
// it seems that during the tests can be lost
input.focus();
yield dispatchAndWaitForFocus(input);
let { selectionStart, selectionEnd, value } = input;
ok(!(selectionStart === 0 && selectionEnd === value.length),
"Text in dialog box is not selected");
synthesizeKeyShortcut(REPLACE_KEY, edWin);
({ selectionStart, selectionEnd } = input);
ok(selectionStart === 0 && selectionEnd === value.length,
"dialog box's text is selected when replace key is pressed");
// Close dialog box
EventUtils.synthesizeKey("VK_ESCAPE", {}, edWin);
});
add_task(function* () {
let { ed, win } = yield setup();
ed.setText([
"// line 1",
"// line 2",
"// line 3",
"// line 4",
"// line 5"
].join("\n"));
yield promiseWaitForFocus();
openSearchBox(ed);
let testVectors = [
// Starting here expect data needs to get updated for length changes to
// "textLines" above.
["line",
{line: 0, ch: 7}],
["line",
{line: 1, ch: 8}],
["line",
{line: 2, ch: 9}],
["line",
{line: 3, ch: 10}],
["line",
{line: 4, ch: 11}],
["ne 3",
{line: 2, ch: 11}],
["line 1",
{line: 0, ch: 9}],
// Testing find prev
["line",
{line: 4, ch: 11},
true],
["line",
{line: 3, ch: 10},
true],
["line",
{line: 2, ch: 9},
true],
["line",
{line: 1, ch: 8},
true],
["line",
{line: 0, ch: 7},
true]
];
for (let v of testVectors) {
yield testFindAgain(ed, ...v);
}
yield testSearchBoxTextIsSelected(ed);
yield testReplaceBoxTextIsSelected(ed);
teardown(ed, win);
});