1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
6 const { CustomizableUITestUtils } = ChromeUtils.import(
7 "resource://testing-common/CustomizableUITestUtils.jsm"
9 const { ContentTaskUtils } = ChromeUtils.import(
10 "resource://testing-common/ContentTaskUtils.jsm"
12 const gCUITestUtils = new CustomizableUITestUtils(window);
13 const gDOMWindowUtils = EventUtils._getDOMWindowUtils(window);
15 add_task(async function test_setup() {
16 await gCUITestUtils.addSearchBar();
17 registerCleanupFunction(() => {
18 gCUITestUtils.removeSearchBar();
22 function promiseResettingSearchBarAndFocus() {
23 const waitForFocusInSearchBar = BrowserTestUtils.waitForEvent(
24 BrowserSearch.searchBar.textbox,
27 BrowserSearch.searchBar.textbox.focus();
28 BrowserSearch.searchBar.textbox.value = "";
30 waitForFocusInSearchBar,
31 TestUtils.waitForCondition(
33 gDOMWindowUtils.IMEStatus === Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED &&
34 gDOMWindowUtils.inputContextOrigin ===
35 Ci.nsIDOMWindowUtils.INPUT_CONTEXT_ORIGIN_MAIN
40 function promiseIMEStateEnabledByRemote() {
41 return TestUtils.waitForCondition(
43 gDOMWindowUtils.IMEStatus === Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED &&
44 gDOMWindowUtils.inputContextOrigin ===
45 Ci.nsIDOMWindowUtils.INPUT_CONTEXT_ORIGIN_CONTENT
49 function promiseContentTick(browser) {
50 return SpecialPowers.spawn(browser, [], async () => {
51 await new Promise(r => {
52 content.requestAnimationFrame(() => {
53 content.requestAnimationFrame(r);
59 add_task(async function test_text_editor_in_chrome() {
60 await promiseResettingSearchBarAndFocus();
63 function logEvent(event) {
66 BrowserSearch.searchBar.textbox.addEventListener("beforeinput", logEvent);
67 gDOMWindowUtils.sendContentCommandEvent("insertText", null, "XYZ");
70 BrowserSearch.searchBar.textbox.value,
72 "The string should be inserted into the focused search bar"
77 "One beforeinput event should be fired in the searchbar"
79 is(events[0]?.inputType, "insertText", 'inputType should be "insertText"');
80 is(events[0]?.data, "XYZ", 'inputType should be "XYZ"');
81 is(events[0]?.cancelable, true, "beforeinput event should be cancelable");
82 BrowserSearch.searchBar.textbox.removeEventListener("beforeinput", logEvent);
84 BrowserSearch.searchBar.textbox.blur();
87 add_task(async function test_text_editor_in_content() {
92 nonTarget: "input + input",
93 page: 'data:text/html,<input value="abc"><input value="def">',
98 nonTarget: "textarea + textarea",
99 page: "data:text/html,<textarea>abc</textarea><textarea>def</textarea>",
102 // Once, move focus to chrome's searchbar.
103 await promiseResettingSearchBarAndFocus();
105 await BrowserTestUtils.withNewTab(test.page, async browser => {
106 await SpecialPowers.spawn(browser, [test], async function(aTest) {
107 content.window.focus();
108 await ContentTaskUtils.waitForCondition(() =>
109 content.document.hasFocus()
111 const target = content.document.querySelector(aTest.target);
113 target.selectionStart = target.selectionEnd = 2;
114 content.document.documentElement.scrollTop; // Flush pending things
117 await promiseIMEStateEnabledByRemote();
118 const waitForBeforeInputEvent = SpecialPowers.spawn(
121 async function(aTest) {
122 await new Promise(resolve => {
123 content.document.querySelector(aTest.target).addEventListener(
129 `The inputType of beforeinput event fired on <${aTest.target}> should be "insertText"`
134 `The data of beforeinput event fired on <${aTest.target}> should be "XYZ"`
139 `The beforeinput event fired on <${aTest.target}> should be cancelable`
148 const waitForInputEvent = BrowserTestUtils.waitForContentEvent(
152 await promiseContentTick(browser); // Ensure "input" event listener in the remote process
153 gDOMWindowUtils.sendContentCommandEvent("insertText", null, "XYZ");
154 await waitForBeforeInputEvent;
155 await waitForInputEvent;
157 await SpecialPowers.spawn(browser, [test], async function(aTest) {
159 content.document.querySelector(aTest.target).value,
161 `The string should be inserted into the focused <${aTest.target}> element`
164 content.document.querySelector(aTest.nonTarget).value,
166 `The string should not be inserted into the non-focused <${aTest.nonTarget}> element`
172 BrowserSearch.searchBar.textbox.value,
174 "The string should not be inserted into the previously focused search bar"
179 add_task(async function test_html_editor_in_content() {
182 mode: "contenteditable",
184 page: "data:text/html,<div contenteditable>abc</div>",
189 page: "data:text/html,<div>abc</div>",
192 // Once, move focus to chrome's searchbar.
193 await promiseResettingSearchBarAndFocus();
195 await BrowserTestUtils.withNewTab(test.page, async browser => {
196 await SpecialPowers.spawn(browser, [test], async function(aTest) {
197 content.window.focus();
198 await ContentTaskUtils.waitForCondition(() =>
199 content.document.hasFocus()
201 const target = content.document.querySelector(aTest.target);
202 if (aTest.mode == "designMode") {
203 content.document.designMode = "on";
204 content.window.focus();
208 content.window.getSelection().collapse(target.firstChild, 2);
209 content.document.documentElement.scrollTop; // Flush pending things
212 await promiseIMEStateEnabledByRemote();
213 const waitForBeforeInputEvent = SpecialPowers.spawn(
216 async function(aTest) {
217 await new Promise(resolve => {
219 aTest.mode === "designMode"
221 : content.document.querySelector(aTest.target);
222 eventTarget.addEventListener(
228 `The inputType of beforeinput event fired on ${aTest.mode} editor should be "insertText"`
233 `The data of beforeinput event fired on ${aTest.mode} editor should be "XYZ"`
238 `The beforeinput event fired on ${aTest.mode} editor should be cancelable`
247 const waitForInputEvent = BrowserTestUtils.waitForContentEvent(
251 await promiseContentTick(browser); // Ensure "input" event listener in the remote process
252 gDOMWindowUtils.sendContentCommandEvent("insertText", null, "XYZ");
253 await waitForBeforeInputEvent;
254 await waitForInputEvent;
256 await SpecialPowers.spawn(browser, [test], async function(aTest) {
258 content.document.querySelector(aTest.target).innerHTML,
260 `The string should be inserted into the focused ${aTest.mode} editor`
266 BrowserSearch.searchBar.textbox.value,
268 "The string should not be inserted into the previously focused search bar"