summaryrefslogtreecommitdiffstats
path: root/devtools/client/sourceeditor/test/browser_editor_find_again.js
blob: f3d80095bbc3cbf6f4a198a959a3f66ee8b705cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/* -*- 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 <input> is not ready yet.
// Therefore, we trigger the UI focus event to the <input>, 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 <input>'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);
});