Commit bcf837f8 authored by Daisuke Akatsuka's avatar Daisuke Akatsuka
Browse files

Bug 1833975: Introduce MockRemoteSettings to sync RemoteSettings data r=adw

parent 73aa7c69
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -87,6 +87,14 @@ class _QuickSuggestRemoteSettings {
    return this.#config;
  }

  /**
   * @returns {Array}
   *   Array of `BasicFeature` instances.
   */
  get features() {
    return [...this.#features];
  }

  get logger() {
    if (!this.#logger) {
      this.#logger = lazy.UrlbarUtils.getLogger({
+23 −18
Original line number Diff line number Diff line
@@ -92,6 +92,9 @@ async function ensureQuickSuggestInit({
    config,
    merinoSuggestions,
    remoteSettingsResults: [
      {
        type: "data",
        attachment: [
          {
            id: 1,
            url: "https://example.com/sponsored",
@@ -113,6 +116,8 @@ async function ensureQuickSuggestInit({
            iab_category: "5 - Education",
          },
        ],
      },
    ],
  });
}

+90 −15
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
  QuickSuggest: "resource:///modules/QuickSuggest.sys.mjs",
  QuickSuggestRemoteSettings:
    "resource:///modules/urlbar/private/QuickSuggestRemoteSettings.sys.mjs",
  RemoteSettings: "resource://services-settings/remote-settings.sys.mjs",
  SearchUtils: "resource://gre/modules/SearchUtils.sys.mjs",
  TelemetryTestUtils: "resource://testing-common/TelemetryTestUtils.sys.mjs",
  TestUtils: "resource://testing-common/TestUtils.sys.mjs",
@@ -130,6 +131,85 @@ const TEST_SCOPE_PROPERTIES = [
  "registerCleanupFunction",
];

/**
 * Mock RemoteSettings.
 *
 * @param {object} options
 *   Options object
 * @param {object} options.config
 *   Dummy config in the RemoteSettings.
 * @param {Array} options.data
 *   Dummy data in the RemoteSettings.
 */
class MockRemoteSettings {
  constructor({ config = DEFAULT_CONFIG, data = [] }) {
    this.#config = config;
    this.#data = data;

    // Make a stub for "get" function to return dummy data.
    const rs = lazy.RemoteSettings("quicksuggest");
    this.#sandbox = lazy.sinon.createSandbox();
    this.#sandbox.stub(rs, "get").callsFake(async query => {
      return query.filters.type === "configuration"
        ? [{ configuration: this.#config }]
        : this.#data.filter(r => r.type === query.filters.type);
    });

    // Make a stub for "download" in attachments.
    this.#sandbox.stub(rs.attachments, "download").callsFake(async record => {
      if (!record.attachment) {
        throw new Error("No attachmet in the record");
      }
      const encoder = new TextEncoder();
      return {
        buffer: encoder.encode(JSON.stringify(record.attachment)),
      };
    });
  }

  async sync() {
    if (!lazy.QuickSuggestRemoteSettings.rs) {
      // There are no registered features that use remote settings.
      return;
    }

    // Observe config-set event to recognize that the config is synced.
    const onConfigSync = new Promise(resolve => {
      lazy.QuickSuggestRemoteSettings.emitter.once("config-set", resolve);
    });

    // Make a stub for each feature to recognize that the features are synced.
    const features = lazy.QuickSuggestRemoteSettings.features;
    const onFeatureSyncs = features.map(feature => {
      return new Promise(resolve => {
        const stub = this.#sandbox
          .stub(feature, "onRemoteSettingsSync")
          .callsFake(async (...args) => {
            // Call and wait for the original function.
            await stub.wrappedMethod.apply(feature, args);
            stub.restore();
            resolve();
          });
      });
    });

    // Force to sync.
    const rs = lazy.RemoteSettings("quicksuggest");
    rs.emit("sync");

    // Wait for sync.
    await Promise.all([onConfigSync, ...onFeatureSyncs]);
  }

  cleanup() {
    this.#sandbox.restore();
  }

  #config = null;
  #data = null;
  #sandbox = null;
}

/**
 * Test utils for quick suggest.
 */
@@ -204,25 +284,20 @@ class _QuickSuggestTestUtils {
   *   otherwise.
   */
  async ensureQuickSuggestInit({
    remoteSettingsResults = [],
    remoteSettingsResults,
    merinoSuggestions = null,
    config = DEFAULT_CONFIG,
  } = {}) {
    lazy.QuickSuggestRemoteSettings._test_ignoreSettingsSync = true;
    this.#mockRemoteSettings = new MockRemoteSettings({
      config,
      data: remoteSettingsResults,
    });

    this.info?.("ensureQuickSuggestInit calling QuickSuggest.init()");
    lazy.QuickSuggest.init();

    this.setConfig(config);

    // Clear remote settings suggestions and add the test suggestions.
    let admWikipedia = lazy.QuickSuggest.getFeature("AdmWikipedia");
    admWikipedia._test_suggestionsMap.clear();
    if (remoteSettingsResults) {
      this.info?.("ensureQuickSuggestInit adding remote settings results");
      await admWikipedia._test_suggestionsMap.add(remoteSettingsResults);
      this.info?.("ensureQuickSuggestInit done adding remote settings results");
    }
    // Sync with current data.
    await this.#mockRemoteSettings.sync();

    // Set up Merino.
    if (merinoSuggestions) {
@@ -235,9 +310,7 @@ class _QuickSuggestTestUtils {

    let cleanup = async () => {
      this.info?.("ensureQuickSuggestInit starting cleanup");
      this.setConfig(DEFAULT_CONFIG);
      delete lazy.QuickSuggestRemoteSettings._test_ignoreSettingsSync;
      admWikipedia._test_suggestionsMap.clear();
      this.#mockRemoteSettings.cleanup();
      if (merinoSuggestions) {
        lazy.UrlbarPrefs.clear("quicksuggest.dataCollection.enabled");
      }
@@ -923,6 +996,8 @@ class _QuickSuggestTestUtils {
    Services.locale.requestedLocales = requested;
    await promise;
  }

  #mockRemoteSettings = null;
}

export var QuickSuggestTestUtils = new _QuickSuggestTestUtils();
+6 −1
Original line number Diff line number Diff line
@@ -37,7 +37,12 @@ add_setup(async function () {
  await UrlbarTestUtils.formHistory.clear();

  await QuickSuggestTestUtils.ensureQuickSuggestInit({
    remoteSettingsResults: REMOTE_SETTINGS_RESULTS,
    remoteSettingsResults: [
      {
        type: "data",
        attachment: REMOTE_SETTINGS_RESULTS,
      },
    ],
  });
});

+6 −1
Original line number Diff line number Diff line
@@ -68,7 +68,12 @@ add_setup(async function () {
  Services.telemetry.clearEvents();

  await QuickSuggestTestUtils.ensureQuickSuggestInit({
    remoteSettingsResults: REMOTE_SETTINGS_RESULTS,
    remoteSettingsResults: [
      {
        type: "data",
        attachment: REMOTE_SETTINGS_RESULTS,
      },
    ],
    config: QuickSuggestTestUtils.BEST_MATCH_CONFIG,
  });
});
Loading