From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../interactions/browser_interactions_typing.js | 410 +++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 browser/components/places/tests/browser/interactions/browser_interactions_typing.js (limited to 'browser/components/places/tests/browser/interactions/browser_interactions_typing.js') diff --git a/browser/components/places/tests/browser/interactions/browser_interactions_typing.js b/browser/components/places/tests/browser/interactions/browser_interactions_typing.js new file mode 100644 index 0000000000..6561a4d334 --- /dev/null +++ b/browser/components/places/tests/browser/interactions/browser_interactions_typing.js @@ -0,0 +1,410 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Tests reporting of typing interactions. + */ + +"use strict"; + +const TEST_URL = + "https://example.com/browser/browser/components/places/tests/browser/keyword_form.html"; +const TEST_URL2 = "https://example.com/browser"; +const TEST_URL3 = + "https://example.com/browser/browser/base/content/test/contextMenu/subtst_contextmenu_input.html"; + +const sentence = "The quick brown fox jumps over the lazy dog."; +const sentenceFragments = [ + "The quick", + " brown fox", + " jumps over the lazy dog.", +]; +const longSentence = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas ut purus a libero cursus scelerisque. In hac habitasse platea dictumst. Quisque posuere ante sed consequat volutpat."; + +// For tests where it matters reduces the maximum time between keypresses to a length that we can +// afford to delay the test by. +const PREF_TYPING_DELAY = "browser.places.interactions.typing_timeout_ms"; +const POST_TYPING_DELAY = 150; + +async function sendTextToInput(browser, text) { + await SpecialPowers.spawn(browser, [], function () { + const input = content.document.querySelector( + "#form1 > input[name='search']" + ); + input.focus(); + input.value = ""; // Reset to later verify that the provided text matches the value + }); + + EventUtils.sendString(text); + + await SpecialPowers.spawn(browser, [{ text }], async function (args) { + await ContentTaskUtils.waitForCondition( + () => + content.document.querySelector("#form1 > input[name='search']").value == + args.text, + "Text has been set on input" + ); + }); +} + +add_task(async function test_load_and_navigate_away_no_keypresses() { + await Interactions.reset(); + await BrowserTestUtils.withNewTab(TEST_URL, async browser => { + BrowserTestUtils.loadURIString(browser, TEST_URL2); + await BrowserTestUtils.browserLoaded(browser, false, TEST_URL2); + + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: 0, + exactTypingTime: 0, + }, + ]); + + BrowserTestUtils.loadURIString(browser, "about:blank"); + await BrowserTestUtils.browserLoaded(browser, false, "about:blank"); + + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: 0, + exactTypingTime: 0, + }, + { + url: TEST_URL2, + keypresses: 0, + exactTypingTime: 0, + }, + ]); + }); +}); + +add_task(async function test_load_type_and_navigate_away() { + await Interactions.reset(); + + await BrowserTestUtils.withNewTab(TEST_URL, async browser => { + await sendTextToInput(browser, sentence); + + BrowserTestUtils.loadURIString(browser, TEST_URL2); + await BrowserTestUtils.browserLoaded(browser, false, TEST_URL2); + + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: sentence.length, + typingTimeIsGreaterThan: 0, + }, + ]); + + BrowserTestUtils.loadURIString(browser, "about:blank"); + await BrowserTestUtils.browserLoaded(browser, false, "about:blank"); + + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: sentence.length, + typingTimeIsGreaterThan: 0, + }, + { + url: TEST_URL2, + keypresses: 0, + exactTypingTime: 0, + }, + ]); + }); +}); + +add_task(async function test_no_typing_close_tab() { + await Interactions.reset(); + await BrowserTestUtils.withNewTab(TEST_URL, async browser => {}); + + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: 0, + exactTypingTime: 0, + }, + ]); +}); + +add_task(async function test_typing_close_tab() { + await Interactions.reset(); + + await BrowserTestUtils.withNewTab(TEST_URL, async browser => { + await sendTextToInput(browser, sentence); + }); + + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: sentence.length, + typingTimeIsGreaterThan: 0, + }, + ]); +}); + +add_task(async function test_single_key_typing_and_delay() { + await Interactions.reset(); + + Services.prefs.setIntPref(PREF_TYPING_DELAY, POST_TYPING_DELAY); + + try { + await BrowserTestUtils.withNewTab(TEST_URL, async browser => { + // Single keystrokes with a delay between each, are not considered typing + const text = ["T", "h", "e"]; + + for (let i = 0; i < text.length; i++) { + await sendTextToInput(browser, text[i]); + + // We do need to wait here because typing is defined as a series of keystrokes followed by a delay. + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(r => setTimeout(r, POST_TYPING_DELAY * 2)); + } + }); + } finally { + Services.prefs.clearUserPref(PREF_TYPING_DELAY); + } + + // Since we typed single keys with delays between each, there should be no typing added to the database + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: 0, + exactTypingTime: 0, + }, + ]); +}); + +add_task(async function test_double_key_typing_and_delay() { + await Interactions.reset(); + + // Test three 2-key typing bursts. + const text = ["Ab", "cd", "ef"]; + + const testStartTime = Cu.now(); + + Services.prefs.setIntPref(PREF_TYPING_DELAY, POST_TYPING_DELAY); + + try { + await BrowserTestUtils.withNewTab(TEST_URL, async browser => { + for (let i = 0; i < text.length; i++) { + await sendTextToInput(browser, text[i]); + + // We do need to wait here because typing is defined as a series of keystrokes followed by a delay. + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(r => setTimeout(r, POST_TYPING_DELAY * 2)); + } + }); + } finally { + Services.prefs.clearUserPref(PREF_TYPING_DELAY); + } + + // All keys should be recorded + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: text.reduce( + (accumulator, current) => accumulator + current.length, + 0 + ), + typingTimeIsLessThan: Cu.now() - testStartTime, + }, + ]); +}); + +add_task(async function test_typing_and_delay() { + await Interactions.reset(); + + const testStartTime = Cu.now(); + + Services.prefs.setIntPref(PREF_TYPING_DELAY, POST_TYPING_DELAY); + + try { + await BrowserTestUtils.withNewTab(TEST_URL, async browser => { + for (let i = 0; i < sentenceFragments.length; i++) { + await sendTextToInput(browser, sentenceFragments[i]); + + // We do need to wait here because typing is defined as a series of keystrokes followed by a delay. + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(r => setTimeout(r, POST_TYPING_DELAY * 2)); + } + }); + } finally { + Services.prefs.clearUserPref(PREF_TYPING_DELAY); + } + + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: sentenceFragments.reduce( + (accumulator, current) => accumulator + current.length, + 0 + ), + typingTimeIsGreaterThan: 0, + typingTimeIsLessThan: Cu.now() - testStartTime, + }, + ]); +}); + +add_task(async function test_typing_and_reload() { + await Interactions.reset(); + + const testStartTime = Cu.now(); + + await BrowserTestUtils.withNewTab(TEST_URL, async browser => { + await sendTextToInput(browser, sentenceFragments[0]); + + info("reload"); + browser.reload(); + await BrowserTestUtils.browserLoaded(browser, false, TEST_URL); + + // First typing should have been recorded + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: sentenceFragments[0].length, + typingTimeIsGreaterThan: 0, + }, + ]); + + await sendTextToInput(browser, sentenceFragments[1]); + + info("reload"); + browser.reload(); + await BrowserTestUtils.browserLoaded(browser, false, TEST_URL); + + // Second typing should have been recorded + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: sentenceFragments[0].length, + typingTimeIsGreaterThan: 0, + typingTimeIsLessThan: Cu.now() - testStartTime, + }, + { + url: TEST_URL, + keypresses: sentenceFragments[1].length, + typingTimeIsGreaterThan: 0, + typingTimeIsLessThan: Cu.now() - testStartTime, + }, + ]); + }); +}).skip(); // Bug 1749328 - intermittent failure: dropping the 2nd interaction after the 2nd reload + +add_task(async function test_switch_tabs_no_typing() { + await Interactions.reset(); + + let tab1 = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + url: TEST_URL, + }); + + let tab2 = BrowserTestUtils.addTab(gBrowser, TEST_URL2); + await BrowserTestUtils.browserLoaded(tab2.linkedBrowser, false, TEST_URL2); + + info("Switch to second tab"); + gBrowser.selectedTab = tab2; + + // Only the interaction of the first tab should be recorded so far, and with no typing + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: 0, + exactTypingTime: 0, + }, + ]); + + BrowserTestUtils.removeTab(tab1); + BrowserTestUtils.removeTab(tab2); +}); + +add_task(async function test_typing_switch_tabs() { + await Interactions.reset(); + + let tab1 = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + url: TEST_URL, + }); + + await sendTextToInput(tab1.linkedBrowser, sentence); + + let tab2 = BrowserTestUtils.addTab(gBrowser, TEST_URL3); + await BrowserTestUtils.browserLoaded(tab2.linkedBrowser, false, TEST_URL3); + + info("Switch to second tab"); + await BrowserTestUtils.switchTab(gBrowser, tab2); + + // Only the interaction of the first tab should be recorded so far + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: sentence.length, + typingTimeIsGreaterThan: 0, + }, + ]); + + const tab1TyingTime = await getDatabaseValue(TEST_URL, "typingTime"); + + info("Switch back to first tab"); + await BrowserTestUtils.switchTab(gBrowser, tab1); + + // The interaction of the second tab should now be recorded (no typing) + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: sentence.length, + exactTypingTime: tab1TyingTime, + }, + { + url: TEST_URL3, + keypresses: 0, + exactTypingTime: 0, + }, + ]); + + info("Switch back to the second tab"); + await BrowserTestUtils.switchTab(gBrowser, tab2); + + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: sentence.length, + exactTypingTime: tab1TyingTime, + }, + { + url: TEST_URL3, + keypresses: 0, + exactTypingTime: 0, + }, + ]); + + // Typing into the second tab + await SpecialPowers.spawn(tab2.linkedBrowser, [], function () { + const input = content.document.getElementById("input_text"); + input.focus(); + }); + await EventUtils.sendString(longSentence); + await TestUtils.waitForTick(); + + info("Switch back to first tab"); + await BrowserTestUtils.switchTab(gBrowser, tab1); + + // The interaction of the second tab should now also be recorded (with typing) + await assertDatabaseValues([ + { + url: TEST_URL, + keypresses: sentence.length, + exactTypingTime: tab1TyingTime, + }, + { + url: TEST_URL3, + keypresses: longSentence.length, + typingTimeIsGreaterThan: 0, + }, + ]); + + BrowserTestUtils.removeTab(tab1); + BrowserTestUtils.removeTab(tab2); +}); -- cgit v1.2.3