Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/browser/components/migration/tests/browser/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 18 kB image not shown  

Quelle  head.js   Sprache: JAVA

 
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */


"use strict";

/* import-globals-from ../head-common.js */

Services.scriptloader.loadSubScript(
  "chrome://mochitests/content/browser/browser/components/migration/tests/browser/head-common.js",
  this
);

const { sinon } = ChromeUtils.importESModule(
  "resource://testing-common/Sinon.sys.mjs"
);
const { InternalTestingProfileMigrator } = ChromeUtils.importESModule(
  "resource:///modules/InternalTestingProfileMigrator.sys.mjs"
);
const { TelemetryTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/TelemetryTestUtils.sys.mjs"
);

const DIALOG_URL =
  "chrome://browser/content/migration/migration-dialog-window.html";

/**
 * We'll have this be our magic number of quantities of various imports.
 * We will use Sinon to prepare MigrationUtils to presume that this was
 * how many of each quantity-supported resource type was imported.
 */

const EXPECTED_QUANTITY = 123;

/**
 * These are the resource types that currently display their import success
 * message with a quantity.
 */

const RESOURCE_TYPES_WITH_QUANTITIES = [
  MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.BOOKMARKS,
  MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.HISTORY,
  MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.PASSWORDS,
  MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.FORMDATA,
  MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.PAYMENT_METHODS,
  MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.EXTENSIONS,
];

/**
 * The withMigrationWizardDialog callback, called after the
 * dialog has loaded and the wizard is ready.
 *
 * @callback withMigrationWizardDialogCallback
 * @param {DOMWindow} window
 *   The content window of the migration wizard subdialog frame.
 * @returns {Promise<undefined>}
 */


/**
 * Opens the migration wizard HTML5 dialog in about:preferences in the
 * current window's selected tab, runs an async taskFn, and then
 * cleans up by loading about:blank in the tab before resolving.
 *
 * @param {withMigrationWizardDialogCallback} taskFn
 *   An async test function to be called while the migration wizard
 *   dialog is open.
 * @returns {Promise<undefined>}
 */

async function withMigrationWizardDialog(taskFn) {
  let migrationDialogPromise = waitForMigrationWizardDialogTab();
  await MigrationUtils.showMigrationWizard(window, {});
  let prefsBrowser = await migrationDialogPromise;

  try {
    await taskFn(prefsBrowser.contentWindow);
  } finally {
    if (gBrowser.tabs.length > 1) {
      BrowserTestUtils.removeTab(gBrowser.getTabForBrowser(prefsBrowser));
    } else {
      BrowserTestUtils.startLoadingURIString(prefsBrowser, "about:blank");
      await BrowserTestUtils.browserLoaded(prefsBrowser);
    }
  }
}

/**
 * Returns a Promise that resolves when an about:preferences tab opens
 * in the current window which loads the migration wizard dialog.
 * The Promise will wait until the migration wizard reports that it
 * is ready with the "MigrationWizard:Ready" event.
 *
 * @returns {Promise<browser>}
 *   Resolves with the about:preferences browser element.
 */

async function waitForMigrationWizardDialogTab() {
  let wizardReady = BrowserTestUtils.waitForEvent(
    window,
    "MigrationWizard:Ready"
  );

  let tab;
  if (gBrowser.selectedTab.isEmpty) {
    tab = gBrowser.selectedTab;
    await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, url => {
      return url.startsWith("about:preferences");
    });
  } else {
    tab = await BrowserTestUtils.waitForNewTab(gBrowser, url => {
      return url.startsWith("about:preferences");
    });
  }

  await wizardReady;
  info("Done waiting - migration subdialog loaded and ready.");

  return tab.linkedBrowser;
}

/**
 * A helper function that prepares the InternalTestingProfileMigrator
 * with some set of fake available resources, and resolves a Promise
 * when the InternalTestingProfileMigrator is used for a migration.
 *
 * @param {number[]} availableResourceTypes
 *   An array of resource types from MigrationUtils.resourcesTypes.
 *   A single MigrationResource will be created per type, with a
 *   no-op migrate function.
 * @param {number[]} expectedResourceTypes
 *   An array of resource types from MigrationUtils.resourceTypes.
 *   These are the resource types that are expected to be passed
 *   to the InternalTestingProfileMigrator.migrate function.
 * @param {object|string} expectedProfile
 *   The profile object or string that is expected to be passed
 *   to the InternalTestingProfileMigrator.migrate function.
 * @param {number[]} [errorResourceTypes=[]]
 *   Resource types that we should pretend have failed to complete
 *   their migration properly.
 * @param {number} [totalExtensions=1]
 *   If migrating extensions, the total that should be reported to
 *   have been found from the source browser.
 * @param {number} [matchedExtensions=1]
 *   If migrating extensions, the number of extensions that should
 *   be reported as having equivalent matches for this browser.
 * @returns {Promise<undefined>}
 */

