diff options
Diffstat (limited to 'browser/components/preferences/tests/browser_connection_dnsoverhttps.js')
-rw-r--r-- | browser/components/preferences/tests/browser_connection_dnsoverhttps.js | 808 |
1 files changed, 808 insertions, 0 deletions
diff --git a/browser/components/preferences/tests/browser_connection_dnsoverhttps.js b/browser/components/preferences/tests/browser_connection_dnsoverhttps.js new file mode 100644 index 0000000000..71d7814fd8 --- /dev/null +++ b/browser/components/preferences/tests/browser_connection_dnsoverhttps.js @@ -0,0 +1,808 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +requestLongerTimeout(4); + +const { + EnterprisePolicyTesting, + PoliciesPrefTracker, +} = ChromeUtils.importESModule( + "resource://testing-common/EnterprisePolicyTesting.sys.mjs" +); + +ChromeUtils.defineModuleGetter( + this, + "DoHController", + "resource:///modules/DoHController.jsm" +); +ChromeUtils.defineModuleGetter( + this, + "DoHConfigController", + "resource:///modules/DoHConfig.jsm" +); +ChromeUtils.defineModuleGetter( + this, + "DoHTestUtils", + "resource://testing-common/DoHTestUtils.jsm" +); + +const SUBDIALOG_URL = + "chrome://browser/content/preferences/dialogs/connection.xhtml"; +const TRR_MODE_PREF = "network.trr.mode"; +const TRR_URI_PREF = "network.trr.uri"; +const TRR_CUSTOM_URI_PREF = "network.trr.custom_uri"; +const ROLLOUT_ENABLED_PREF = "doh-rollout.enabled"; +const ROLLOUT_SELF_ENABLED_PREF = "doh-rollout.self-enabled"; +const HEURISTICS_DISABLED_PREF = "doh-rollout.disable-heuristics"; +const FIRST_RESOLVER_VALUE = DoHTestUtils.providers[0].uri; +const SECOND_RESOLVER_VALUE = DoHTestUtils.providers[1].uri; +const DEFAULT_RESOLVER_VALUE = FIRST_RESOLVER_VALUE; + +const modeCheckboxSelector = "#networkDnsOverHttps"; +const uriTextboxSelector = "#networkCustomDnsOverHttpsInput"; +const resolverMenulistSelector = "#networkDnsOverHttpsResolverChoices"; +const defaultPrefValues = Object.freeze({ + [TRR_MODE_PREF]: 0, + [TRR_CUSTOM_URI_PREF]: "", +}); + +// See bug 1741554. This test should not actually try to create a connection to +// the real DoH endpoint. But a background request could do that while the test +// is in progress, before we've actually disabled TRR, and would cause a crash +// due to connecting to a non-local IP. +// To prevent that we override the IP to a local address. +Cc["@mozilla.org/network/native-dns-override;1"] + .getService(Ci.nsINativeDNSResolverOverride) + .addIPOverride("mozilla.cloudflare-dns.com", "127.0.0.1"); + +async function resetPrefs() { + await DoHTestUtils.resetRemoteSettingsConfig(); + await DoHController._uninit(); + Services.prefs.clearUserPref(TRR_MODE_PREF); + Services.prefs.clearUserPref(TRR_URI_PREF); + Services.prefs.clearUserPref(TRR_CUSTOM_URI_PREF); + Services.prefs.getChildList("doh-rollout.").forEach(pref => { + Services.prefs.clearUserPref(pref); + }); + // Clear out any telemetry events generated by DoHController so that we don't + // confuse tests running after this one that are looking at those. + Services.telemetry.clearEvents(); + await DoHController.init(); +} +Services.prefs.setStringPref("network.trr.confirmationNS", "skip"); +let preferencesOpen = new Promise(res => open_preferences(res)); + +registerCleanupFunction(async () => { + await resetPrefs(); + gBrowser.removeCurrentTab(); + Services.prefs.clearUserPref("network.trr.confirmationNS"); +}); + +async function openConnectionsSubDialog() { + /* + The connection dialog has type="child", So it has to be opened as a sub dialog + of the main pref tab. Prefs only get updated after the subdialog is confirmed & closed + */ + let dialog = await openAndLoadSubDialog(SUBDIALOG_URL); + ok(dialog, "connection window opened"); + return dialog; +} + +function waitForPrefObserver(name) { + return new Promise(resolve => { + const observer = { + observe(aSubject, aTopic, aData) { + if (aData == name) { + Services.prefs.removeObserver(name, observer); + resolve(); + } + }, + }; + Services.prefs.addObserver(name, observer); + }); +} + +async function testWithProperties(props, startTime) { + info( + Date.now() - + startTime + + ": testWithProperties: testing with " + + JSON.stringify(props) + ); + + // There are two different signals that the DoHController is ready, depending + // on the config being tested. If we're setting the TRR mode pref, we should + // expect the disable-heuristics pref to be set as the signal. Else, we can + // expect the self-enabled pref as the signal. + let rolloutReadyPromise; + if (props.hasOwnProperty(TRR_MODE_PREF)) { + if ( + [2, 3, 5].includes(props[TRR_MODE_PREF]) && + props.hasOwnProperty(ROLLOUT_ENABLED_PREF) + ) { + // Only initialize the promise if we're going to enable the rollout - + // otherwise we will never await it, which could cause a leak if it doesn't + // end up resolving. + rolloutReadyPromise = waitForPrefObserver(HEURISTICS_DISABLED_PREF); + } + Services.prefs.setIntPref(TRR_MODE_PREF, props[TRR_MODE_PREF]); + } + if (props.hasOwnProperty(ROLLOUT_ENABLED_PREF)) { + if (!rolloutReadyPromise) { + rolloutReadyPromise = waitForPrefObserver(ROLLOUT_SELF_ENABLED_PREF); + } + Services.prefs.setBoolPref( + ROLLOUT_ENABLED_PREF, + props[ROLLOUT_ENABLED_PREF] + ); + await rolloutReadyPromise; + } + if (props.hasOwnProperty(TRR_CUSTOM_URI_PREF)) { + Services.prefs.setStringPref( + TRR_CUSTOM_URI_PREF, + props[TRR_CUSTOM_URI_PREF] + ); + } + if (props.hasOwnProperty(TRR_URI_PREF)) { + Services.prefs.setStringPref(TRR_URI_PREF, props[TRR_URI_PREF]); + } + + let dialog = await openConnectionsSubDialog(); + await dialog.uiReady; + info( + Date.now() - startTime + ": testWithProperties: connections dialog now open" + ); + let doc = dialog.document; + let win = doc.ownerGlobal; + let dialogElement = doc.getElementById("ConnectionsDialog"); + let dialogClosingPromise = BrowserTestUtils.waitForEvent( + dialogElement, + "dialogclosing" + ); + let modeCheckbox = doc.querySelector(modeCheckboxSelector); + let uriTextbox = doc.querySelector(uriTextboxSelector); + let resolverMenulist = doc.querySelector(resolverMenulistSelector); + let uriPrefChangedPromise; + let modePrefChangedPromise; + let disableHeuristicsPrefChangedPromise; + + if (props.hasOwnProperty("expectedModeChecked")) { + await TestUtils.waitForCondition( + () => modeCheckbox.checked === props.expectedModeChecked + ); + is( + modeCheckbox.checked, + props.expectedModeChecked, + "mode checkbox has expected checked state" + ); + } + if (props.hasOwnProperty("expectedUriValue")) { + await TestUtils.waitForCondition( + () => uriTextbox.value === props.expectedUriValue + ); + is( + uriTextbox.value, + props.expectedUriValue, + "URI textbox has expected value" + ); + } + if (props.hasOwnProperty("expectedResolverListValue")) { + await TestUtils.waitForCondition( + () => resolverMenulist.value === props.expectedResolverListValue + ); + is( + resolverMenulist.value, + props.expectedResolverListValue, + "resolver menulist has expected value" + ); + } + if (props.clickMode) { + info( + Date.now() - + startTime + + ": testWithProperties: clickMode, waiting for the pref observer" + ); + modePrefChangedPromise = waitForPrefObserver(TRR_MODE_PREF); + if (props.hasOwnProperty("expectedDisabledHeuristics")) { + disableHeuristicsPrefChangedPromise = waitForPrefObserver( + HEURISTICS_DISABLED_PREF + ); + } + info( + Date.now() - startTime + ": testWithProperties: clickMode, pref changed" + ); + modeCheckbox.scrollIntoView(); + EventUtils.synthesizeMouseAtCenter(modeCheckbox, {}, win); + info( + Date.now() - + startTime + + ": testWithProperties: clickMode, mouse click synthesized" + ); + } + if (props.hasOwnProperty("selectResolver")) { + info( + Date.now() - + startTime + + ": testWithProperties: selectResolver, creating change event" + ); + resolverMenulist.focus(); + resolverMenulist.value = props.selectResolver; + resolverMenulist.dispatchEvent(new Event("input", { bubbles: true })); + resolverMenulist.dispatchEvent(new Event("change", { bubbles: true })); + info( + Date.now() - + startTime + + ": testWithProperties: selectResolver, item value set and events dispatched" + ); + } + + if (props.hasOwnProperty("inputUriKeys")) { + info( + Date.now() - + startTime + + ": testWithProperties: inputUriKeys, waiting for the pref observer" + ); + uriPrefChangedPromise = waitForPrefObserver(TRR_CUSTOM_URI_PREF); + info( + Date.now() - + startTime + + ": testWithProperties: inputUriKeys, pref changed, now enter the new value" + ); + uriTextbox.focus(); + uriTextbox.value = props.inputUriKeys; + uriTextbox.dispatchEvent(new win.Event("input", { bubbles: true })); + uriTextbox.dispatchEvent(new win.Event("change", { bubbles: true })); + info( + Date.now() - + startTime + + ": testWithProperties: inputUriKeys, input and change events dispatched" + ); + } + + info(Date.now() - startTime + ": testWithProperties: calling acceptDialog"); + dialogElement.acceptDialog(); + + info( + Date.now() - + startTime + + ": testWithProperties: waiting for the dialogClosingPromise" + ); + let dialogClosingEvent = await dialogClosingPromise; + ok(dialogClosingEvent, "connection window closed"); + + info( + Date.now() - + startTime + + ": testWithProperties: waiting for any of uri and mode prefs to change" + ); + await Promise.all([ + uriPrefChangedPromise, + modePrefChangedPromise, + disableHeuristicsPrefChangedPromise, + ]); + info(Date.now() - startTime + ": testWithProperties: prefs changed"); + + if (props.hasOwnProperty("expectedFinalUriPref")) { + if (props.expectedFinalUriPref) { + let uriPref = Services.prefs.getStringPref(TRR_URI_PREF); + is( + uriPref, + props.expectedFinalUriPref, + "uri pref ended up with the expected value" + ); + } else { + ok( + !Services.prefs.prefHasUserValue(TRR_URI_PREF), + "uri pref ended up with the expected value (unset)" + ); + } + } + + if (props.hasOwnProperty("expectedModePref")) { + let modePref = Services.prefs.getIntPref(TRR_MODE_PREF); + is( + modePref, + props.expectedModePref, + "mode pref ended up with the expected value" + ); + } + + if (props.hasOwnProperty("expectedDisabledHeuristics")) { + let disabledHeuristicsPref = Services.prefs.getBoolPref( + HEURISTICS_DISABLED_PREF + ); + is( + disabledHeuristicsPref, + props.expectedDisabledHeuristics, + "disable-heuristics pref ended up with the expected value" + ); + } + + if (props.hasOwnProperty("expectedFinalCusomUriPref")) { + let customUriPref = Services.prefs.getStringPref(TRR_CUSTOM_URI_PREF); + is( + customUriPref, + props.expectedFinalCustomUriPref, + "custom_uri pref ended up with the expected value" + ); + } + + info(Date.now() - startTime + ": testWithProperties: fin"); +} + +add_task(async function default_values() { + let customUriPref = Services.prefs.getStringPref(TRR_CUSTOM_URI_PREF); + let uriPrefHasUserValue = Services.prefs.prefHasUserValue(TRR_URI_PREF); + let modePref = Services.prefs.getIntPref(TRR_MODE_PREF); + is( + modePref, + defaultPrefValues[TRR_MODE_PREF], + `Actual value of ${TRR_MODE_PREF} matches expected default value` + ); + ok( + !uriPrefHasUserValue, + `Actual value of ${TRR_URI_PREF} matches expected default value (unset)` + ); + is( + customUriPref, + defaultPrefValues[TRR_CUSTOM_URI_PREF], + `Actual value of ${TRR_CUSTOM_URI_PREF} matches expected default value` + ); +}); + +let testVariations = [ + // verify state with defaults + { name: "default", expectedModePref: 5, expectedUriValue: "" }, + + // verify each of the modes maps to the correct checked state + { name: "mode 0", [TRR_MODE_PREF]: 0, expectedModeChecked: false }, + { + name: "mode 1", + [TRR_MODE_PREF]: 1, + expectedModeChecked: false, + }, + { + name: "mode 2", + [TRR_MODE_PREF]: 2, + expectedModeChecked: true, + expectedFinalUriPref: DEFAULT_RESOLVER_VALUE, + }, + { + name: "mode 3", + [TRR_MODE_PREF]: 3, + expectedModeChecked: true, + expectedFinalUriPref: DEFAULT_RESOLVER_VALUE, + }, + { + name: "mode 4", + [TRR_MODE_PREF]: 4, + expectedModeChecked: false, + }, + { name: "mode 5", [TRR_MODE_PREF]: 5, expectedModeChecked: false }, + // verify an out of bounds mode value maps to the correct checked state + { + name: "mode out-of-bounds", + [TRR_MODE_PREF]: 77, + expectedModeChecked: false, + }, + + // verify automatic heuristics states + { + name: "heuristics on and mode unset", + [TRR_MODE_PREF]: 0, + [ROLLOUT_ENABLED_PREF]: true, + expectedModeChecked: true, + }, + { + name: "heuristics on and mode set to 2", + [TRR_MODE_PREF]: 2, + [ROLLOUT_ENABLED_PREF]: true, + expectedModeChecked: true, + }, + { + name: "heuristics on but disabled, mode unset", + [TRR_MODE_PREF]: 5, + [ROLLOUT_ENABLED_PREF]: true, + expectedModeChecked: false, + }, + { + name: "heuristics on but disabled, mode set to 2", + [TRR_MODE_PREF]: 2, + [ROLLOUT_ENABLED_PREF]: true, + expectedModeChecked: true, + }, + + // verify toggling the checkbox gives the right outcomes + { + name: "toggle mode on", + clickMode: true, + expectedModeValue: 2, + expectedUriValue: "", + expectedFinalUriPref: DEFAULT_RESOLVER_VALUE, + }, + { + name: "toggle mode off", + [TRR_MODE_PREF]: 2, + expectedModeChecked: true, + clickMode: true, + expectedModePref: 5, + }, + { + name: "toggle mode off when on due to heuristics", + [TRR_MODE_PREF]: 0, + [ROLLOUT_ENABLED_PREF]: true, + expectedModeChecked: true, + clickMode: true, + expectedModePref: 5, + expectedDisabledHeuristics: true, + }, + // Test selecting non-default, non-custom TRR provider, NextDNS. + { + name: "Select NextDNS as TRR provider", + [TRR_MODE_PREF]: 2, + selectResolver: SECOND_RESOLVER_VALUE, + expectedFinalUriPref: SECOND_RESOLVER_VALUE, + }, + // Test selecting non-default, non-custom TRR provider, NextDNS, + // with DoH not enabled. The provider selection should stick. + { + name: "Select NextDNS as TRR provider in mode 0", + [TRR_MODE_PREF]: 0, + selectResolver: SECOND_RESOLVER_VALUE, + expectedFinalUriPref: SECOND_RESOLVER_VALUE, + }, + { + name: "return to default from NextDNS", + [TRR_MODE_PREF]: 2, + [TRR_URI_PREF]: SECOND_RESOLVER_VALUE, + expectedResolverListValue: SECOND_RESOLVER_VALUE, + selectResolver: DEFAULT_RESOLVER_VALUE, + expectedFinalUriPref: DEFAULT_RESOLVER_VALUE, + }, + // test that selecting Custom, when we have a TRR_CUSTOM_URI_PREF subsequently changes TRR_URI_PREF + { + name: "select custom with existing custom_uri pref value", + [TRR_MODE_PREF]: 2, + [TRR_CUSTOM_URI_PREF]: "https://example.com", + expectedModeValue: true, + selectResolver: "custom", + expectedUriValue: "https://example.com", + expectedFinalUriPref: "https://example.com", + expectedFinalCustomUriPref: "https://example.com", + }, + { + name: "select custom and enter new custom_uri pref value", + [TRR_URI_PREF]: "", + [TRR_CUSTOM_URI_PREF]: "", + clickMode: true, + selectResolver: "custom", + inputUriKeys: "https://example.com", + expectedModePref: 2, + expectedFinalUriPref: "https://example.com", + expectedFinalCustomUriPref: "https://example.com", + }, + + { + name: "return to default from custom", + [TRR_MODE_PREF]: 2, + [TRR_URI_PREF]: "https://example.com", + [TRR_CUSTOM_URI_PREF]: "https://example.com", + expectedUriValue: "https://example.com", + expectedResolverListValue: "custom", + selectResolver: DEFAULT_RESOLVER_VALUE, + expectedFinalUriPref: DEFAULT_RESOLVER_VALUE, + expectedFinalCustomUriPref: "https://example.com", + }, + { + name: "clear the custom uri", + [TRR_MODE_PREF]: 2, + [TRR_URI_PREF]: "https://example.com", + [TRR_CUSTOM_URI_PREF]: "https://example.com", + expectedUriValue: "https://example.com", + expectedResolverListValue: "custom", + inputUriKeys: "", + expectedFinalUriPref: DEFAULT_RESOLVER_VALUE, + expectedFinalCustomUriPref: "", + }, + { + name: "empty default resolver list", + [TRR_MODE_PREF]: 2, + [TRR_URI_PREF]: "https://example.com", + [TRR_CUSTOM_URI_PREF]: "", + expectedUriValue: "https://example.com", + expectedResolverListValue: "custom", + expectedFinalUriPref: "https://example.com", + expectedFinalCustomUriPref: "https://example.com", + }, +]; + +for (let props of testVariations) { + add_task(async function testVariation() { + await preferencesOpen; + let startTime = Date.now(); + info("starting test: " + props.name); + await testWithProperties(props, startTime); + await resetPrefs(); + }); +} + +add_task(async function testRemoteSettingsEnable() { + // Enable the rollout. + await DoHTestUtils.loadRemoteSettingsConfig({ + providers: "example-1, example-2", + rolloutEnabled: true, + steeringEnabled: false, + steeringProviders: "", + autoDefaultEnabled: false, + autoDefaultProviders: "", + id: "global", + }); + + let doTest = async (cancelOrAccept = "cancel") => { + let dialog = await openConnectionsSubDialog(); + await dialog.uiReady; + let doc = dialog.document; + let dialogElement = doc.getElementById("ConnectionsDialog"); + let modeCheckbox = doc.querySelector(modeCheckboxSelector); + ok(modeCheckbox.checked, "The mode checkbox should be checked."); + let dialogClosingPromise = BrowserTestUtils.waitForEvent( + dialogElement, + "dialogclosing" + ); + if (cancelOrAccept == "cancel") { + dialogElement.cancelDialog(); + } else { + dialogElement.acceptDialog(); + } + await dialogClosingPromise; + if (cancelOrAccept == "cancel") { + try { + await TestUtils.waitForCondition(() => + Services.prefs.prefHasUserValue("doh-rollout.disable-heuristics") + ); + ok(false, "Heuristics were disabled when they shouldn't have been!"); + } catch (e) { + ok(true, "Heuristics remained enabled."); + } + is(Services.prefs.getStringPref("network.trr.uri"), ""); + ok(!Services.prefs.prefHasUserValue("network.trr.mode")); + } else { + // If accepting, the chosen provider is persisted to network.trr.uri + // and heuristics should get disabled. + await TestUtils.waitForCondition(() => + Services.prefs.prefHasUserValue("doh-rollout.disable-heuristics") + ); + ok( + Services.prefs.getBoolPref("doh-rollout.disable-heuristics"), + "Heurstics were disabled." + ); + is( + Services.prefs.getStringPref("network.trr.uri"), + DEFAULT_RESOLVER_VALUE + ); + is(Services.prefs.getIntPref("network.trr.mode"), 2); + } + }; + + for (let action of ["cancel", "accept"]) { + await doTest(action); + } +}); + +add_task(async function testEnterprisePolicy() { + async function closeDialog(dialog) { + let dialogClosingPromise = BrowserTestUtils.waitForEvent( + dialog, + "dialogclosing" + ); + + dialog.cancelDialog(); + await dialogClosingPromise; + } + + async function withPolicy(policy, fn, preFn = () => {}) { + await resetPrefs(); + PoliciesPrefTracker.start(); + await EnterprisePolicyTesting.setupPolicyEngineWithJson(policy); + + await preFn(); + + let dialog = await openConnectionsSubDialog(); + await dialog.uiReady; + + let doc = dialog.document; + + let dialogElement = doc.getElementById("ConnectionsDialog"); + let modeCheckbox = doc.querySelector(modeCheckboxSelector); + let resolverMenulist = doc.querySelector(resolverMenulistSelector); + let uriTextbox = doc.querySelector(uriTextboxSelector); + + await fn({ + dialog, + dialogElement, + modeCheckbox, + resolverMenulist, + doc, + uriTextbox, + }); + + await closeDialog(dialogElement); + EnterprisePolicyTesting.resetRunOnceState(); + PoliciesPrefTracker.stop(); + } + + info("Check that a locked policy does not allow any changes in the UI"); + await withPolicy( + { + policies: { + DNSOverHTTPS: { + Enabled: true, + ProviderURL: "https://examplelocked.com/provider", + ExcludedDomains: ["examplelocked.com", "example.org"], + Locked: true, + }, + }, + }, + async res => { + ok(res.modeCheckbox.checked, "The mode checkbox should be checked."); + is(res.modeCheckbox.disabled, true, "The checkbox should be locked."); + + is(res.resolverMenulist.value, "custom", "Resolver list shows custom"); + is( + res.resolverMenulist.disabled, + true, + "The resolver list should be locked." + ); + + is(res.uriTextbox.disabled, true, "The custom URI should be locked."); + } + ); + + info("Check that an unlocked policy has editable fields in the dialog"); + await withPolicy( + { + policies: { + DNSOverHTTPS: { + Enabled: true, + ProviderURL: "https://example.com/provider", + ExcludedDomains: ["example.com", "example.org"], + }, + }, + }, + async res => { + ok(res.modeCheckbox.checked, "The mode checkbox should be checked."); + is( + res.modeCheckbox.disabled, + false, + "The checkbox should not be locked." + ); + + is(res.resolverMenulist.value, "custom", "Resolver list shows custom"); + is( + res.resolverMenulist.disabled, + false, + "The resolver list should not be locked." + ); + + is( + res.uriTextbox.value, + "https://example.com/provider", + "Expected custom resolver" + ); + is( + res.uriTextbox.disabled, + false, + "The custom URI should not be locked." + ); + } + ); + + info("Check that a locked disabled policy disables the buttons"); + await withPolicy( + { + policies: { + DNSOverHTTPS: { + Enabled: false, + ProviderURL: "https://example.com/provider", + ExcludedDomains: ["example.com", "example.org"], + Locked: true, + }, + }, + }, + async res => { + ok(!res.modeCheckbox.checked, "The mode checkbox should be unchecked."); + is(res.modeCheckbox.disabled, true, "The checkbox should be locked."); + + is(res.resolverMenulist.value, "custom", "Resolver list shows custom"); + is( + res.resolverMenulist.disabled, + true, + "The resolver list should be locked." + ); + + is(res.uriTextbox.disabled, true, "The custom URI should be locked."); + } + ); + + info("Check that an unlocked disabled policy has editable fields"); + await withPolicy( + { + policies: { + DNSOverHTTPS: { + Enabled: false, + ProviderURL: "https://example.com/provider", + ExcludedDomains: ["example.com", "example.org"], + }, + }, + }, + async res => { + ok(!res.modeCheckbox.checked, "The mode checkbox should be unchecked."); + is( + res.modeCheckbox.disabled, + false, + "The checkbox should not be locked." + ); + + is(res.resolverMenulist.value, "custom", "Resolver list shows custom"); + is( + res.resolverMenulist.disabled, + true, + "The resolver list should be locked." + ); + + is(res.uriTextbox.disabled, true, "The custom URI should be locked."); + } + ); + + info("Check that the remote settings config doesn't override the policy"); + await withPolicy( + { + policies: { + DNSOverHTTPS: { + Enabled: true, + ProviderURL: "https://example.com/provider", + ExcludedDomains: ["example.com", "example.org"], + }, + }, + }, + async res => { + ok(res.modeCheckbox.checked, "The mode checkbox should be checked."); + is( + res.modeCheckbox.disabled, + false, + "The checkbox should not be locked." + ); + + is(res.resolverMenulist.value, "custom", "Resolver list shows custom"); + is( + res.resolverMenulist.disabled, + false, + "The resolver list should not be locked." + ); + + is( + res.uriTextbox.value, + "https://example.com/provider", + "Expected custom resolver" + ); + is( + res.uriTextbox.disabled, + false, + "The custom URI should not be locked." + ); + }, + async function runAfterSettingPolicy() { + await DoHTestUtils.loadRemoteSettingsConfig({ + providers: "example-1, example-2", + rolloutEnabled: true, + steeringEnabled: false, + steeringProviders: "", + autoDefaultEnabled: false, + autoDefaultProviders: "", + id: "global", + }); + } + ); +}); |