summaryrefslogtreecommitdiffstats
path: root/browser/components/places/tests/browser/interactions/browser_interactions_typing.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/places/tests/browser/interactions/browser_interactions_typing.js')
-rw-r--r--browser/components/places/tests/browser/interactions/browser_interactions_typing.js410
1 files changed, 410 insertions, 0 deletions
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);
+});