async function waitForTestMigration(
  availableResourceTypes,
  expectedResourceTypes,
  expectedProfile,
  errorResourceTypes = [],
  totalExtensions = 1,
  matchedExtensions = 1
) {
  let sandbox = sinon.createSandbox();
  let sourceHistogram = TelemetryTestUtils.getAndClearHistogram(
    "FX_MIGRATION_SOURCE_BROWSER"
  );
  let usageHistogram =
    TelemetryTestUtils.getAndClearKeyedHistogram("FX_MIGRATION_USAGE");
  let errorHistogram = TelemetryTestUtils.getAndClearKeyedHistogram(
    "FX_MIGRATION_ERRORS"
  );

  // Fake out the getResources method of the migrator so that we return
  // a single fake MigratorResource per availableResourceType.
  sandbox
    .stub(InternalTestingProfileMigrator.prototype, "getResources")
    .callsFake(aProfile => {
      Assert.deepEqual(
        aProfile,
        expectedProfile,
        "Should have gotten the expected profile."
      );
      return Promise.resolve(
        availableResourceTypes.map(resourceType => {
          return {
            type: resourceType,
            migrate: () => {},
          };
        })
      );
    });

  sandbox.stub(MigrationUtils, "_importQuantities").value({
    bookmarks: EXPECTED_QUANTITY,
    history: EXPECTED_QUANTITY,
    logins: EXPECTED_QUANTITY,
    cards: EXPECTED_QUANTITY,
  });

  sandbox
    .stub(MigrationUtils, "getSourceIdForTelemetry")
    .withArgs(InternalTestingProfileMigrator.key)
    .returns(InternalTestingProfileMigrator.sourceID);

  // Fake out the migrate method of the migrator and assert that the
  // next time it's called, its arguments match our expectations.
  return new Promise(resolve => {
    sandbox
      .stub(InternalTestingProfileMigrator.prototype, "migrate")
      .callsFake((aResourceTypes, aStartup, aProfile, aProgressCallback) => {
        Assert.ok(
          !aStartup,
          "Migrator should not have been called as a startup migration."
        );

        let bitMask = 0;
        for (let resourceType of expectedResourceTypes) {
          bitMask |= resourceType;
        }

        Assert.deepEqual(
          aResourceTypes,
          bitMask,
          "Got the expected resource types"
        );
        Assert.deepEqual(
          aProfile,
          expectedProfile,
          "Got the expected profile object"
        );

        for (let resourceType of expectedResourceTypes) {
          let shouldError = errorResourceTypes.includes(resourceType);
          if (
            resourceType == MigrationUtils.resourceTypes.EXTENSIONS &&
            !shouldError
          ) {
            let progressValue;
            if (totalExtensions == matchedExtensions) {
              progressValue = MigrationWizardConstants.PROGRESS_VALUE.SUCCESS;
            } else if (
              totalExtensions > matchedExtensions &&
              matchedExtensions
            ) {
              progressValue = MigrationWizardConstants.PROGRESS_VALUE.INFO;
            } else {
              Assert.ok(
                false,
                "Total and matched extensions should be greater than 0 on success." +
                  `Total: ${totalExtensions}, Matched: ${matchedExtensions}`
              );
            }
            aProgressCallback(resourceType, !shouldError, {
              totalExtensions: Array(totalExtensions),
              importedExtensions: Array(matchedExtensions),
              progressValue,
            });
          } else {
            aProgressCallback(resourceType, !shouldError);
          }
        }

        let usageHistogramSnapshot =
          usageHistogram.snapshot()[InternalTestingProfileMigrator.key];

        let errorHistogramSnapshot =
          errorHistogram.snapshot()[InternalTestingProfileMigrator.key];

        for (let resourceTypeName in MigrationUtils.resourceTypes) {
          let resourceType = MigrationUtils.resourceTypes[resourceTypeName];
          if (resourceType == MigrationUtils.resourceTypes.ALL) {
            continue;
          }

          if (expectedResourceTypes.includes(resourceType)) {
            Assert.equal(
              usageHistogramSnapshot.values[Math.log2(resourceType)],
              1,
              `Should have set resource type ${resourceTypeName} on the FX_MIGRATION_USAGE keyed histogram.`
            );

            if (errorResourceTypes.includes(resourceType)) {
              Assert.equal(
                errorHistogramSnapshot.values[Math.log2(resourceType)],
                1,
                `Should have set resource type ${resourceTypeName} on the FX_MIGRATION_ERRORS keyed histogram.`
              );
            }
          } else {
            let value = usageHistogramSnapshot.values[Math.log2(resourceType)];
            Assert.ok(
              value === 0 || value === undefined,
              `Should not have set resource type ${resourceTypeName} on the FX_MIGRATION_USAGE keyed histogram.`
            );
          }
        }

        Services.obs.notifyObservers(null"Migration:Ended");

        TelemetryTestUtils.assertHistogram(
          sourceHistogram,
          InternalTestingProfileMigrator.sourceID,
          1
        );

        resolve();
      });
  }).finally(async () => {
    sandbox.restore();

    // MigratorBase caches resources fetched by the getResources method
    // as a performance optimization. In order to allow different tests
    // to have different available resources, we call into a special
    // method of InternalTestingProfileMigrator that clears that
    // cache.
    let migrator = await MigrationUtils.getMigrator(
      InternalTestingProfileMigrator.key
    );
    migrator.flushResourceCache();
  });
}

