summaryrefslogtreecommitdiffstats
path: root/browser/components/translations/tests/browser/head.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/translations/tests/browser/head.js')
-rw-r--r--browser/components/translations/tests/browser/head.js784
1 files changed, 614 insertions, 170 deletions
diff --git a/browser/components/translations/tests/browser/head.js b/browser/components/translations/tests/browser/head.js
index 454de9146b..4bd5dc074f 100644
--- a/browser/components/translations/tests/browser/head.js
+++ b/browser/components/translations/tests/browser/head.js
@@ -297,6 +297,20 @@ class SharedTranslationsTestUtils {
}
/**
+ * Asserts that the given element has the expected L10nId.
+ *
+ * @param {Element} element - The element to assert against.
+ * @param {string} l10nId - The expected localization id.
+ */
+ static _assertL10nId(element, l10nId) {
+ is(
+ element.getAttribute("data-l10n-id"),
+ l10nId,
+ `The element ${element.id} should have L10n Id ${l10nId}.`
+ );
+ }
+
+ /**
* Asserts that the mainViewId of the panel matches the given string.
*
* @param {FullPageTranslationsPanel | SelectTranslationsPanel} panel
@@ -369,6 +383,28 @@ class SharedTranslationsTestUtils {
}
/**
+ * Asserts that the given elements are focusable in order
+ * via the tab key, starting with the first element already
+ * focused and ending back on that same first element.
+ *
+ * @param {Element[]} elements - The focusable elements.
+ */
+ static _assertTabIndexOrder(elements) {
+ const activeElementAtStart = document.activeElement;
+
+ if (elements.length) {
+ elements[0].focus();
+ elements.push(elements[0]);
+ }
+ for (const element of elements) {
+ SharedTranslationsTestUtils._assertHasFocus(element);
+ EventUtils.synthesizeKey("KEY_Tab");
+ }
+
+ activeElementAtStart.focus();
+ }
+
+ /**
* Executes the provided callback before waiting for the event and then waits for the given event
* to be fired for the element corresponding to the provided elementId.
*
@@ -696,11 +732,7 @@ class FullPageTranslationsTestUtils {
*/
static #assertPanelHeaderL10nId(l10nId) {
const { header } = FullPageTranslationsPanel.elements;
- is(
- header.getAttribute("data-l10n-id"),
- l10nId,
- "The translations panel header should match the expected data-l10n-id"
- );
+ SharedTranslationsTestUtils._assertL10nId(header, l10nId);
}
/**
@@ -710,11 +742,7 @@ class FullPageTranslationsTestUtils {
*/
static #assertPanelErrorL10nId(l10nId) {
const { errorMessage } = FullPageTranslationsPanel.elements;
- is(
- errorMessage.getAttribute("data-l10n-id"),
- l10nId,
- "The translations panel error message should match the expected data-l10n-id"
- );
+ SharedTranslationsTestUtils._assertL10nId(errorMessage, l10nId);
}
/**
@@ -1111,7 +1139,7 @@ class FullPageTranslationsTestUtils {
static async #clickSettingsMenuItemByL10nId(l10nId) {
info(`Toggling the "${l10nId}" settings menu item.`);
click(getByL10nId(l10nId), `Clicking the "${l10nId}" settings menu item.`);
- await closeSettingsMenuIfOpen();
+ await closeFullPagePanelSettingsMenuIfOpen();
}
/**
@@ -1363,10 +1391,21 @@ class SelectTranslationsTestUtils {
* @param {Function} runInPage - A content-exposed function to run within the context of the page.
* @param {object} options - Options for how to open the context menu and what properties to assert about the translate-selection item.
*
- * The following options will only work when testing SELECT_TEST_PAGE_URL.
- *
* @param {boolean} options.expectMenuItemVisible - Whether the select-translations menu item should be present in the context menu.
* @param {boolean} options.expectedTargetLanguage - The expected target language to be shown in the context menu.
+ *
+ * The following options will work on all test pages that have an <h1> element.
+ *
+ * @param {boolean} options.selectH1 - Selects the first H1 element of the page.
+ * @param {boolean} options.openAtH1 - Opens the context menu at the first H1 element of the page.
+ *
+ * The following options will work only in the PDF_TEST_PAGE_URL.
+ *
+ * @param {boolean} options.selectPdfSpan - Selects the first span of text on the first page of a pdf.
+ * @param {boolean} options.openAtPdfSpan - Opens the context menu at the first span of text on the first page of a pdf.
+ *
+ * The following options will only work when testing SELECT_TEST_PAGE_URL.
+ *
* @param {boolean} options.selectFrenchSection - Selects the section of French text.
* @param {boolean} options.selectEnglishSection - Selects the section of English text.
* @param {boolean} options.selectSpanishSection - Selects the section of Spanish text.
@@ -1390,12 +1429,16 @@ class SelectTranslationsTestUtils {
{
expectMenuItemVisible,
expectedTargetLanguage,
+ selectH1,
+ selectPdfSpan,
selectFrenchSection,
selectEnglishSection,
selectSpanishSection,
selectFrenchSentence,
selectEnglishSentence,
selectSpanishSentence,
+ openAtH1,
+ openAtPdfSpan,
openAtFrenchSection,
openAtEnglishSection,
openAtSpanishSection,
@@ -1419,12 +1462,16 @@ class SelectTranslationsTestUtils {
await SelectTranslationsTestUtils.openContextMenu(runInPage, {
expectMenuItemVisible,
expectedTargetLanguage,
+ selectH1,
+ selectPdfSpan,
selectFrenchSection,
selectEnglishSection,
selectSpanishSection,
selectFrenchSentence,
selectEnglishSentence,
selectSpanishSentence,
+ openAtH1,
+ openAtPdfSpan,
openAtFrenchSection,
openAtEnglishSection,
openAtSpanishSection,
@@ -1501,21 +1548,6 @@ class SelectTranslationsTestUtils {
}
/**
- * Elements that should always be visible in the SelectTranslationsPanel.
- */
- static #alwaysPresentElements = {
- betaIcon: true,
- copyButton: true,
- doneButton: true,
- fromLabel: true,
- fromMenuList: true,
- header: true,
- toLabel: true,
- toMenuList: true,
- textArea: true,
- };
-
- /**
* Asserts that for each provided expectation, the visible state of the corresponding
* element in FullPageTranslationsPanel.elements both exists and matches the visibility expectation.
*
@@ -1526,7 +1558,31 @@ class SelectTranslationsTestUtils {
SharedTranslationsTestUtils._assertPanelElementVisibility(
SelectTranslationsPanel.elements,
{
- ...SelectTranslationsTestUtils.#alwaysPresentElements,
+ betaIcon: false,
+ cancelButton: false,
+ copyButton: false,
+ doneButtonPrimary: false,
+ doneButtonSecondary: false,
+ fromLabel: false,
+ fromMenuList: false,
+ fromMenuPopup: false,
+ header: false,
+ initFailureContent: false,
+ initFailureMessageBar: false,
+ mainContent: false,
+ settingsButton: false,
+ textArea: false,
+ toLabel: false,
+ toMenuList: false,
+ toMenuPopup: false,
+ translateButton: false,
+ translateFullPageButton: false,
+ translationFailureMessageBar: false,
+ tryAgainButton: false,
+ tryAnotherSourceMenuList: false,
+ tryAnotherSourceMenuPopup: false,
+ unsupportedLanguageContent: false,
+ unsupportedLanguageMessageBar: false,
// Overwrite any of the above defaults with the passed in expectations.
...expectations,
}
@@ -1534,26 +1590,172 @@ class SelectTranslationsTestUtils {
}
/**
+ * Waits for the panel's translation state to reach the given phase,
+ * if it is not currently in that phase already.
+ *
+ * @param {string} phase - The phase of the panel's translation state to wait for.
+ */
+ static async waitForPanelState(phase) {
+ const currentPhase = SelectTranslationsPanel.phase();
+ if (currentPhase !== phase) {
+ info(
+ `Waiting for SelectTranslationsPanel to change state from "${currentPhase}" to "${phase}"`
+ );
+ await BrowserTestUtils.waitForEvent(
+ document,
+ "SelectTranslationsPanelStateChanged",
+ event => event.detail.phase === phase
+ );
+ }
+ }
+
+ /**
* Asserts that the SelectTranslationsPanel UI matches the expected
* state when the panel has completed its translation.
*/
- static assertPanelViewTranslated() {
- const { textArea } = SelectTranslationsPanel.elements;
+ static async assertPanelViewTranslated() {
+ const {
+ copyButton,
+ doneButtonPrimary,
+ fromMenuList,
+ settingsButton,
+ textArea,
+ toMenuList,
+ translateFullPageButton,
+ } = SelectTranslationsPanel.elements;
+ const sameLanguageSelected = fromMenuList.value === toMenuList.value;
+ await SelectTranslationsTestUtils.waitForPanelState("translated");
ok(
!textArea.classList.contains("translating"),
"The textarea should not have the translating class."
);
+ const isFullPageTranslationsRestrictedForPage =
+ TranslationsParent.isFullPageTranslationsRestrictedForPage(gBrowser);
SelectTranslationsTestUtils.#assertPanelElementVisibility({
- ...SelectTranslationsTestUtils.#alwaysPresentElements,
+ betaIcon: true,
+ copyButton: true,
+ doneButtonPrimary: true,
+ fromLabel: true,
+ fromMenuList: true,
+ header: true,
+ mainContent: true,
+ settingsButton: true,
+ textArea: true,
+ toLabel: true,
+ toMenuList: true,
+ translateFullPageButton: !isFullPageTranslationsRestrictedForPage,
});
SelectTranslationsTestUtils.#assertConditionalUIEnabled({
- textArea: true,
copyButton: true,
- translateFullPageButton: true,
+ doneButtonPrimary: true,
+ textArea: true,
+ translateFullPageButton:
+ !sameLanguageSelected && !isFullPageTranslationsRestrictedForPage,
});
+
+ await waitForCondition(
+ () =>
+ !copyButton.classList.contains("copied") &&
+ copyButton.getAttribute("data-l10n-id") ===
+ "select-translations-panel-copy-button",
+ "Waiting for copy button to match the not-copied state."
+ );
+
SelectTranslationsTestUtils.#assertPanelHasTranslatedText();
SelectTranslationsTestUtils.#assertPanelTextAreaHeight();
- SelectTranslationsTestUtils.#assertPanelTextAreaOverflow();
+ await SelectTranslationsTestUtils.#assertPanelTextAreaOverflow();
+
+ let footerButtons;
+ if (sameLanguageSelected || isFullPageTranslationsRestrictedForPage) {
+ footerButtons = [copyButton, doneButtonPrimary];
+ } else {
+ footerButtons =
+ AppConstants.platform === "win"
+ ? [copyButton, doneButtonPrimary, translateFullPageButton]
+ : [copyButton, translateFullPageButton, doneButtonPrimary];
+ }
+
+ SharedTranslationsTestUtils._assertTabIndexOrder([
+ settingsButton,
+ fromMenuList,
+ toMenuList,
+ textArea,
+ ...footerButtons,
+ ]);
+ }
+
+ /**
+ * Asserts that the SelectTranslationsPanel UI matches the expected
+ * state when the language lists fail to initialize upon opening the panel.
+ */
+ static async assertPanelViewInitFailure() {
+ const { cancelButton, settingsButton, tryAgainButton } =
+ SelectTranslationsPanel.elements;
+ await SelectTranslationsTestUtils.waitForPanelState("init-failure");
+ SelectTranslationsTestUtils.#assertPanelElementVisibility({
+ header: true,
+ betaIcon: true,
+ cancelButton: true,
+ initFailureContent: true,
+ initFailureMessageBar: true,
+ settingsButton: true,
+ tryAgainButton: true,
+ });
+ SharedTranslationsTestUtils._assertTabIndexOrder([
+ settingsButton,
+ ...(AppConstants.platform === "win"
+ ? [tryAgainButton, cancelButton]
+ : [cancelButton, tryAgainButton]),
+ ]);
+ SharedTranslationsTestUtils._assertHasFocus(tryAgainButton);
+ }
+
+ /**
+ * Asserts that the SelectTranslationsPanel UI matches the expected
+ * state when a translation has failed to complete.
+ */
+ static async assertPanelViewTranslationFailure() {
+ const {
+ cancelButton,
+ fromMenuList,
+ settingsButton,
+ toMenuList,
+ translationFailureMessageBar,
+ tryAgainButton,
+ } = SelectTranslationsPanel.elements;
+ await SelectTranslationsTestUtils.waitForPanelState("translation-failure");
+ SelectTranslationsTestUtils.#assertPanelElementVisibility({
+ header: true,
+ betaIcon: true,
+ cancelButton: true,
+ fromLabel: true,
+ fromMenuList: true,
+ mainContent: true,
+ settingsButton: true,
+ toLabel: true,
+ toMenuList: true,
+ translationFailureMessageBar: true,
+ tryAgainButton: true,
+ });
+ is(
+ document.activeElement,
+ tryAgainButton,
+ "The try-again button should have focus."
+ );
+ is(
+ translationFailureMessageBar.getAttribute("role"),
+ "alert",
+ "The translation failure message bar is an alert."
+ );
+ SharedTranslationsTestUtils._assertTabIndexOrder([
+ settingsButton,
+ fromMenuList,
+ toMenuList,
+ ...(AppConstants.platform === "win"
+ ? [tryAgainButton, cancelButton]
+ : [cancelButton, tryAgainButton]),
+ ]);
+ SharedTranslationsTestUtils._assertHasFocus(tryAgainButton);
}
static #assertPanelTextAreaDirection(langTag = null) {
@@ -1571,23 +1773,65 @@ class SelectTranslationsTestUtils {
}
/**
+ * Asserts that the SelectTranslationsPanel UI matches the expected
+ * state when the panel has completed its translation.
+ */
+ static async assertPanelViewUnsupportedLanguage() {
+ await SelectTranslationsTestUtils.waitForPanelState("unsupported");
+ const {
+ doneButtonSecondary,
+ settingsButton,
+ translateButton,
+ tryAnotherSourceMenuList,
+ unsupportedLanguageMessageBar,
+ } = SelectTranslationsPanel.elements;
+ SelectTranslationsTestUtils.#assertPanelElementVisibility({
+ betaIcon: true,
+ doneButtonSecondary: true,
+ header: true,
+ settingsButton: true,
+ translateButton: true,
+ tryAnotherSourceMenuList: true,
+ unsupportedLanguageContent: true,
+ unsupportedLanguageMessageBar: true,
+ });
+ SelectTranslationsTestUtils.#assertConditionalUIEnabled({
+ doneButtonSecondary: true,
+ translateButton: false,
+ });
+ ok(
+ translateButton.disabled,
+ "The translate button should be disabled when first shown."
+ );
+ SharedTranslationsTestUtils._assertL10nId(
+ unsupportedLanguageMessageBar,
+ "select-translations-panel-unsupported-language-message-known"
+ );
+ SharedTranslationsTestUtils._assertHasFocus(tryAnotherSourceMenuList);
+ SharedTranslationsTestUtils._assertTabIndexOrder([
+ settingsButton,
+ tryAnotherSourceMenuList,
+ doneButtonSecondary,
+ ]);
+ }
+
+ /**
* Asserts that the SelectTranslationsPanel translated text area is
* both scrollable and scrolled to the top.
*/
- static #assertPanelTextAreaOverflow() {
+ static async #assertPanelTextAreaOverflow() {
const { textArea } = SelectTranslationsPanel.elements;
- is(
- textArea.style.overflow,
- "auto",
- "The translated-text area should be scrollable."
- );
- if (textArea.scrollHeight > textArea.clientHeight) {
- is(
- textArea.scrollTop,
- 0,
- "The translated-text area should be scrolled to the top."
+ if (textArea.style.overflow !== "auto") {
+ await BrowserTestUtils.waitForMutationCondition(
+ textArea,
+ { attributes: true, attributeFilter: ["style"] },
+ () => textArea.style.overflow === "auto"
);
}
+ if (textArea.scrollHeight > textArea.clientHeight) {
+ info("Ensuring that the textarea is scrolled to the top.");
+ await waitForCondition(() => textArea.scrollTop === 0);
+ }
}
/**
@@ -1619,88 +1863,44 @@ class SelectTranslationsTestUtils {
* Asserts that the SelectTranslationsPanel UI matches the expected
* state when the panel is actively translating text.
*/
- static assertPanelViewActivelyTranslating() {
+ static async assertPanelViewActivelyTranslating() {
const { textArea } = SelectTranslationsPanel.elements;
+ const isFullPageTranslationsRestrictedForPage =
+ TranslationsParent.isFullPageTranslationsRestrictedForPage(gBrowser);
+ await SelectTranslationsTestUtils.waitForPanelState("translating");
ok(
textArea.classList.contains("translating"),
"The textarea should have the translating class."
);
SelectTranslationsTestUtils.#assertPanelElementVisibility({
- ...SelectTranslationsTestUtils.#alwaysPresentElements,
+ betaIcon: true,
+ copyButton: true,
+ doneButtonPrimary: true,
+ fromLabel: true,
+ fromMenuList: true,
+ header: true,
+ mainContent: true,
+ settingsButton: true,
+ textArea: true,
+ toLabel: true,
+ toMenuList: true,
+ translateFullPageButton: !isFullPageTranslationsRestrictedForPage,
});
SelectTranslationsTestUtils.#assertPanelHasTranslatingPlaceholder();
}
/**
- * Asserts that the SelectTranslationsPanel UI matches the expected
- * state when no from-language is selected in the panel.
- */
- static async assertPanelViewNoFromLangSelected() {
- const { textArea } = SelectTranslationsPanel.elements;
- ok(
- !textArea.classList.contains("translating"),
- "The textarea should not have the translating class."
- );
- SelectTranslationsTestUtils.#assertPanelElementVisibility({
- ...SelectTranslationsTestUtils.#alwaysPresentElements,
- });
- await SelectTranslationsTestUtils.#assertPanelHasIdlePlaceholder();
- SelectTranslationsTestUtils.#assertConditionalUIEnabled({
- textArea: false,
- copyButton: false,
- translateFullPageButton: false,
- });
- SelectTranslationsTestUtils.assertSelectedFromLanguage(null);
- }
-
- /**
- * Asserts that the SelectTranslationsPanel UI matches the expected
- * state when no to-language is selected in the panel.
- */
- static async assertPanelViewNoToLangSelected() {
- const { textArea } = SelectTranslationsPanel.elements;
- ok(
- !textArea.classList.contains("translating"),
- "The textarea should not have the translating class."
- );
- SelectTranslationsTestUtils.#assertPanelElementVisibility({
- ...SelectTranslationsTestUtils.#alwaysPresentElements,
- });
- SelectTranslationsTestUtils.assertSelectedToLanguage(null);
- SelectTranslationsTestUtils.#assertConditionalUIEnabled({
- textArea: false,
- copyButton: false,
- translateFullPageButton: false,
- });
- await SelectTranslationsTestUtils.#assertPanelHasIdlePlaceholder();
- }
-
- /**
- * Asserts that the SelectTranslationsPanel UI contains the
- * idle placeholder text.
- */
- static async #assertPanelHasIdlePlaceholder() {
- const { textArea } = SelectTranslationsPanel.elements;
- const expected = await document.l10n.formatValue(
- "select-translations-panel-idle-placeholder-text"
- );
- is(
- textArea.value,
- expected,
- "Translated text area should be the idle placeholder."
- );
- SelectTranslationsTestUtils.#assertPanelTextAreaDirection();
- }
-
- /**
* Asserts that the SelectTranslationsPanel UI contains the
* translating placeholder text.
*/
static async #assertPanelHasTranslatingPlaceholder() {
- const { textArea } = SelectTranslationsPanel.elements;
+ const { textArea, fromMenuList, toMenuList } =
+ SelectTranslationsPanel.elements;
const expected = await document.l10n.formatValue(
"select-translations-panel-translating-placeholder-text"
);
+ const isFullPageTranslationsRestrictedForPage =
+ TranslationsParent.isFullPageTranslationsRestrictedForPage(gBrowser);
is(
textArea.value,
expected,
@@ -1710,7 +1910,10 @@ class SelectTranslationsTestUtils {
SelectTranslationsTestUtils.#assertConditionalUIEnabled({
textArea: true,
copyButton: false,
- translateFullPageButton: true,
+ doneButtonPrimary: true,
+ translateFullPageButton:
+ fromMenuList.value !== toMenuList.value &&
+ !isFullPageTranslationsRestrictedForPage,
});
}
@@ -1723,6 +1926,27 @@ class SelectTranslationsTestUtils {
SelectTranslationsPanel.elements;
const fromLanguage = fromMenuList.value;
const toLanguage = toMenuList.value;
+ const isFullPageTranslationsRestrictedForPage =
+ TranslationsParent.isFullPageTranslationsRestrictedForPage(gBrowser);
+
+ SelectTranslationsTestUtils.#assertPanelTextAreaDirection(toLanguage);
+ SelectTranslationsTestUtils.#assertConditionalUIEnabled({
+ textArea: true,
+ copyButton: true,
+ doneButtonPrimary: true,
+ translateFullPageButton:
+ fromLanguage !== toLanguage && !isFullPageTranslationsRestrictedForPage,
+ });
+
+ if (fromLanguage === toLanguage) {
+ is(
+ SelectTranslationsPanel.getSourceText(),
+ SelectTranslationsPanel.getTranslatedText(),
+ "The source text should passthrough as the translated text."
+ );
+ return;
+ }
+
const translatedSuffix = ` [${fromLanguage} to ${toLanguage}]`;
ok(
textArea.value.endsWith(translatedSuffix),
@@ -1734,45 +1958,32 @@ class SelectTranslationsTestUtils {
translatedSuffix.length,
"Expected translated text length to correspond to the source text length."
);
- SelectTranslationsTestUtils.#assertPanelTextAreaDirection(toLanguage);
- SelectTranslationsTestUtils.#assertConditionalUIEnabled({
- textArea: true,
- copyButton: true,
- translateFullPageButton: true,
- });
}
/**
* Asserts the enabled state of action buttons in the SelectTranslationsPanel.
*
- * @param {boolean} expectEnabled - Whether the buttons should be enabled (true) or not (false).
+ * @param {Record<string, boolean>} enabledStates
+ * - An object that maps whether each element should be enabled (true) or disabled (false).
*/
- static #assertConditionalUIEnabled({
- copyButton: copyButtonEnabled,
- translateFullPageButton: translateFullPageButtonEnabled,
- textArea: textAreaEnabled,
- }) {
- const { copyButton, translateFullPageButton, textArea } =
- SelectTranslationsPanel.elements;
- is(
- copyButton.disabled,
- !copyButtonEnabled,
- `The copy button should be ${copyButtonEnabled ? "enabled" : "disabled"}.`
- );
- is(
- translateFullPageButton.disabled,
- !translateFullPageButtonEnabled,
- `The translate-full-page button should be ${
- translateFullPageButtonEnabled ? "enabled" : "disabled"
- }.`
- );
- is(
- textArea.disabled,
- !textAreaEnabled,
- `The translated-text area should be ${
- textAreaEnabled ? "enabled" : "disabled"
- }.`
- );
+ static #assertConditionalUIEnabled(enabledStates) {
+ const elements = SelectTranslationsPanel.elements;
+
+ for (const [elementName, expectEnabled] of Object.entries(enabledStates)) {
+ const element = elements[elementName];
+ if (!element) {
+ throw new Error(
+ `SelectTranslationsPanel element '${elementName}' not found.`
+ );
+ }
+ is(
+ element.disabled,
+ !expectEnabled,
+ `The element '${elementName} should be ${
+ expectEnabled ? "enabled" : "disabled"
+ }.`
+ );
+ }
}
/**
@@ -1820,22 +2031,235 @@ class SelectTranslationsTestUtils {
*/
static async clickDoneButton() {
logAction();
- const { doneButton } = SelectTranslationsPanel.elements;
- assertVisibility({ visible: { doneButton } });
+ const { doneButtonPrimary, doneButtonSecondary } =
+ SelectTranslationsPanel.elements;
+ let visibleDoneButton;
+ let hiddenDoneButton;
+ if (BrowserTestUtils.isVisible(doneButtonPrimary)) {
+ visibleDoneButton = doneButtonPrimary;
+ hiddenDoneButton = doneButtonSecondary;
+ } else if (BrowserTestUtils.isVisible(doneButtonSecondary)) {
+ visibleDoneButton = doneButtonSecondary;
+ hiddenDoneButton = doneButtonPrimary;
+ } else {
+ throw new Error(
+ "Expected either the primary or secondary done button to be visible."
+ );
+ }
+ assertVisibility({
+ visible: { visibleDoneButton },
+ hidden: { hiddenDoneButton },
+ });
+ await SelectTranslationsTestUtils.waitForPanelPopupEvent(
+ "popuphidden",
+ () => {
+ click(visibleDoneButton, "Clicking the done button");
+ }
+ );
+ }
+
+ /**
+ * Simulates clicking the cancel button and waits for the panel to close.
+ */
+ static async clickCancelButton() {
+ logAction();
+ const { cancelButton } = SelectTranslationsPanel.elements;
+ assertVisibility({ visible: { cancelButton } });
await SelectTranslationsTestUtils.waitForPanelPopupEvent(
"popuphidden",
() => {
- click(doneButton, "Clicking the done button");
+ click(cancelButton, "Clicking the cancel button");
}
);
}
/**
+ * Simulates clicking the copy button and asserts that all relevant states are correctly updated.
+ */
+ static async clickCopyButton() {
+ logAction();
+ const { copyButton } = SelectTranslationsPanel.elements;
+
+ assertVisibility({ visible: { copyButton } });
+ is(
+ SelectTranslationsPanel.phase(),
+ "translated",
+ 'The copy button should only be clickable in the "translated" phase'
+ );
+
+ click(copyButton, "Clicking the copy button");
+ await waitForCondition(
+ () =>
+ copyButton.classList.contains("copied") &&
+ copyButton.getAttribute("data-l10n-id") ===
+ "select-translations-panel-copy-button-copied",
+ "Waiting for copy button to match the copied state."
+ );
+
+ const copiedText = SpecialPowers.getClipboardData("text/plain");
+ is(
+ // Because of differences in the clipboard code on Windows, we are going
+ // to explicitly sanitize carriage returns here when checking equality.
+ copiedText.replaceAll("\r", ""),
+ SelectTranslationsPanel.getTranslatedText().replaceAll("\r", ""),
+ "The clipboard should contain the translated text."
+ );
+ }
+
+ /**
+ * Simulates clicking the Translate button in the SelectTranslationsPanel,
+ * then waits for any pending translation effects, based on the provided options.
+ *
+ * @param {object} config
+ * @param {Function} [config.downloadHandler]
+ * - The function handle expected downloads, resolveDownloads() or rejectDownloads()
+ * Leave as null to test more granularly, such as testing opening the loading view,
+ * or allowing for the automatic downloading of files.
+ * @param {boolean} [config.pivotTranslation]
+ * - True if the expected translation is a pivot translation, otherwise false.
+ * Affects the number of expected downloads.
+ * @param {Function} [config.viewAssertion]
+ * - An optional callback function to execute for asserting the panel UI state.
+ */
+ static async clickTranslateButton({
+ downloadHandler,
+ pivotTranslation,
+ viewAssertion,
+ }) {
+ logAction();
+ const {
+ doneButtonSecondary,
+ settingsButton,
+ translateButton,
+ tryAnotherSourceMenuList,
+ } = SelectTranslationsPanel.elements;
+ assertVisibility({ visible: { doneButtonPrimary: translateButton } });
+
+ ok(!translateButton.disabled, "The translate button should be enabled.");
+ SharedTranslationsTestUtils._assertTabIndexOrder([
+ settingsButton,
+ tryAnotherSourceMenuList,
+ ...(AppConstants.platform === "win"
+ ? [translateButton, doneButtonSecondary]
+ : [doneButtonSecondary, translateButton]),
+ ]);
+
+ click(translateButton);
+ await SelectTranslationsTestUtils.waitForPanelState("translatable");
+ if (downloadHandler) {
+ await this.handleDownloads({ downloadHandler, pivotTranslation });
+ }
+ if (viewAssertion) {
+ await viewAssertion();
+ }
+ }
+
+ /**
+ * Simulates clicking the translate-full-page button.
+ */
+ static async clickTranslateFullPageButton() {
+ logAction();
+ const { translateFullPageButton } = SelectTranslationsPanel.elements;
+ assertVisibility({ visible: { translateFullPageButton } });
+ click(translateFullPageButton);
+ await FullPageTranslationsTestUtils.assertTranslationsButton(
+ { button: true, circleArrows: true, locale: false, icon: true },
+ "The icon presents the loading indicator."
+ );
+ }
+
+ /**
+ * Simulates clicking the try-again button.
+ *
+ * @param {object} config
+ * @param {Function} [config.downloadHandler]
+ * - The function handle expected downloads, resolveDownloads() or rejectDownloads()
+ * Leave as null to test more granularly, such as testing opening the loading view,
+ * or allowing for the automatic downloading of files.
+ * @param {boolean} [config.pivotTranslation]
+ * - True if the expected translation is a pivot translation, otherwise false.
+ * Affects the number of expected downloads.
+ * @param {Function} [config.viewAssertion]
+ * - An optional callback function to execute for asserting the panel UI state.
+ */
+ static async clickTryAgainButton({
+ downloadHandler,
+ pivotTranslation,
+ viewAssertion,
+ } = {}) {
+ logAction();
+ const { tryAgainButton } = SelectTranslationsPanel.elements;
+ assertVisibility({ visible: { tryAgainButton } });
+ click(tryAgainButton, "Clicking the try-again button");
+ await SelectTranslationsTestUtils.waitForPanelState("translatable");
+ if (downloadHandler) {
+ await this.handleDownloads({ downloadHandler, pivotTranslation });
+ }
+ if (viewAssertion) {
+ await viewAssertion();
+ }
+ }
+
+ /**
+ * Opens the SelectTranslationsPanel settings menu.
+ * Requires that the translations panel is already open.
+ */
+ static async openPanelSettingsMenu() {
+ logAction();
+ const { settingsButton } = SelectTranslationsPanel.elements;
+ assertVisibility({ visible: { settingsButton } });
+ await SharedTranslationsTestUtils._waitForPopupEvent(
+ "select-translations-panel-settings-menupopup",
+ "popupshown",
+ () => click(settingsButton, "Opening the settings menu")
+ );
+ const settingsPageMenuItem = document.getElementById(
+ "select-translations-panel-open-settings-page-menuitem"
+ );
+ const aboutTranslationsMenuItem = document.getElementById(
+ "select-translations-panel-about-translations-menuitem"
+ );
+
+ assertVisibility({
+ visible: {
+ settingsPageMenuItem,
+ aboutTranslationsMenuItem,
+ },
+ });
+ }
+
+ /**
+ * Clicks the SelectTranslationsPanel settings menu item
+ * that leads to the Translations Settings in about:preferences.
+ */
+ static clickTranslationsSettingsPageMenuItem() {
+ logAction();
+ const settingsPageMenuItem = document.getElementById(
+ "select-translations-panel-open-settings-page-menuitem"
+ );
+ assertVisibility({ visible: { settingsPageMenuItem } });
+ click(settingsPageMenuItem);
+ }
+
+ /**
* Opens the context menu at a specified element on the page, based on the provided options.
*
* @param {Function} runInPage - A content-exposed function to run within the context of the page.
* @param {object} options - Options for opening the context menu.
*
+ * @param {boolean} options.expectMenuItemVisible - Whether the select-translations menu item should be present in the context menu.
+ * @param {boolean} options.expectedTargetLanguage - The expected target language to be shown in the context menu.
+ *
+ * The following options will work on all test pages that have an <h1> element.
+ *
+ * @param {boolean} options.selectH1 - Selects the first H1 element of the page.
+ * @param {boolean} options.openAtH1 - Opens the context menu at the first H1 element of the page.
+ *
+ * The following options will work only in the PDF_TEST_PAGE_URL.
+ *
+ * @param {boolean} options.selectPdfSpan - Selects the first span of text on the first page of a pdf.
+ * @param {boolean} options.openAtPdfSpan - Opens the context menu at the first span of text on the first page of a pdf.
+ *
* The following options will only work when testing SELECT_TEST_PAGE_URL.
*
* @param {boolean} options.selectFrenchSection - Selects the section of French text.
@@ -1868,8 +2292,8 @@ class SelectTranslationsTestUtils {
const selectorFunction =
TranslationsTest.getSelectors()[data.selectorFunctionName];
if (typeof selectorFunction === "function") {
- const paragraph = selectorFunction();
- TranslationsTest.selectContentElement(paragraph);
+ const element = await selectorFunction();
+ TranslationsTest.selectContentElement(element);
}
},
{ selectorFunctionName }
@@ -1877,6 +2301,8 @@ class SelectTranslationsTestUtils {
}
};
+ await maybeSelectContentFrom("H1");
+ await maybeSelectContentFrom("PdfSpan");
await maybeSelectContentFrom("FrenchSection");
await maybeSelectContentFrom("EnglishSection");
await maybeSelectContentFrom("SpanishSection");
@@ -1898,7 +2324,7 @@ class SelectTranslationsTestUtils {
const selectorFunction =
TranslationsTest.getSelectors()[data.selectorFunctionName];
if (typeof selectorFunction === "function") {
- const element = selectorFunction();
+ const element = await selectorFunction();
await TranslationsTest.rightClickContentElement(element);
}
},
@@ -1909,6 +2335,8 @@ class SelectTranslationsTestUtils {
}
};
+ await maybeOpenContextMenuAt("H1");
+ await maybeOpenContextMenuAt("PdfSpan");
await maybeOpenContextMenuAt("FrenchSection");
await maybeOpenContextMenuAt("EnglishSection");
await maybeOpenContextMenuAt("SpanishSection");
@@ -1931,28 +2359,10 @@ class SelectTranslationsTestUtils {
* @returns {Promise<void>}
*/
static async handleDownloads({ downloadHandler, pivotTranslation }) {
- const { textArea } = SelectTranslationsPanel.elements;
-
if (downloadHandler) {
- if (textArea.style.overflow !== "hidden") {
- await BrowserTestUtils.waitForMutationCondition(
- textArea,
- { attributes: true, attributeFilter: ["style"] },
- () => textArea.style.overflow === "hidden"
- );
- }
-
await SelectTranslationsTestUtils.assertPanelViewActivelyTranslating();
await downloadHandler(pivotTranslation ? 2 : 1);
}
-
- if (textArea.style.overflow === "hidden") {
- await BrowserTestUtils.waitForMutationCondition(
- textArea,
- { attributes: true, attributeFilter: ["style"] },
- () => textArea.style.overflow === "auto"
- );
- }
}
/**
@@ -1965,6 +2375,7 @@ class SelectTranslationsTestUtils {
* @returns {Promise<void>}
*/
static async changeSelectedFromLanguage(langTags, options) {
+ logAction(langTags);
const { fromMenuList, fromMenuPopup } = SelectTranslationsPanel.elements;
const { openDropdownMenu } = options;
@@ -1980,6 +2391,28 @@ class SelectTranslationsTestUtils {
}
/**
+ * Change the selected language in the try-another-source-language dropdown.
+ *
+ * @param {string} langTag - A BCP-47 language tag.
+ */
+ static async changeSelectedTryAnotherSourceLanguage(langTag) {
+ logAction(langTag);
+ const { tryAnotherSourceMenuList, translateButton } =
+ SelectTranslationsPanel.elements;
+ await SelectTranslationsTestUtils.#changeSelectedLanguageDirectly(
+ [langTag],
+ { menuList: tryAnotherSourceMenuList },
+ {
+ onChangeLanguage: () =>
+ ok(
+ !translateButton.disabled,
+ "The translate button should be enabled after selecting a language."
+ ),
+ }
+ );
+ }
+
+ /**
* Switches the selected to-language to the provided language tag.
*
* @param {string[]} langTags - An array of BCP-47 language tags.
@@ -1991,6 +2424,7 @@ class SelectTranslationsTestUtils {
* @returns {Promise<void>}
*/
static async changeSelectedToLanguage(langTags, options) {
+ logAction(langTags);
const { toMenuList, toMenuPopup } = SelectTranslationsPanel.elements;
const { openDropdownMenu } = options;
@@ -2019,6 +2453,7 @@ class SelectTranslationsTestUtils {
*/
static async #changeSelectedLanguageDirectly(langTags, elements, options) {
const { menuList } = elements;
+ const { textArea } = SelectTranslationsPanel.elements;
const { onChangeLanguage, downloadHandler } = options;
for (const langTag of langTags) {
@@ -2028,14 +2463,23 @@ class SelectTranslationsTestUtils {
() => menuList.value === langTag
);
+ menuList.focus();
menuList.value = langTag;
menuList.dispatchEvent(new Event("command"));
await menuListUpdated;
}
- if (downloadHandler) {
- menuList.focus();
+ // Either of these events should trigger a translation after the selected
+ // language has been changed directly.
+ if (Math.random() < 0.5) {
+ info("Attempting to trigger translation via text-area focus.");
+ textArea.focus();
+ } else {
+ info("Attempting to trigger translation via pressing Enter.");
EventUtils.synthesizeKey("KEY_Enter");
+ }
+
+ if (downloadHandler) {
await SelectTranslationsTestUtils.handleDownloads(options);
}