From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../translations/tests/browser/browser.ini | 19 + .../tests/browser/browser_manage_languages.js | 195 ++++++++++ ...translations_panel_always_translate_language.js | 413 ++++++++++++++++++++ .../browser/browser_translations_panel_basics.js | 94 +++++ .../browser_translations_panel_beta_langs.js | 66 ++++ .../browser/browser_translations_panel_button.js | 80 ++++ .../browser/browser_translations_panel_cancel.js | 32 ++ .../browser/browser_translations_panel_gear.js | 42 ++ ..._translations_panel_never_translate_language.js | 343 ++++++++++++++++ ...wser_translations_panel_never_translate_site.js | 432 +++++++++++++++++++++ .../browser/browser_translations_panel_retry.js | 80 ++++ .../browser_translations_panel_switch_languages.js | 97 +++++ .../browser_translations_telemetry_open_panel.js | 73 ++++ ...r_translations_telemetry_translation_failure.js | 195 ++++++++++ ...r_translations_telemetry_translation_request.js | 173 +++++++++ .../components/translations/tests/browser/head.js | 348 +++++++++++++++++ 16 files changed, 2682 insertions(+) create mode 100644 browser/components/translations/tests/browser/browser.ini create mode 100644 browser/components/translations/tests/browser/browser_manage_languages.js create mode 100644 browser/components/translations/tests/browser/browser_translations_panel_always_translate_language.js create mode 100644 browser/components/translations/tests/browser/browser_translations_panel_basics.js create mode 100644 browser/components/translations/tests/browser/browser_translations_panel_beta_langs.js create mode 100644 browser/components/translations/tests/browser/browser_translations_panel_button.js create mode 100644 browser/components/translations/tests/browser/browser_translations_panel_cancel.js create mode 100644 browser/components/translations/tests/browser/browser_translations_panel_gear.js create mode 100644 browser/components/translations/tests/browser/browser_translations_panel_never_translate_language.js create mode 100644 browser/components/translations/tests/browser/browser_translations_panel_never_translate_site.js create mode 100644 browser/components/translations/tests/browser/browser_translations_panel_retry.js create mode 100644 browser/components/translations/tests/browser/browser_translations_panel_switch_languages.js create mode 100644 browser/components/translations/tests/browser/browser_translations_telemetry_open_panel.js create mode 100644 browser/components/translations/tests/browser/browser_translations_telemetry_translation_failure.js create mode 100644 browser/components/translations/tests/browser/browser_translations_telemetry_translation_request.js create mode 100644 browser/components/translations/tests/browser/head.js (limited to 'browser/components/translations/tests') diff --git a/browser/components/translations/tests/browser/browser.ini b/browser/components/translations/tests/browser/browser.ini new file mode 100644 index 0000000000..fd67597972 --- /dev/null +++ b/browser/components/translations/tests/browser/browser.ini @@ -0,0 +1,19 @@ +[DEFAULT] +support-files = + head.js + !/toolkit/components/translations/tests/browser/shared-head.js + !/toolkit/components/translations/tests/browser/translations-test.mjs +[browser_manage_languages.js] +[browser_translations_panel_always_translate_language.js] +[browser_translations_panel_basics.js] +[browser_translations_panel_beta_langs.js] +[browser_translations_panel_button.js] +[browser_translations_panel_cancel.js] +[browser_translations_panel_gear.js] +[browser_translations_panel_never_translate_language.js] +[browser_translations_panel_never_translate_site.js] +[browser_translations_panel_retry.js] +[browser_translations_panel_switch_languages.js] +[browser_translations_telemetry_open_panel.js] +[browser_translations_telemetry_translation_failure.js] +[browser_translations_telemetry_translation_request.js] diff --git a/browser/components/translations/tests/browser/browser_manage_languages.js b/browser/components/translations/tests/browser/browser_manage_languages.js new file mode 100644 index 0000000000..651029ad86 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_manage_languages.js @@ -0,0 +1,195 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const frenchModels = [ + "lex.50.50.enfr.s2t.bin", + "lex.50.50.fren.s2t.bin", + "model.enfr.intgemm.alphas.bin", + "model.fren.intgemm.alphas.bin", + "vocab.enfr.spm", + "vocab.fren.spm", +]; + +add_task(async function test_about_preferences_manage_languages() { + const { + cleanup, + remoteClients, + elements: { + downloadAllLabel, + downloadAll, + deleteAll, + frenchLabel, + frenchDownload, + frenchDelete, + spanishLabel, + spanishDownload, + spanishDelete, + }, + } = await setupAboutPreferences([ + { fromLang: "en", toLang: "fr" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "es", toLang: "en" }, + ]); + + is( + downloadAllLabel.getAttribute("data-l10n-id"), + "translations-manage-all-language", + "The first row is all of the languages." + ); + is(frenchLabel.textContent, "French", "There is a French row."); + is(spanishLabel.textContent, "Spanish", "There is a Spanish row."); + + await assertVisibility({ + message: "Everything starts out as available to download", + visible: { downloadAll, frenchDownload, spanishDownload }, + hidden: { deleteAll, frenchDelete, spanishDelete }, + }); + + click(frenchDownload, "Downloading French"); + + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + frenchModels.length + ), + frenchModels, + "French models were downloaded." + ); + + await assertVisibility({ + message: "French can now be deleted, and delete all is available.", + visible: { downloadAll, deleteAll, frenchDelete, spanishDownload }, + hidden: { frenchDownload, spanishDelete }, + }); + + click(frenchDelete, "Deleting French"); + + await assertVisibility({ + message: "Everything can be downloaded.", + visible: { downloadAll, frenchDownload, spanishDownload }, + hidden: { deleteAll, frenchDelete, spanishDelete }, + }); + + click(downloadAll, "Downloading all languages."); + + const allModels = [ + "lex.50.50.enes.s2t.bin", + "lex.50.50.enfr.s2t.bin", + "lex.50.50.esen.s2t.bin", + "lex.50.50.fren.s2t.bin", + "model.enes.intgemm.alphas.bin", + "model.enfr.intgemm.alphas.bin", + "model.esen.intgemm.alphas.bin", + "model.fren.intgemm.alphas.bin", + "vocab.enes.spm", + "vocab.enfr.spm", + "vocab.esen.spm", + "vocab.fren.spm", + ]; + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + allModels.length + ), + allModels, + "All models were downloaded." + ); + Assert.deepEqual( + await remoteClients.languageIdModels.resolvePendingDownloads(1), + ["lid.176.ftz"], + "Language ID model was downloaded." + ); + Assert.deepEqual( + await remoteClients.translationsWasm.resolvePendingDownloads(2), + ["bergamot-translator", "fasttext-wasm"], + "Wasm was downloaded." + ); + + await assertVisibility({ + message: "Everything can be deleted.", + visible: { deleteAll, frenchDelete, spanishDelete }, + hidden: { downloadAll, frenchDownload, spanishDownload }, + }); + + click(deleteAll, "Deleting all languages."); + + await assertVisibility({ + message: "Everything can be downloaded again", + visible: { downloadAll, frenchDownload, spanishDownload }, + hidden: { deleteAll, frenchDelete, spanishDelete }, + }); + + click(frenchDownload, "Downloading French."); + click(spanishDownload, "Downloading Spanish."); + + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + allModels.length + ), + allModels, + "All models were downloaded again." + ); + + remoteClients.translationsWasm.assertNoNewDownloads(); + remoteClients.languageIdModels.assertNoNewDownloads(); + + await assertVisibility({ + message: "Everything is downloaded again.", + visible: { deleteAll, frenchDelete, spanishDelete }, + hidden: { downloadAll, frenchDownload, spanishDownload }, + }); + + return cleanup(); +}); + +add_task(async function test_about_preferences_download_reject() { + const { + cleanup, + remoteClients, + elements: { document, frenchDownload }, + } = await setupAboutPreferences([ + { fromLang: "en", toLang: "fr" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "es", toLang: "en" }, + ]); + + click(frenchDownload, "Downloading French"); + + is( + maybeGetByL10nId("translations-manage-error-download", document), + null, + "No error messages are present." + ); + + const errors = await captureTranslationsError(() => + remoteClients.translationModels.rejectPendingDownloads(frenchModels.length) + ); + + ok( + !!errors.length, + `The errors for download should have been reported, found ${errors.length} errors` + ); + for (const { error } of errors) { + is( + error?.message, + "Failed to download file.", + "The error reported was a download error." + ); + } + + await TestUtils.waitForCondition( + () => maybeGetByL10nId("translations-manage-error-download", document), + "The error message is now visible." + ); + + click(frenchDownload, "Attempting to download French again", document); + is( + maybeGetByL10nId("translations-manage-error-download", document), + null, + "The error message is hidden again." + ); + + return cleanup(); +}); diff --git a/browser/components/translations/tests/browser/browser_translations_panel_always_translate_language.js b/browser/components/translations/tests/browser/browser_translations_panel_always_translate_language.js new file mode 100644 index 0000000000..4bc2c7dc15 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_panel_always_translate_language.js @@ -0,0 +1,413 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the effect of toggling the always-translate-language menuitem. + * Checking the box on an untranslated page should immediately translate the page. + * Unchecking the box on a translated page should immediately restore the page. + */ +add_task(async function test_toggle_always_translate_language_menuitem() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.alwaysTranslateLanguages", "pl,fr"]], + }); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + info( + 'The document language "es" is not in the alwaysTranslateLanguages pref, ' + + "so the page should be untranslated, in its original form" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + info( + "Simulate clicking always-translate-language in the settings menu, " + + "adding the document language to the alwaysTranslateLanguages pref" + ); + await openSettingsMenu(); + + await assertIsAlwaysTranslateLanguage("es", false); + await toggleAlwaysTranslateLanguage(); + await assertIsAlwaysTranslateLanguage("es", true); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + const { locale } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + info( + "The page should now be automatically translated because the document language " + + "should be added to the always-translate pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is translated automatically", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + info("Navigate to a different Spanish page"); + await navigate(SPANISH_PAGE_URL_DOT_ORG); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + info( + "The page should now be automatically translated because the document language " + + "should be added to the always-translate pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is translated automatically", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + info( + "Simulate clicking always-translate-language in the settings menu " + + "removing the document language from the alwaysTranslateLanguages pref" + ); + await openSettingsMenu(); + + await assertIsAlwaysTranslateLanguage("es", true); + await toggleAlwaysTranslateLanguage(); + await assertIsAlwaysTranslateLanguage("es", false); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "Only the button appears" + ); + + info( + "The page should no longer automatically translated because the document language " + + "should be removed from the always-translate pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await cleanup(); +}); + +/** + * Tests the effect of toggling the always-translate-language menuitem after the page has + * been manually translated. This should not reload or retranslate the page, but just check + * the box. + */ +add_task( + async function test_activate_always_translate_language_after_manual_translation() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.alwaysTranslateLanguages", "pl,fr"]], + }); + + const { button } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + info( + 'The document language "es" is not in the alwaysTranslateLanguages pref, ' + + "so the page should be untranslated, in its original form" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-button"), + "Start translating by clicking the translate button." + ); + }); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + const { locale } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + info( + "Simulate clicking always-translate-language in the settings menu, " + + "adding the document language to the alwaysTranslateLanguages pref" + ); + await openSettingsMenu(); + + await assertIsAlwaysTranslateLanguage("es", false); + await toggleAlwaysTranslateLanguage(); + await assertIsAlwaysTranslateLanguage("es", true); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The continues to present the locale without pending downloads." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + info( + "Simulate clicking always-translate-language in the settings menu " + + "removing the document language from the alwaysTranslateLanguages pref" + ); + await assertIsAlwaysTranslateLanguage("es", true); + await toggleAlwaysTranslateLanguage(); + await assertIsAlwaysTranslateLanguage("es", false); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "Only the button appears" + ); + + info( + "The page should no longer automatically translated because the document language " + + "should be removed from the always-translate pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await cleanup(); + } +); + +/** + * Tests the effect of unchecking the always-translate language menuitem after the page has + * been manually restored to its original form. + * This should have no effect on the page, and further page loads should no longer auto-translate. + */ +add_task( + async function test_deactivate_always_translate_language_after_restore() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.alwaysTranslateLanguages", "pl,fr"]], + }); + + const { button } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + info( + 'The document language "es" is not in the alwaysTranslateLanguages pref, ' + + "so the page should be untranslated, in its original form" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + info( + "Simulate clicking always-translate-language in the settings menu, " + + "adding the document language to the alwaysTranslateLanguages pref" + ); + await openSettingsMenu(); + + await assertIsAlwaysTranslateLanguage("es", false); + await toggleAlwaysTranslateLanguage(); + await assertIsAlwaysTranslateLanguage("es", true); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + const { locale } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + info( + "The page should now be automatically translated because the document language " + + "should be added to the always-translate pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is translated automatically", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + await navigate( + SPANISH_PAGE_URL_DOT_ORG, + "Navigate to a different Spanish page" + ); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + info( + "The page should now be automatically translated because the document language " + + "should be added to the always-translate pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is translated automatically", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Re-opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-restore-button"), + "Click the restore language button." + ); + }); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is reverted to have an icon." + ); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is restored to Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + info( + "Simulate clicking always-translate-language in the settings menu, " + + "removing the document language to the alwaysTranslateLanguages pref" + ); + await openSettingsMenu(); + + await assertIsAlwaysTranslateLanguage("es", true); + await toggleAlwaysTranslateLanguage(); + await assertIsAlwaysTranslateLanguage("es", false); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button shows only the icon." + ); + + await navigate(SPANISH_PAGE_URL_DOT_ORG, "Reload the page"); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button shows only the icon." + ); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is restored to Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await cleanup(); + } +); diff --git a/browser/components/translations/tests/browser/browser_translations_panel_basics.js b/browser/components/translations/tests/browser/browser_translations_panel_basics.js new file mode 100644 index 0000000000..df2b0da4e5 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_panel_basics.js @@ -0,0 +1,94 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests a basic panel open, translation, and restoration to the original language. + */ +add_task(async function test_translations_panel_basics() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + const { button } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-button"), + "Start translating by clicking the translate button." + ); + }); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + const { locale } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Re-opening the popup"); + }); + + ok( + getByL10nId("translations-panel-translate-button").disabled, + "The translate button is disabled when re-opening." + ); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-restore-button"), + "Click the restore language button." + ); + }); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is restored to Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is reverted to have an icon." + ); + + await cleanup(); +}); diff --git a/browser/components/translations/tests/browser/browser_translations_panel_beta_langs.js b/browser/components/translations/tests/browser/browser_translations_panel_beta_langs.js new file mode 100644 index 0000000000..f44f2ad9e8 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_panel_beta_langs.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that languages are displayed correctly as being in beta or not. + */ +add_task(async function test_translations_panel_display_beta_languages() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + function assertBetaDisplay(selectElement) { + const betaL10nId = "translations-panel-displayname-beta"; + const options = selectElement.querySelectorAll("menuitem"); + if (options.length === 0) { + throw new Error("Could not find the menuitems."); + } + + for (const option of options) { + for (const languagePair of LANGUAGE_PAIRS) { + if ( + languagePair.fromLang === option.value || + languagePair.toLang === option.value + ) { + if (option.getAttribute("data-l10n-id") === betaL10nId) { + is( + languagePair.isBeta, + true, + `Since data-l10n-id was ${betaL10nId} for ${option.value}, then it must be part of a beta language pair, but it was not.` + ); + } + if (!languagePair.isBeta) { + is( + option.getAttribute("data-l10n-id") === betaL10nId, + false, + `Since the languagePair is non-beta, the language option ${option.value} should not have a data-l10-id of ${betaL10nId}, but it does.` + ); + } + } + } + } + } + + const { button } = await assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + assertBetaDisplay(document.getElementById("translations-panel-to")); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-cancel"), + "Click the cancel button." + ); + }); + + await cleanup(); +}); diff --git a/browser/components/translations/tests/browser/browser_translations_panel_button.js b/browser/components/translations/tests/browser/browser_translations_panel_button.js new file mode 100644 index 0000000000..57e09260fb --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_panel_button.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Test that the translations button is correctly visible when navigating between pages. + */ +add_task(async function test_button_visible_navigation() { + info("Start at a page in Spanish."); + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await assertTranslationsButton( + { button: true }, + "The button should be visible since the page can be translated from Spanish." + ); + + navigate(ENGLISH_PAGE_URL, "Navigate to an English page."); + + await assertTranslationsButton( + { button: false }, + "The button should be invisible since the page is in English." + ); + + navigate(SPANISH_PAGE_URL, "Navigate back to a Spanish page."); + + await assertTranslationsButton( + { button: true }, + "The button should be visible again since the page is in Spanish." + ); + + await cleanup(); +}); + +/** + * Test that the translations button is correctly visible when opening and switch tabs. + */ +add_task(async function test_button_visible() { + info("Start at a page in Spanish."); + + const { cleanup, tab: spanishTab } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await assertTranslationsButton( + { button: true }, + "The button should be visible since the page can be translated from Spanish." + ); + + const { removeTab, tab: englishTab } = await addTab( + ENGLISH_PAGE_URL, + "Creating a new tab for a page in English." + ); + + await assertTranslationsButton( + { button: false }, + "The button should be invisible since the tab is in English." + ); + + await switchTab(spanishTab); + + await assertTranslationsButton( + { button: true }, + "The button should be visible again since the page is in Spanish." + ); + + await switchTab(englishTab); + + await assertTranslationsButton( + { button: false }, + "Don't show for english pages" + ); + + await removeTab(); + await cleanup(); +}); diff --git a/browser/components/translations/tests/browser/browser_translations_panel_cancel.js b/browser/components/translations/tests/browser/browser_translations_panel_cancel.js new file mode 100644 index 0000000000..b9bf532d96 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_panel_cancel.js @@ -0,0 +1,32 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests a panel open, and hitting the cancel button. + */ +add_task(async function test_translations_panel_cancel() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + const { button } = await assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-cancel"), + "Click the cancel button." + ); + }); + + await cleanup(); +}); diff --git a/browser/components/translations/tests/browser/browser_translations_panel_gear.js b/browser/components/translations/tests/browser/browser_translations_panel_gear.js new file mode 100644 index 0000000000..46838accb4 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_panel_gear.js @@ -0,0 +1,42 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Test managing the languages menu item. + */ +add_task(async function test_translations_panel_manage_languages() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + const { button } = await assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + const gearIcon = getByL10nId("translations-panel-settings-button"); + click(gearIcon, "Open the preferences menu"); + + const manageLanguages = getByL10nId( + "translations-panel-settings-manage-languages" + ); + info("Choose to manage the languages."); + manageLanguages.doCommand(); + + await TestUtils.waitForCondition( + () => gBrowser.currentURI.spec === "about:preferences#general", + "Waiting for about:preferences to be opened." + ); + + info("Remove the about:preferences tab"); + gBrowser.removeCurrentTab(); + + await cleanup(); +}); diff --git a/browser/components/translations/tests/browser/browser_translations_panel_never_translate_language.js b/browser/components/translations/tests/browser/browser_translations_panel_never_translate_language.js new file mode 100644 index 0000000000..c85443f457 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_panel_never_translate_language.js @@ -0,0 +1,343 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the effect of toggling the never-translate-language menuitem. + * Checking the box on an untranslated page should immediately hide the button. + * The button should not appear again for sites in the disabled language. + */ +add_task(async function test_toggle_never_translate_language_menuitem() { + const { cleanup, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.neverTranslateLanguages", "pl,fr"]], + }); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + info( + 'The document language "es" is not in the neverTranslateLanguages pref, ' + + "so the page should be untranslated, in its original form." + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + info( + "Simulate clicking never-translate-language in the settings menu, " + + "adding the document language from the neverTranslateLanguages pref" + ); + await openSettingsMenu(); + + await assertIsNeverTranslateLanguage("es", false); + await toggleNeverTranslateLanguage(); + await assertIsNeverTranslateLanguage("es", true); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info( + "The page should still be in its original, untranslated form because " + + "the document language is in the neverTranslateLanguages pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate(SPANISH_PAGE_URL, "Reload the page"); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info( + "The page should still be in its original, untranslated form because " + + "the document language is in the neverTranslateLanguages pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate( + SPANISH_PAGE_URL_DOT_ORG, + "Navigate to a different Spanish page" + ); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info( + "The page should still be in its original, untranslated form because " + + "the document language is in the neverTranslateLanguages pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await cleanup(); +}); + +/** + * Tests the effect of toggling the never-translate-language menuitem on a page where + * where translation is already active. + * Checking the box on a translated page should restore the page and hide the button. + * The button should not appear again for sites in the disabled language. + */ +add_task( + async function test_toggle_never_translate_language_menuitem_with_active_translations() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.neverTranslateLanguages", "pl,fr"]], + }); + + const { button } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + info( + 'The document language "es" is not in the alwaysTranslateLanguages pref, ' + + "so the page should be untranslated, in its original form" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-button"), + "Start translating by clicking the translate button." + ); + }); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + const { locale } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + info( + "Simulate clicking never-translate-language in the settings menu, " + + "adding the document language from the neverTranslateLanguages pref" + ); + await openSettingsMenu(); + + await assertIsNeverTranslateLanguage("es", false); + await toggleNeverTranslateLanguage(); + await assertIsNeverTranslateLanguage("es", true); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info( + "The page should still be in its original, untranslated form because " + + "the document language is in the neverTranslateLanguages pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate(SPANISH_PAGE_URL, "Reload the page"); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info( + "The page should still be in its original, untranslated form because " + + "the document language is in the neverTranslateLanguages pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await cleanup(); + } +); + +/** + * Tests the effect of toggling the never-translate-language menuitem on a page where + * where translation is already active via always-translate. + * Checking the box on a translated page should restore the page and hide the button. + * The language should be moved from always-translate to never-translate. + * The button should not appear again for sites in the disabled language. + */ +add_task( + async function test_toggle_never_translate_language_menuitem_with_always_translate_active() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [ + ["browser.translations.alwaysTranslateLanguages", "uk,it"], + ["browser.translations.neverTranslateLanguages", "pl,fr"], + ], + }); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + info( + "Simulate clicking always-translate-language in the settings menu, " + + "adding the document language to the alwaysTranslateLanguages pref" + ); + await openSettingsMenu(); + + await assertIsAlwaysTranslateLanguage("es", false); + await assertIsNeverTranslateLanguage("es", false); + + await toggleAlwaysTranslateLanguage(); + + await assertIsAlwaysTranslateLanguage("es", true); + await assertIsNeverTranslateLanguage("es", false); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + const { locale } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + info( + "Simulate clicking never-translate-language in the settings menu, " + + "adding the document language from the neverTranslateLanguages pref " + + "and removing it from the alwaysTranslateLanguages pref" + ); + await openSettingsMenu(); + + await assertIsAlwaysTranslateLanguage("es", true); + await assertIsNeverTranslateLanguage("es", false); + + await toggleNeverTranslateLanguage(); + + await assertIsAlwaysTranslateLanguage("es", false); + await assertIsNeverTranslateLanguage("es", true); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info( + "The page should still be in its original, untranslated form because " + + "the document language is in the neverTranslateLanguages pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate(SPANISH_PAGE_URL, "Reload the page"); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info( + "The page should still be in its original, untranslated form because " + + "the document language is in the neverTranslateLanguages pref" + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await cleanup(); + } +); diff --git a/browser/components/translations/tests/browser/browser_translations_panel_never_translate_site.js b/browser/components/translations/tests/browser/browser_translations_panel_never_translate_site.js new file mode 100644 index 0000000000..b54b5a4a2c --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_panel_never_translate_site.js @@ -0,0 +1,432 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the effect of toggling the never-translate-site menuitem. + * Checking the box on an untranslated page should immediately hide the button. + * The button should not appear again for sites that share the same content principal + * of the disabled site. + */ +add_task(async function test_toggle_never_translate_site_menuitem() { + const { cleanup, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + permissionsUrls: [SPANISH_PAGE_URL], + }); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + info( + "Translations permissions are currently allowed for this test page " + + "and the page should be untranslated, in its original form." + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + info( + "Simulate clicking never-translate-site in the settings menu, " + + "denying translations permissions for this content window principal" + ); + await openSettingsMenu(); + + await assertIsNeverTranslateSite(SPANISH_PAGE_URL, false); + await toggleNeverTranslateSite(); + await assertIsNeverTranslateSite(SPANISH_PAGE_URL, true); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate(SPANISH_PAGE_URL, "Reload the page"); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate( + SPANISH_PAGE_URL_2, + "Navigate to a Spanish page with the same content principal" + ); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible, because this content principal is denied" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate( + SPANISH_PAGE_URL_DOT_ORG, + "Navigate to a Spanish page with a different content principal" + ); + + await assertTranslationsButton( + { button: false }, + "The translations button should be visible, because this content principal " + + "has not been denied translations permissions" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await cleanup(); +}); + +/** + * Tests the effect of toggling the never-translate-site menuitem on a page where + * where translation is already active. + * Checking the box on a translated page should restore the page and hide the button. + * The button should not appear again for sites that share the same content principal + * of the disabled site. + */ +add_task( + async function test_toggle_never_translate_site_menuitem_with_active_translations() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + permissionsUrls: [SPANISH_PAGE_URL], + }); + + const { button } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + info( + "Translations permissions are currently allowed for this test page " + + "and the page should be untranslated, in its original form." + ); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-button"), + "Start translating by clicking the translate button." + ); + }); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + const { locale } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + info( + "Simulate clicking never-translate-site in the settings menu, " + + "denying translations permissions for this content window principal" + ); + await openSettingsMenu(); + + await assertIsNeverTranslateSite(SPANISH_PAGE_URL, false); + await toggleNeverTranslateSite(); + await assertIsNeverTranslateSite(SPANISH_PAGE_URL, true); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate(SPANISH_PAGE_URL, "Reload the page"); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate( + SPANISH_PAGE_URL_2, + "Navigate to a Spanish page with the same content principal" + ); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible, because this content principal is denied" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate( + SPANISH_PAGE_URL_DOT_ORG, + "Navigate to a Spanish page with a different content principal" + ); + + await assertTranslationsButton( + { button: false }, + "The translations button should be visible, because this content principal " + + "has not been denied translations permissions" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await cleanup(); + } +); + +/** + * Tests the effect of toggling the never-translate-site menuitem on a page where + * where translation is already active via always-translate. + * Checking the box on a translated page should restore the page and hide the button. + * The button should not appear again for sites that share the same content principal + * of the disabled site, and no auto-translation should occur. + * Other sites should still auto-translate for this language. + */ +add_task( + async function test_toggle_never_translate_site_menuitem_with_always_translate_active() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.alwaysTranslateLanguages", "uk,it"]], + permissionsUrls: [SPANISH_PAGE_URL], + }); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + info( + "Simulate clicking always-translate-language in the settings menu, " + + "adding the document language to the alwaysTranslateLanguages pref" + ); + await openSettingsMenu(); + + await assertIsAlwaysTranslateLanguage("es", false); + await assertIsNeverTranslateSite(SPANISH_PAGE_URL, false); + + await toggleAlwaysTranslateLanguage(); + + await assertIsAlwaysTranslateLanguage("es", true); + await assertIsNeverTranslateSite(SPANISH_PAGE_URL, false); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + const { locale } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + info( + "Simulate clicking never-translate-site in the settings menu, " + + "denying translations permissions for this content window principal" + ); + await openSettingsMenu(); + + await assertIsAlwaysTranslateLanguage("es", true); + await assertIsNeverTranslateSite(SPANISH_PAGE_URL, false); + + await toggleNeverTranslateSite(); + + await assertIsAlwaysTranslateLanguage("es", true); + await assertIsNeverTranslateSite(SPANISH_PAGE_URL, true); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate(SPANISH_PAGE_URL, "Reload the page"); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate( + SPANISH_PAGE_URL_2, + "Navigate to a Spanish page with the same content principal" + ); + + await assertTranslationsButton( + { button: false }, + "The translations button should be invisible, because this content principal is denied" + ); + + info("The page should still be in its original, untranslated form"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await navigate( + SPANISH_PAGE_URL_DOT_ORG, + "Navigate to a Spanish page with a different content principal" + ); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + await cleanup(); + } +); diff --git a/browser/components/translations/tests/browser/browser_translations_panel_retry.js b/browser/components/translations/tests/browser/browser_translations_panel_retry.js new file mode 100644 index 0000000000..e9b3f93257 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_panel_retry.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests translating, and then immediately translating to a new language. + */ +add_task(async function test_translations_panel_retry() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + const { button } = await assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-button"), + "Start translating by clicking the translate button." + ); + }); + + await resolveDownloads(1); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Re-opening the popup"); + }); + + info('Switch to language to "fr"'); + const toSelect = getById("translations-panel-to"); + toSelect.value = "fr"; + toSelect.dispatchEvent(new Event("command")); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-button"), + "Re-translate the page by clicking the translate button." + ); + }); + + // This is a pivot language which requires 2 models. + await resolveDownloads(2); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated using the changed languages.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to fr, html]" + ); + }); + + await cleanup(); +}); diff --git a/browser/components/translations/tests/browser/browser_translations_panel_switch_languages.js b/browser/components/translations/tests/browser/browser_translations_panel_switch_languages.js new file mode 100644 index 0000000000..58bcb212d7 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_panel_switch_languages.js @@ -0,0 +1,97 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests switching the language. + */ +add_task(async function test_translations_panel_switch_language() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + const { button } = await assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + const translateButton = getByL10nId("translations-panel-translate-button"); + const fromSelect = getById("translations-panel-from"); + const toSelect = getById("translations-panel-to"); + + ok(!translateButton.disabled, "The translate button starts as enabled"); + is(fromSelect.value, "es", "The from select starts as Spanish"); + is(toSelect.value, "en", "The to select starts as English"); + + info('Switch from language to "es"'); + fromSelect.value = "en"; + fromSelect.dispatchEvent(new Event("command")); + + ok( + translateButton.disabled, + "The translate button is disabled when the languages are the same" + ); + + info('Switch from language back to "es"'); + fromSelect.value = "es"; + fromSelect.dispatchEvent(new Event("command")); + + ok( + !translateButton.disabled, + "When the languages are different it can be translated" + ); + + info("Switch to language to nothing"); + fromSelect.value = ""; + fromSelect.dispatchEvent(new Event("command")); + + ok( + translateButton.disabled, + "The translate button is disabled nothing is selected." + ); + + info('Switch from language to "en"'); + fromSelect.value = "en"; + fromSelect.dispatchEvent(new Event("command")); + + info('Switch to language to "fr"'); + toSelect.value = "fr"; + toSelect.dispatchEvent(new Event("command")); + + ok(!translateButton.disabled, "The translate button can now be used"); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + translateButton, + "Start translating by clicking the translate button." + ); + }); + + await resolveDownloads(1); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated using the changed languages.", + getH1, + "DON QUIJOTE DE LA MANCHA [en to fr, html]" + ); + }); + + await cleanup(); +}); diff --git a/browser/components/translations/tests/browser/browser_translations_telemetry_open_panel.js b/browser/components/translations/tests/browser/browser_translations_telemetry_open_panel.js new file mode 100644 index 0000000000..41aa730863 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_telemetry_open_panel.js @@ -0,0 +1,73 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the telemetry event for opening the translations panel. + */ +add_task(async function test_translations_telemetry_open_panel() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await TestTranslationsTelemetry.assertEvent( + "OpenPanel", + Glean.translationsPanel.open, + { + expectedLength: 0, + } + ); + + const { button } = await assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-cancel"), + "Click the cancel button." + ); + }); + + await TestTranslationsTelemetry.assertEvent( + "OpenPanel", + Glean.translationsPanel.open, + { + expectedLength: 1, + finalValuePredicates: [ + value => value.extra.opened_from === "translationsButton", + ], + } + ); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-cancel"), + "Click the cancel button." + ); + }); + + await TestTranslationsTelemetry.assertEvent( + "OpenPanel", + Glean.translationsPanel.open, + { + expectedLength: 2, + allValuePredicates: [ + value => value.extra.opened_from === "translationsButton", + ], + } + ); + + await cleanup(); +}); diff --git a/browser/components/translations/tests/browser/browser_translations_telemetry_translation_failure.js b/browser/components/translations/tests/browser/browser_translations_telemetry_translation_failure.js new file mode 100644 index 0000000000..1268e6452b --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_telemetry_translation_failure.js @@ -0,0 +1,195 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { PromiseTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PromiseTestUtils.sys.mjs" +); + +/** + * Tests the telemetry event for a manual translation request failure. + */ +add_task( + async function test_translations_telemetry_manual_translation_failure() { + PromiseTestUtils.expectUncaughtRejection( + /Intentionally rejecting downloads./ + ); + + const { cleanup, rejectDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + const { button } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await TestTranslationsTelemetry.assertCounter( + "RequestCount", + Glean.translations.requestsCount, + 0 + ); + await TestTranslationsTelemetry.assertRate( + "ErrorRate", + Glean.translations.errorRate, + { + expectedNumerator: 0, + expectedDenominator: 0, + } + ); + await TestTranslationsTelemetry.assertEvent( + "TranslationRequest", + Glean.translations.translationRequest, + { + expectedLength: 0, + } + ); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-button"), + "Start translating by clicking the translate button." + ); + }); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await rejectDownloads(1); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await TestTranslationsTelemetry.assertCounter( + "RequestCount", + Glean.translations.requestsCount, + 1 + ); + await TestTranslationsTelemetry.assertRate( + "ErrorRate", + Glean.translations.errorRate, + { + expectedNumerator: 1, + expectedDenominator: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + "Error", + Glean.translations.error, + { + expectedLength: 1, + finalValuePredicates: [ + value => + value.extra.reason === "Error: Intentionally rejecting downloads.", + ], + } + ); + await TestTranslationsTelemetry.assertEvent( + "TranslationRequest", + Glean.translations.translationRequest, + { + expectedLength: 1, + finalValuePredicates: [ + value => value.extra.from_language === "es", + value => value.extra.to_language === "en", + value => value.extra.auto_translate === "false", + ], + } + ); + + await cleanup(); + } +); + +/** + * Tests the telemetry event for an automatic translation request failure. + */ +add_task(async function test_translations_telemetry_auto_translation_failure() { + PromiseTestUtils.expectUncaughtRejection( + /Intentionally rejecting downloads./ + ); + + const { cleanup, rejectDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.alwaysTranslateLanguages", "es"]], + }); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await rejectDownloads(1); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await TestTranslationsTelemetry.assertCounter( + "RequestCount", + Glean.translations.requestsCount, + 1 + ); + await TestTranslationsTelemetry.assertRate( + "ErrorRate", + Glean.translations.errorRate, + { + expectedNumerator: 1, + expectedDenominator: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + "Error", + Glean.translations.error, + { + expectedLength: 1, + finalValuePredicates: [ + value => + value.extra.reason === "Error: Intentionally rejecting downloads.", + ], + } + ); + await TestTranslationsTelemetry.assertEvent( + "TranslationRequest", + Glean.translations.translationRequest, + { + expectedLength: 1, + finalValuePredicates: [ + value => value.extra.from_language === "es", + value => value.extra.to_language === "en", + value => value.extra.auto_translate === "true", + ], + } + ); + + await cleanup(); +}); diff --git a/browser/components/translations/tests/browser/browser_translations_telemetry_translation_request.js b/browser/components/translations/tests/browser/browser_translations_telemetry_translation_request.js new file mode 100644 index 0000000000..ce22615630 --- /dev/null +++ b/browser/components/translations/tests/browser/browser_translations_telemetry_translation_request.js @@ -0,0 +1,173 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the telemetry event for a manual translation request. + */ +add_task(async function test_translations_telemetry_manual_translation() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + const { button } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is in Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + + await TestTranslationsTelemetry.assertCounter( + "RequestCount", + Glean.translations.requestsCount, + 0 + ); + await TestTranslationsTelemetry.assertRate( + "ErrorRate", + Glean.translations.errorRate, + { + expectedNumerator: 0, + expectedDenominator: 0, + } + ); + await TestTranslationsTelemetry.assertEvent( + "TranslationRequest", + Glean.translations.translationRequest, + { + expectedLength: 0, + } + ); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + await waitForTranslationsPopupEvent("popuphidden", () => { + click( + getByL10nId("translations-panel-translate-button"), + "Start translating by clicking the translate button." + ); + }); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + const { locale } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + await TestTranslationsTelemetry.assertCounter( + "RequestCount", + Glean.translations.requestsCount, + 1 + ); + await TestTranslationsTelemetry.assertRate( + "ErrorRate", + Glean.translations.errorRate, + { + expectedNumerator: 0, + expectedDenominator: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + "TranslationRequest", + Glean.translations.translationRequest, + { + expectedLength: 1, + finalValuePredicates: [ + value => value.extra.from_language === "es", + value => value.extra.to_language === "en", + value => value.extra.auto_translate === "false", + ], + } + ); + + await cleanup(); +}); + +/** + * Tests the telemetry event for an automatic translation request. + */ +add_task(async function test_translations_telemetry_auto_translation() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.alwaysTranslateLanguages", "es"]], + }); + + await assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await resolveDownloads(1); + + const { locale } = await assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + is(locale.innerText, "en", "The English language tag is shown."); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The pages H1 is translated.", + getH1, + "DON QUIJOTE DE LA MANCHA [es to en, html]" + ); + }); + + await TestTranslationsTelemetry.assertCounter( + "RequestCount", + Glean.translations.requestsCount, + 1 + ); + await TestTranslationsTelemetry.assertRate( + "ErrorRate", + Glean.translations.errorRate, + { + expectedNumerator: 0, + expectedDenominator: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + "TranslationRequest", + Glean.translations.translationRequest, + { + expectedLength: 1, + finalValuePredicates: [ + value => value.extra.from_language === "es", + value => value.extra.to_language === "en", + value => value.extra.auto_translate === "true", + ], + } + ); + + await cleanup(); +}); diff --git a/browser/components/translations/tests/browser/head.js b/browser/components/translations/tests/browser/head.js new file mode 100644 index 0000000000..56839971b7 --- /dev/null +++ b/browser/components/translations/tests/browser/head.js @@ -0,0 +1,348 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/toolkit/components/translations/tests/browser/shared-head.js", + this +); + +/** + * Assert some property about the translations button. + * + * @param {Record} visibleAssertions + * @param {string} message The message for the assertion. + * @returns {HTMLElement} + */ +async function assertTranslationsButton(visibleAssertions, message) { + const elements = { + button: document.getElementById("translations-button"), + icon: document.getElementById("translations-button-icon"), + circleArrows: document.getElementById("translations-button-circle-arrows"), + locale: document.getElementById("translations-button-locale"), + }; + + for (const [name, element] of Object.entries(elements)) { + if (!element) { + throw new Error("Could not find the " + name); + } + } + + try { + // Test that the visibilities match. + await TestUtils.waitForCondition(() => { + for (const [name, visible] of Object.entries(visibleAssertions)) { + if (elements[name].hidden === visible) { + return false; + } + } + return true; + }, message); + } catch (error) { + // On a mismatch, report it. + for (const [name, expected] of Object.entries(visibleAssertions)) { + is(!elements[name].hidden, expected, `Visibility for "${name}"`); + } + } + + ok(true, message); + + return elements; +} + +/** + * A convenience function to open the settings menu of the + * translations panel. Fails the test if the menu cannot be opened. + */ +async function openSettingsMenu() { + const { button } = await assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await waitForTranslationsPopupEvent("popupshown", () => { + click(button, "Opening the popup"); + }); + + const gearIcon = getByL10nId("translations-panel-settings-button"); + click(gearIcon, "Open the settings menu"); +} + +/** + * Simulates the effect of clicking the always-translate-language menuitem. + * Requires that the settings menu of the translations panel is open, + * otherwise the test will fail. + */ +async function toggleAlwaysTranslateLanguage() { + const alwaysTranslateLanguage = getByL10nId( + "translations-panel-settings-always-translate-language" + ); + info("Toggle the always-translate-language menuitem"); + await alwaysTranslateLanguage.doCommand(); +} + +/** + * Simulates the effect of clicking the never-translate-language menuitem. + * Requires that the settings menu of the translations panel is open, + * otherwise the test will fail. + */ +async function toggleNeverTranslateLanguage() { + const neverTranslateLanguage = getByL10nId( + "translations-panel-settings-never-translate-language" + ); + info("Toggle the never-translate-language menuitem"); + await neverTranslateLanguage.doCommand(); +} + +/** + * Simulates the effect of clicking the never-translate-site menuitem. + * Requires that the settings menu of the translations panel is open, + * otherwise the test will fail. + */ +async function toggleNeverTranslateSite() { + const neverTranslateSite = getByL10nId( + "translations-panel-settings-never-translate-site" + ); + info("Toggle the never-translate-site menuitem"); + await neverTranslateSite.doCommand(); +} + +/** + * Asserts that the always-translate-language checkbox matches the expected checked state. + * + * @param {string} langTag - A BCP-47 language tag + * @param {boolean} expectChecked - Whether the checkbox should be checked + */ +async function assertIsAlwaysTranslateLanguage(langTag, expectChecked) { + await assertCheckboxState( + "translations-panel-settings-always-translate-language", + expectChecked + ); +} + +/** + * Asserts that the never-translate-language checkbox matches the expected checked state. + * + * @param {string} langTag - A BCP-47 language tag + * @param {boolean} expectChecked - Whether the checkbox should be checked + */ +async function assertIsNeverTranslateLanguage(langTag, expectChecked) { + await assertCheckboxState( + "translations-panel-settings-never-translate-language", + expectChecked + ); +} + +/** + * Asserts that the never-translate-site checkbox matches the expected checked state. + * + * @param {string} url - The url of a website + * @param {boolean} expectChecked - Whether the checkbox should be checked + */ +async function assertIsNeverTranslateSite(url, expectChecked) { + await assertCheckboxState( + "translations-panel-settings-never-translate-site", + expectChecked + ); +} + +/** + * Asserts that the state of a checkbox with a given dataL10nId is + * checked or not, based on the value of expected being true or false. + * + * @param {string} dataL10nId - The data-l10n-id of the checkbox. + * @param {boolean} expectChecked - Whether the checkbox should be checked. + */ +async function assertCheckboxState(dataL10nId, expectChecked) { + const menuItems = getAllByL10nId(dataL10nId); + for (const menuItem of menuItems) { + await TestUtils.waitForCondition( + () => + menuItem.getAttribute("checked") === (expectChecked ? "true" : "false"), + "Waiting for checkbox state" + ); + is( + menuItem.getAttribute("checked"), + expectChecked ? "true" : "false", + `Should match expected checkbox state for ${dataL10nId}` + ); + } +} + +/** + * Navigate to a URL and indicate a message as to why. + */ +async function navigate(url, message) { + info(message); + + // Load a blank page first to ensure that tests don't hang. + // I don't know why this is needed, but it appears to be necessary. + BrowserTestUtils.loadURIString(gBrowser.selectedBrowser, BLANK_PAGE); + await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + + BrowserTestUtils.loadURIString(gBrowser.selectedBrowser, url); + await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); +} + +/** + * Add a tab to the page + * + * @param {string} url + */ +async function addTab(url) { + info(`Adding tab for ` + url); + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + url, + true // Wait for laod + ); + return { + tab, + removeTab() { + BrowserTestUtils.removeTab(tab); + }, + }; +} + +async function switchTab(tab) { + info("Switching tabs"); + await BrowserTestUtils.switchTab(gBrowser, tab); +} + +function click(button, message) { + info(message); + EventUtils.synthesizeMouseAtCenter(button, {}); +} + +/** + * @param {Element} element + * @returns {boolean} + */ +function isVisible(element) { + const win = element.ownerDocument.ownerGlobal; + const { visibility, display } = win.getComputedStyle(element); + return visibility === "visible" && display !== "none"; +} + +/** + * Get an element by its l10n id, as this is a user-visible way to find an element. + * The `l10nId` represents the text that a user would actually see. + * + * @param {string} l10nId + * @param {Document} doc + * @returns {Element} + */ +function getByL10nId(l10nId, doc = document) { + const elements = doc.querySelectorAll(`[data-l10n-id="${l10nId}"]`); + if (elements.length === 0) { + throw new Error("Could not find the element by l10n id: " + l10nId); + } + for (const element of elements) { + if (isVisible(element)) { + return element; + } + } + throw new Error("The element is not visible in the DOM: " + l10nId); +} + +/** + * Get all elements that match the l10n id. + * + * @param {string} l10nId + * @param {Document} doc + * @returns {Element} + */ +function getAllByL10nId(l10nId, doc = document) { + const elements = doc.querySelectorAll(`[data-l10n-id="${l10nId}"]`); + if (elements.length === 0) { + throw new Error("Could not find the element by l10n id: " + l10nId); + } + return elements; +} + +/** + * @param {string} id + * @param {Document} [doc] + * @returns {Element} + */ +function getById(id, doc = document) { + const element = doc.getElementById(id); + if (!element) { + throw new Error("Could not find the element by id: #" + id); + } + if (isVisible(element)) { + return element; + } + throw new Error("The element is not visible in the DOM: #" + id); +} + +/** + * A non-throwing version of `getByL10nId`. + * + * @param {string} l10nId + * @returns {Element | null} + */ +function maybeGetByL10nId(l10nId, doc = document) { + const selector = `[data-l10n-id="${l10nId}"]`; + const elements = doc.querySelectorAll(selector); + for (const element of elements) { + if (isVisible(element)) { + return element; + } + } + return null; +} + +/** + * XUL popups will fire the popupshown and popuphidden events. These will fire for + * any type of popup in the browser. This function waits for one of those events, and + * checks that the viewId of the popup is PanelUI-profiler + * + * @param {"popupshown" | "popuphidden"} eventName + * @param {Function} callback + * @returns {Promise} + */ +async function waitForTranslationsPopupEvent(eventName, callback) { + const panel = document.getElementById("translations-panel"); + if (!panel) { + throw new Error("Unable to find the translations panel element."); + } + const promise = BrowserTestUtils.waitForEvent(panel, eventName); + callback(); + info("Waiting for the translations panel popup to be shown"); + await promise; + // Wait a single tick on the event loop. + await new Promise(resolve => setTimeout(resolve, 0)); +} + +/** + * When switching between between views in the popup panel, wait for the view to + * be fully shown. + * + * @param {Function} callback + */ +async function waitForViewShown(callback) { + const panel = document.getElementById("translations-panel"); + if (!panel) { + throw new Error("Unable to find the translations panel element."); + } + const promise = BrowserTestUtils.waitForEvent(panel, "ViewShown"); + callback(); + info("Waiting for the translations panel view to be shown"); + await promise; + await new Promise(resolve => setTimeout(resolve, 0)); +} + +const ENGLISH_PAGE_URL = TRANSLATIONS_TESTER_EN; +const SPANISH_PAGE_URL = TRANSLATIONS_TESTER_ES; +const SPANISH_PAGE_URL_2 = TRANSLATIONS_TESTER_ES_2; +const SPANISH_PAGE_URL_DOT_ORG = TRANSLATIONS_TESTER_ES_DOT_ORG; +const LANGUAGE_PAIRS = [ + { fromLang: "es", toLang: "en", isBeta: false }, + { fromLang: "en", toLang: "es", isBeta: false }, + { fromLang: "fr", toLang: "en", isBeta: false }, + { fromLang: "en", toLang: "fr", isBeta: false }, + { fromLang: "en", toLang: "uk", isBeta: true }, + { fromLang: "uk", toLang: "en", isBeta: true }, +]; -- cgit v1.2.3