/**
 * Takes a MigrationWizard element and chooses the
 * InternalTestingProfileMigrator as the browser to migrate from. Then, it
 * checks the checkboxes associated with the selectedResourceTypes and
 * unchecks the rest before clicking the "Import" button.
 *
 * @param {Element} wizard
 *   The MigrationWizard element.
 * @param {string[]} selectedResourceTypes
 *   An array of resource type strings from
 *   MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.
 * @param {string} [migratorKey=InternalTestingProfileMigrator.key]
 *   The key for the migrator to use. Defaults to the
 *   InternalTestingProfileMigrator.
 */

async function selectResourceTypesAndStartMigration(
  wizard,
  selectedResourceTypes,
  migratorKey = InternalTestingProfileMigrator.key
) {
  let shadow = wizard.openOrClosedShadowRoot;

  // First, select the InternalTestingProfileMigrator browser.
  let selector = shadow.querySelector("#browser-profile-selector");
  EventUtils.synthesizeMouseAtCenter(selector, {}, wizard.ownerGlobal);

  await new Promise(resolve => {
    shadow
      .querySelector("panel-list")
      .addEventListener("shown", resolve, { once: true });
  });

  let panelItem = shadow.querySelector(`panel-item[key="${migratorKey}"]`);
  panelItem.click();

  // And then check the right checkboxes for the resource types.
  let resourceTypeList = shadow.querySelector("#resource-type-list");
  for (let resourceType of getChoosableResourceTypes()) {
    let node = resourceTypeList.querySelector(
      `label[data-resource-type="${resourceType}"]`
    );
    node.control.checked = selectedResourceTypes.includes(resourceType);
  }

  let importButton = shadow.querySelector("#import");
  importButton.click();
}

/**
 * Assert that the resource types passed in expectedResourceTypes are
 * showing a success state after a migration, and if they are part of
 * the RESOURCE_TYPES_WITH_QUANTITIES group, that they're showing the
 * EXPECTED_QUANTITY magic number in their success message. Otherwise,
 * we (currently) check that they show the empty string.
 *
 * @param {Element} wizard
 *   The MigrationWizard element.
 * @param {string[]} expectedResourceTypes
 *   An array of resource type strings from
 *   MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.
 * @param {string[]} [warningResourceTypes=[]]
 *   An array of resource type strings from
 *   MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES. These
 *   are the resources that should be showing a warning message.
 */

