summaryrefslogtreecommitdiffstats
path: root/toolkit/components/aboutconfig/test/browser/browser_edit.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /toolkit/components/aboutconfig/test/browser/browser_edit.js
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/aboutconfig/test/browser/browser_edit.js')
-rw-r--r--toolkit/components/aboutconfig/test/browser/browser_edit.js430
1 files changed, 430 insertions, 0 deletions
diff --git a/toolkit/components/aboutconfig/test/browser/browser_edit.js b/toolkit/components/aboutconfig/test/browser/browser_edit.js
new file mode 100644
index 0000000000..9d10fb1e75
--- /dev/null
+++ b/toolkit/components/aboutconfig/test/browser/browser_edit.js
@@ -0,0 +1,430 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const PREF_MODIFY_PREFIX = "test.aboutconfig.modify";
+const PREF_MODIFY_BOOLEAN = "test.aboutconfig.modify.boolean";
+const PREF_MODIFY_NUMBER = "test.aboutconfig.modify.number";
+const PREF_MODIFY_STRING = "test.aboutconfig.modify.string";
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [PREF_MODIFY_BOOLEAN, true],
+ [PREF_MODIFY_NUMBER, 1337],
+ [
+ PREF_MODIFY_STRING,
+ "the answer to the life the universe and everything",
+ ],
+ ],
+ });
+
+ registerCleanupFunction(() => {
+ Services.prefs.clearUserPref(PREF_BOOLEAN_DEFAULT_TRUE);
+ Services.prefs.clearUserPref(PREF_NUMBER_DEFAULT_ZERO);
+ Services.prefs.clearUserPref(PREF_STRING_DEFAULT_EMPTY);
+ });
+});
+
+add_task(async function test_add_user_pref() {
+ Assert.equal(
+ Services.prefs.getPrefType(PREF_NEW),
+ Ci.nsIPrefBranch.PREF_INVALID
+ );
+
+ await AboutConfigTest.withNewTab(async function () {
+ // The row for a new preference appears when searching for its name.
+ Assert.ok(!this.getRow(PREF_NEW));
+
+ for (let [radioIndex, expectedValue, expectedEditingMode] of [
+ [0, true, false],
+ [1, 0, true],
+ [2, "", true],
+ ]) {
+ this.search(PREF_NEW);
+ let row = this.getRow(PREF_NEW);
+ Assert.ok(row.hasClass("deleted"));
+ Assert.ok(row.hasClass("add"));
+
+ // Adding the preference should set the default for the data type.
+ row.element.querySelectorAll("input")[radioIndex].click();
+ row.editColumnButton.click();
+ Assert.ok(!row.hasClass("deleted"));
+ Assert.ok(!row.hasClass("add"));
+ Assert.ok(Preferences.get(PREF_NEW) === expectedValue);
+
+ // Number and String preferences should be in edit mode.
+ Assert.equal(!!row.valueInput, expectedEditingMode);
+
+ // Repeat the search to verify that the preference remains.
+ this.search(PREF_NEW);
+ row = this.getRow(PREF_NEW);
+ Assert.ok(!row.hasClass("deleted"));
+ Assert.ok(!row.hasClass("add"));
+ Assert.ok(!row.valueInput);
+
+ // Reset the preference, then continue by adding a different type.
+ row.resetColumnButton.click();
+ Assert.equal(
+ Services.prefs.getPrefType(PREF_NEW),
+ Ci.nsIPrefBranch.PREF_INVALID
+ );
+ }
+ });
+});
+
+add_task(async function test_delete_user_pref() {
+ for (let [radioIndex, testValue] of [
+ [0, false],
+ [1, -1],
+ [2, "value"],
+ ]) {
+ Preferences.set(PREF_NEW, testValue);
+ await AboutConfigTest.withNewTab(async function () {
+ // Deleting the preference should keep the row.
+ let row = this.getRow(PREF_NEW);
+ row.resetColumnButton.click();
+ Assert.ok(row.hasClass("deleted"));
+ Assert.equal(
+ Services.prefs.getPrefType(PREF_NEW),
+ Ci.nsIPrefBranch.PREF_INVALID
+ );
+
+ // Re-adding the preference should keep the same value.
+ Assert.ok(row.element.querySelectorAll("input")[radioIndex].checked);
+ row.editColumnButton.click();
+ Assert.ok(!row.hasClass("deleted"));
+ Assert.ok(Preferences.get(PREF_NEW) === testValue);
+
+ // Filtering again after deleting should remove the row.
+ row.resetColumnButton.click();
+ this.showAll();
+ Assert.ok(!this.getRow(PREF_NEW));
+ });
+ }
+});
+
+add_task(async function test_click_type_label_multiple_forms() {
+ // This test displays the row to add a preference while other preferences are
+ // also displayed, and tries to select the type of the new preference by
+ // clicking the label next to the radio button. This should work even if the
+ // user has deleted a different preference, and multiple forms are displayed.
+ const PREF_TO_DELETE = "test.aboutconfig.modify.boolean";
+ const PREF_NEW_WHILE_DELETED = "test.aboutconfig.modify.";
+
+ await AboutConfigTest.withNewTab(async function () {
+ this.search(PREF_NEW_WHILE_DELETED);
+
+ // This preference will remain deleted during the test.
+ let existingRow = this.getRow(PREF_TO_DELETE);
+ existingRow.resetColumnButton.click();
+
+ let newRow = this.getRow(PREF_NEW_WHILE_DELETED);
+
+ for (let [radioIndex, expectedValue] of [
+ [0, true],
+ [1, 0],
+ [2, ""],
+ ]) {
+ let radioLabels = newRow.element.querySelectorAll("label > span");
+ await this.document.l10n.translateElements(radioLabels);
+
+ // Even if this is the second form on the page, the click should select
+ // the radio button next to the label, not the one on the first form.
+ EventUtils.synthesizeMouseAtCenter(
+ radioLabels[radioIndex],
+ {},
+ this.browser.contentWindow
+ );
+
+ // Adding the preference should set the default for the data type.
+ newRow.editColumnButton.click();
+ Assert.ok(Preferences.get(PREF_NEW_WHILE_DELETED) === expectedValue);
+
+ // Reset the preference, then continue by adding a different type.
+ newRow.resetColumnButton.click();
+ }
+
+ // Re-adding the deleted preference should restore the value.
+ existingRow.editColumnButton.click();
+ Assert.ok(Preferences.get(PREF_TO_DELETE) === true);
+ });
+});
+
+add_task(async function test_reset_user_pref() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [PREF_BOOLEAN_DEFAULT_TRUE, false],
+ [PREF_STRING_LOCALIZED_MISSING, "user-value"],
+ ],
+ });
+
+ await AboutConfigTest.withNewTab(async function () {
+ // Click reset.
+ let row = this.getRow(PREF_BOOLEAN_DEFAULT_TRUE);
+ row.resetColumnButton.click();
+ // Check new layout and reset.
+ Assert.ok(!row.hasClass("has-user-value"));
+ Assert.ok(!row.resetColumnButton);
+ Assert.ok(!Services.prefs.prefHasUserValue(PREF_BOOLEAN_DEFAULT_TRUE));
+ Assert.equal(this.getRow(PREF_BOOLEAN_DEFAULT_TRUE).value, "true");
+
+ // Filter again to test the preference cache.
+ this.showAll();
+ row = this.getRow(PREF_BOOLEAN_DEFAULT_TRUE);
+ Assert.ok(!row.hasClass("has-user-value"));
+ Assert.ok(!row.resetColumnButton);
+ Assert.equal(this.getRow(PREF_BOOLEAN_DEFAULT_TRUE).value, "true");
+
+ // Clicking reset on a localized preference without a corresponding value.
+ row = this.getRow(PREF_STRING_LOCALIZED_MISSING);
+ Assert.equal(row.value, "user-value");
+ row.resetColumnButton.click();
+ // Check new layout and reset.
+ Assert.ok(!row.hasClass("has-user-value"));
+ Assert.ok(!row.resetColumnButton);
+ Assert.ok(!Services.prefs.prefHasUserValue(PREF_STRING_LOCALIZED_MISSING));
+ Assert.equal(this.getRow(PREF_STRING_LOCALIZED_MISSING).value, "");
+ });
+});
+
+add_task(async function test_modify() {
+ await AboutConfigTest.withNewTab(async function () {
+ // Test toggle for boolean prefs.
+ for (let nameOfBoolPref of [
+ PREF_MODIFY_BOOLEAN,
+ PREF_BOOLEAN_DEFAULT_TRUE,
+ ]) {
+ let row = this.getRow(nameOfBoolPref);
+ // Do this a two times to reset the pref.
+ for (let i = 0; i < 2; i++) {
+ row.editColumnButton.click();
+ // Check new layout and saving in backend.
+ Assert.equal(
+ this.getRow(nameOfBoolPref).value,
+ "" + Preferences.get(nameOfBoolPref)
+ );
+ let prefHasUserValue = Services.prefs.prefHasUserValue(nameOfBoolPref);
+ Assert.equal(row.hasClass("has-user-value"), prefHasUserValue);
+ Assert.equal(!!row.resetColumnButton, prefHasUserValue);
+ }
+ }
+
+ // Test abort of edit by starting with string and continuing with editing Int pref.
+ let row = this.getRow(PREF_MODIFY_STRING);
+ row.editColumnButton.click();
+ row.valueInput.value = "test";
+ let intRow = this.getRow(PREF_MODIFY_NUMBER);
+ intRow.editColumnButton.click();
+ Assert.equal(intRow.valueInput.value, Preferences.get(PREF_MODIFY_NUMBER));
+ Assert.ok(!row.valueInput);
+ Assert.equal(row.value, Preferences.get(PREF_MODIFY_STRING));
+
+ // Test validation of integer values.
+ for (let invalidValue of [
+ "",
+ " ",
+ "a",
+ "1.5",
+ "-2147483649",
+ "2147483648",
+ ]) {
+ intRow.valueInput.value = invalidValue;
+ intRow.editColumnButton.click();
+ // We should still be in edit mode.
+ Assert.ok(intRow.valueInput);
+ }
+
+ // Test correct saving and DOM-update.
+ for (let [prefName, willDelete] of [
+ [PREF_MODIFY_STRING, true],
+ [PREF_MODIFY_NUMBER, true],
+ [PREF_NUMBER_DEFAULT_ZERO, false],
+ [PREF_STRING_DEFAULT_EMPTY, false],
+ ]) {
+ row = this.getRow(prefName);
+ // Activate edit and check displaying.
+ row.editColumnButton.click();
+ Assert.equal(row.valueInput.value, Preferences.get(prefName));
+ row.valueInput.value = "42";
+ // Save and check saving.
+ row.editColumnButton.click();
+ Assert.equal(Preferences.get(prefName), "42");
+ Assert.equal(row.value, "42");
+ Assert.ok(row.hasClass("has-user-value"));
+ // Reset or delete the preference while editing.
+ row.editColumnButton.click();
+ Assert.equal(row.valueInput.value, Preferences.get(prefName));
+ row.resetColumnButton.click();
+ Assert.ok(!row.hasClass("has-user-value"));
+ Assert.equal(row.hasClass("deleted"), willDelete);
+ }
+ });
+
+ // This test would have opened the invalid form popup, so just close it so as not to
+ // affect later tests.
+ let invalidFormPopup = window.document.getElementById("invalid-form-popup");
+ invalidFormPopup.hidePopup();
+ await BrowserTestUtils.waitForCondition(() => {
+ return invalidFormPopup.state == "closed";
+ }, "form validation popup closed");
+});
+
+add_task(async function test_edit_field_selected() {
+ let prefsToCheck = [
+ [PREF_MODIFY_STRING, "A string", "A new string"],
+ [PREF_MODIFY_NUMBER, "100", "500"],
+ ];
+ await AboutConfigTest.withNewTab(async function () {
+ for (let [prefName, startValue, endValue] of prefsToCheck) {
+ Preferences.set(prefName, startValue);
+ let row = this.getRow(prefName);
+
+ Assert.equal(row.value, startValue);
+ row.editColumnButton.click();
+ Assert.equal(row.valueInput.value, startValue);
+
+ EventUtils.sendString(endValue, this.window);
+
+ row.editColumnButton.click();
+ Assert.equal(row.value, endValue);
+ Assert.equal(Preferences.get(prefName), endValue);
+ }
+ });
+});
+
+add_task(async function test_escape_cancels_edit() {
+ await AboutConfigTest.withNewTab(async function () {
+ let row = this.getRow(PREF_MODIFY_STRING);
+ Preferences.set(PREF_MODIFY_STRING, "Edit me, maybe");
+
+ for (let blurInput of [false, true]) {
+ Assert.ok(!row.valueInput);
+ row.editColumnButton.click();
+
+ Assert.ok(row.valueInput);
+
+ Assert.equal(row.valueInput.value, "Edit me, maybe");
+ row.valueInput.value = "Edited";
+
+ // Test both cases of the input being focused and not being focused.
+ if (blurInput) {
+ row.valueInput.blur();
+ Assert.notEqual(this.document.activeElement, row.valueInput);
+ } else {
+ Assert.equal(this.document.activeElement, row.valueInput);
+ }
+
+ EventUtils.synthesizeKey("KEY_Escape", {}, this.window);
+
+ Assert.ok(!row.valueInput);
+ Assert.equal(row.value, "Edit me, maybe");
+ Assert.equal(row.value, Preferences.get(PREF_MODIFY_STRING));
+ }
+ });
+});
+
+add_task(async function test_double_click_modify() {
+ Preferences.set(PREF_MODIFY_BOOLEAN, true);
+ Preferences.set(PREF_MODIFY_NUMBER, 10);
+ Preferences.set(PREF_MODIFY_STRING, "Hello!");
+
+ await AboutConfigTest.withNewTab(async function () {
+ this.search(PREF_MODIFY_PREFIX);
+
+ let click = (target, opts) =>
+ EventUtils.synthesizeMouseAtCenter(target, opts, this.window);
+ let doubleClick = target => {
+ // Trigger two mouse events to simulate the first then second click.
+ click(target, { clickCount: 1 });
+ click(target, { clickCount: 2 });
+ };
+ let tripleClick = target => {
+ // Trigger all 3 mouse events to simulate the three mouse events we'd see.
+ click(target, { clickCount: 1 });
+ click(target, { clickCount: 2 });
+ click(target, { clickCount: 3 });
+ };
+
+ // Check double-click to edit a boolean.
+ let boolRow = this.getRow(PREF_MODIFY_BOOLEAN);
+ Assert.equal(boolRow.value, "true");
+ doubleClick(boolRow.valueCell);
+ Assert.equal(boolRow.value, "false");
+ doubleClick(boolRow.nameCell);
+ Assert.equal(boolRow.value, "true");
+
+ // Check double-click to edit a number.
+ let intRow = this.getRow(PREF_MODIFY_NUMBER);
+ Assert.equal(intRow.value, 10);
+ doubleClick(intRow.valueCell);
+ Assert.equal(this.document.activeElement, intRow.valueInput);
+ EventUtils.sendString("75");
+ EventUtils.synthesizeKey("KEY_Enter");
+ Assert.equal(intRow.value, 75);
+
+ // Check double-click focuses input when already editing.
+ Assert.equal(intRow.value, 75);
+ doubleClick(intRow.nameCell);
+ Assert.equal(this.document.activeElement, intRow.valueInput);
+ intRow.valueInput.blur();
+ Assert.notEqual(this.document.activeElement, intRow.valueInput);
+ doubleClick(intRow.nameCell);
+ Assert.equal(this.document.activeElement, intRow.valueInput);
+ EventUtils.sendString("20");
+ EventUtils.synthesizeKey("KEY_Enter");
+ Assert.equal(intRow.value, 20);
+
+ // Check double-click to edit a string.
+ let stringRow = this.getRow(PREF_MODIFY_STRING);
+ Assert.equal(stringRow.value, "Hello!");
+ doubleClick(stringRow.valueCell);
+ Assert.equal(
+ this.document.activeElement,
+ stringRow.valueInput,
+ "The input is focused"
+ );
+ EventUtils.sendString("New String!");
+ EventUtils.synthesizeKey("KEY_Enter");
+ Assert.equal(stringRow.value, "New String!");
+
+ // Check triple-click also edits the pref and selects the text inside.
+ tripleClick(stringRow.nameCell);
+ Assert.equal(
+ this.document.activeElement,
+ stringRow.valueInput,
+ "The input is focused"
+ );
+
+ // Check double-click inside input selects a word.
+ let newString = "Another string...";
+ EventUtils.sendString(newString);
+ Assert.equal(this.window.getSelection().toString(), "");
+ let stringInput = stringRow.valueInput;
+ doubleClick(stringInput);
+ let selectionLength = stringInput.selectionEnd - stringInput.selectionStart;
+ Assert.greater(selectionLength, 0);
+ Assert.less(selectionLength, newString.length);
+ EventUtils.synthesizeKey("KEY_Enter");
+ Assert.equal(stringRow.value, newString);
+
+ // Check that double/triple-click on the add row selects text as usual.
+ let addRow = this.getRow(PREF_MODIFY_PREFIX);
+ Assert.ok(addRow.hasClass("deleted"));
+ doubleClick(addRow.nameCell);
+ Assert.ok(PREF_MODIFY_PREFIX.includes(this.window.getSelection()));
+ tripleClick(addRow.nameCell);
+ Assert.equal(this.window.getSelection().toString(), PREF_MODIFY_PREFIX);
+ // Make sure the localized text is set in the value cell.
+ let labels = Array.from(addRow.valueCell.querySelectorAll("label > span"));
+ await this.document.l10n.translateElements(labels);
+ Assert.ok(labels.every(label => !!label.textContent));
+ // Double-click the first input label text.
+ doubleClick(labels[0]);
+ Assert.equal(this.window.getSelection().toString(), labels[0].textContent);
+ tripleClick(addRow.valueCell.querySelector("label > span"));
+ Assert.equal(
+ this.window.getSelection().toString(),
+ labels.map(l => l.textContent).join("")
+ );
+ });
+});