function assertQuantitiesShown(
  wizard,
  expectedResourceTypes,
  warningResourceTypes = []
) {
  let shadow = wizard.openOrClosedShadowRoot;

  // Make sure that we're showing the progress page first.
  let deck = shadow.querySelector("#wizard-deck");
  Assert.equal(
    deck.selectedViewName,
    `page-${MigrationWizardConstants.PAGES.PROGRESS}`
  );

  let headerL10nID = shadow.querySelector("#progress-header").dataset.l10nId;
  if (warningResourceTypes.length) {
    Assert.equal(
      headerL10nID,
      "migration-wizard-progress-done-with-warnings-header"
    );
  } else {
    Assert.equal(headerL10nID, "migration-wizard-progress-done-header");
  }

  // Go through each displayed resource and make sure that only the
  // ones that are expected are shown, and are showing the right
  // success message.

  let progressGroups = shadow.querySelectorAll(".resource-progress-group");
  for (let progressGroup of progressGroups) {
    if (expectedResourceTypes.includes(progressGroup.dataset.resourceType)) {
      let progressIcon = progressGroup.querySelector(".progress-icon");
      let messageText =
        progressGroup.querySelector(".message-text").textContent;

      if (warningResourceTypes.includes(progressGroup.dataset.resourceType)) {
        Assert.equal(
          progressIcon.getAttribute("state"),
          "warning",
          "Should be showing the warning icon state."
        );
      } else {
        Assert.equal(
          progressIcon.getAttribute("state"),
          "success",
          "Should be showing the success icon state."
        );
      }

      if (
        RESOURCE_TYPES_WITH_QUANTITIES.includes(
          progressGroup.dataset.resourceType
        )
      ) {
        if (
          progressGroup.dataset.resourceType ==
          MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.HISTORY
        ) {
          // HISTORY is a special case that doesn't show the number of imported
          // history entries, but instead shows the maximum number of days of history
          // that might have been imported.
          Assert.notEqual(
            messageText.indexOf(MigrationUtils.HISTORY_MAX_AGE_IN_DAYS),
            -1,
            `Found expected maximum number of days of history: ${messageText}`
          );
        } else if (
          progressGroup.dataset.resourceType ==
          MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.FORMDATA
        ) {
          // FORMDATA is another special case, because we simply show "Form history" as
          // the message string, rather than a particular quantity.
          Assert.equal(
            messageText,
            "Form history",
            `Found expected form data string: ${messageText}`
          );
        } else if (
          progressGroup.dataset.resourceType ==
          MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.EXTENSIONS
        ) {
          // waitForTestMigration by default sets up a "successful" migration of 1
          // extension.
          Assert.stringMatches(messageText, "1 extension");
        } else {
          Assert.notEqual(
            messageText.indexOf(EXPECTED_QUANTITY),
            -1,
            `Found expected quantity in message string: ${messageText}`
          );
        }
      } else {
        // If you've found yourself here, and this is failing, it's probably because you've
        // updated MigrationWizardParent.#getStringForImportQuantity to return a string for
        // a resource type that's not in RESOURCE_TYPES_WITH_QUANTITIES, and you'll need
        // to modify this function to check for that string.
        Assert.equal(
          messageText,
          "",
          "Expected the empty string if the resource type " +
            "isn't in RESOURCE_TYPES_WITH_QUANTITIES"
        );
      }
    } else {
      Assert.ok(
        BrowserTestUtils.isHidden(progressGroup),
        `Resource progress group for ${progressGroup.dataset.resourceType}` +
          ` should be hidden.`
      );
    }
  }
}

/**
 * Translates an entrypoint string into the proper numeric value for the
 * FX_MIGRATION_ENTRY_POINT_CATEGORICAL histogram.
 *
 * @param {string} entrypoint
 *   The entrypoint to translate from MIGRATION_ENTRYPOINTS.
 * @returns {number}
 *   The numeric index value for the FX_MIGRATION_ENTRY_POINT_CATEGORICAL
 *   histogram.
 */

function getEntrypointHistogramIndex(entrypoint) {
  switch (entrypoint) {
    case MigrationUtils.MIGRATION_ENTRYPOINTS.FIRSTRUN: {
      return 1;
    }
    case MigrationUtils.MIGRATION_ENTRYPOINTS.FXREFRESH: {
      return 2;
    }
    case MigrationUtils.MIGRATION_ENTRYPOINTS.PLACES: {
      return 3;
    }
    case MigrationUtils.MIGRATION_ENTRYPOINTS.PASSWORDS: {
      return 4;
    }
    case MigrationUtils.MIGRATION_ENTRYPOINTS.NEWTAB: {
      return 5;
    }
    case MigrationUtils.MIGRATION_ENTRYPOINTS.FILE_MENU: {
      return 6;
    }
    case MigrationUtils.MIGRATION_ENTRYPOINTS.HELP_MENU: {
      return 7;
    }
    case MigrationUtils.MIGRATION_ENTRYPOINTS.BOOKMARKS_TOOLBAR: {
      return 8;
    }
    case MigrationUtils.MIGRATION_ENTRYPOINTS.PREFERENCES: {
      return 9;
    }
    case MigrationUtils.MIGRATION_ENTRYPOINTS.UNKNOWN:
    // Intentional fall-through
    default: {
      return 0; // Unknown
    }
  }
}

Messung V0.5
C=92 H=89 G=90

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.