From 1d509e30a9e1864cedc8135936b7ac40f20535c2 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Tue, 21 Oct 2025 16:03:13 +0200 Subject: [PATCH 1/3] test: Import some mochitests from firefox, b=no-bug, c=tests, scripts, tabs --- .prettierignore | 2 + .../browser/preferences/zen-preferences.ftl | 3 + scripts/import_external_tests.py | 115 + scripts/run_tests.py | 5 +- src/zen/tests/manifest.toml | 26 + src/zen/tests/mochitests/moz.build | 15 + .../mochitests/reportbrokensite/browser.toml | 49 + .../browser_addon_data_sent.js | 99 + .../browser_antitracking_data_sent.js | 117 + .../reportbrokensite/browser_back_buttons.js | 34 + .../browser_error_messages.js | 64 + .../browser_experiment_data_sent.js | 88 + .../browser_keyboard_navigation.js | 107 + .../browser_parent_menuitems.js | 96 + .../browser_prefers_contrast.js | 56 + .../browser_reason_dropdown.js | 156 + .../reportbrokensite/browser_report_send.js | 79 + .../browser_send_more_info.js | 65 + .../reportbrokensite/browser_tab_key_order.js | 132 + .../browser_tab_switch_handling.js | 81 + .../browser_webcompat.com_fallback.js | 45 + .../reportbrokensite/example_report_page.html | 22 + .../tests/mochitests/reportbrokensite/head.js | 897 ++++ .../tests/mochitests/reportbrokensite/send.js | 330 ++ .../sendMoreInfoTestEndpoint.html | 27 + .../reportbrokensite/send_more_info.js | 305 ++ .../mochitests/safebrowsing/browser.toml | 14 + .../safebrowsing/browser_bug400731.js | 65 + .../safebrowsing/browser_bug415846.js | 98 + .../browser_mixedcontent_aboutblocked.js | 47 + .../safebrowsing/browser_whitelisted.js | 46 + .../mochitests/safebrowsing/empty_file.html | 1 + src/zen/tests/mochitests/safebrowsing/head.js | 103 + src/zen/tests/mochitests/shell/browser.toml | 101 + .../tests/mochitests/shell/browser_1119088.js | 179 + .../tests/mochitests/shell/browser_420786.js | 101 + .../tests/mochitests/shell/browser_633221.js | 11 + .../shell/browser_createWindowsShortcut.js | 218 + .../shell/browser_doesAppNeedPin.js | 54 + .../shell/browser_headless_screenshot_1.js | 74 + .../shell/browser_headless_screenshot_2.js | 48 + .../shell/browser_headless_screenshot_3.js | 59 + .../shell/browser_headless_screenshot_4.js | 31 + ...rowser_headless_screenshot_cross_origin.js | 9 + .../browser_headless_screenshot_redirect.js | 14 + .../mochitests/shell/browser_processAUMID.js | 27 + .../shell/browser_setDefaultBrowser.js | 239 + .../shell/browser_setDefaultPDFHandler.js | 279 ++ .../browser_setDesktopBackgroundPreview.js | 93 + .../shell/gtest/LimitedAccessFeatureTests.cpp | 40 + .../mochitests/shell/gtest/ShellLinkTests.cpp | 54 + .../tests/mochitests/shell/gtest/moz.build | 15 + src/zen/tests/mochitests/shell/head.js | 159 + src/zen/tests/mochitests/shell/headless.html | 6 + .../shell/headless_cross_origin.html | 7 + .../mochitests/shell/headless_iframe.html | 6 + .../mochitests/shell/headless_redirect.html | 0 .../shell/headless_redirect.html^headers^ | 2 + .../mochitests/shell/mac_desktop_image.py | 168 + .../test_macOS_showSecurityPreferences.js | 40 + .../tests/mochitests/shell/unit/xpcshell.toml | 6 + .../tests/mochitests/tooltiptext/browser.toml | 17 + .../tooltiptext/browser_bug329212.js | 48 + ...owser_bug331772_xul_tooltiptext_in_html.js | 30 + .../tooltiptext/browser_bug561623.js | 33 + .../tooltiptext/browser_bug581947.js | 107 + .../browser_input_file_tooltips.js | 131 + .../tooltiptext/browser_nac_tooltip.js | 66 + .../tooltiptext/browser_shadow_dom_tooltip.js | 166 + .../mochitests/tooltiptext/title_test.svg | 59 + .../tooltiptext/xul_tooltiptext.xhtml | 12 + .../mochitests/translations/browser.toml | 285 ++ ...preferences_manage_downloaded_languages.js | 225 + ...ces_settings_always_translate_languages.js | 97 + ...nces_settings_download_languages_all_ui.js | 159 + ...es_settings_download_languages_error_ui.js | 173 + ...ferences_settings_download_languages_ui.js | 117 + ...nces_settings_never_translate_languages.js | 89 + ...ferences_settings_never_translate_sites.js | 124 + ...nslations_about_preferences_settings_ui.js | 462 ++ ...t_preferences_settings_ui_keyboard_a11y.js | 635 +++ ...tions_about_preferences_settings_ui_tab.js | 56 + ...l_page_translate_with_lexical_shortlist.js | 100 + ...age_translate_without_lexical_shortlist.js | 100 + ...ns_full_page_intersection_content_eager.js | 156 + ...lations_full_page_intersection_find_bar.js | 256 + ...section_find_bar_move_tab_to_new_window.js | 267 + ...ll_page_intersection_find_bar_multi_tab.js | 256 + ...ranslations_full_page_intersection_lazy.js | 161 + ...ge_intersection_mutations_content_eager.js | 247 + ...s_full_page_intersection_mutations_lazy.js | 235 + ...slations_full_page_language_id_behavior.js | 298 ++ ...ations_full_page_move_tab_to_new_window.js | 68 + ...er_translations_full_page_moz_extension.js | 79 + ...translations_full_page_multiple_windows.js | 65 + ...translations_full_page_panel_a11y_focus.js | 34 + ...anel_always_translate_language_bad_data.js | 41 + ...e_panel_always_translate_language_basic.js | 81 + ..._panel_always_translate_language_manual.js | 88 + ...panel_always_translate_language_restore.js | 109 + ...panel_app_menu_never_translate_language.js | 42 + ...age_panel_app_menu_never_translate_site.js | 151 + ...ll_page_panel_auto_translate_error_view.js | 88 + ..._page_panel_auto_translate_revisit_view.js | 92 + ...ser_translations_full_page_panel_basics.js | 69 + ...ser_translations_full_page_panel_button.js | 77 + ...ser_translations_full_page_panel_cancel.js | 29 + ...tions_full_page_panel_change_app_locale.js | 74 + ...slate_language_with_translations_active.js | 159 + ...ate_language_with_translations_inactive.js | 99 + ..._panel_close_panel_never_translate_site.js | 170 + ...slations_full_page_panel_engine_destroy.js | 64 + ..._full_page_panel_engine_destroy_pending.js | 77 + ...ions_full_page_panel_engine_unsupported.js | 59 + ...r_translations_full_page_panel_firstrun.js | 55 + ...ations_full_page_panel_firstrun_revisit.js | 64 + ..._full_page_panel_flip_lexical_shortlist.js | 146 + ...er_translations_full_page_panel_fuzzing.js | 243 + ...owser_translations_full_page_panel_gear.js | 34 + ...anslations_full_page_panel_init_failure.js | 25 + ..._panel_modify_available_language_models.js | 148 + ...ull_page_panel_never_translate_language.js | 198 + ...ns_full_page_panel_never_translate_site.js | 261 + ...ll_page_panel_never_translate_site_auto.js | 115 + ...l_page_panel_never_translate_site_basic.js | 64 + ..._page_panel_never_translate_site_manual.js | 89 + ...wser_translations_full_page_panel_retry.js | 59 + ...ranslations_full_page_panel_script_tags.js | 153 + ...ll_page_panel_settings_unsupported_lang.js | 76 + ...ations_full_page_panel_switch_languages.js | 79 + ...e_panel_switch_tabs_before_engine_ready.js | 300 ++ ...anel_target_language_persists_on_reopen.js | 46 + ...ations_full_page_panel_unsupported_lang.js | 33 + ...page_panel_weblanguage_differs_from_app.js | 42 + ...wser_translations_full_page_reader_mode.js | 141 + ...ions_full_page_telemetry_auto_translate.js | 127 + ...translations_full_page_telemetry_basics.js | 93 + ...slations_full_page_telemetry_open_panel.js | 93 + ...ns_full_page_telemetry_panel_auto_offer.js | 87 + ...age_telemetry_panel_auto_offer_settings.js | 120 + ...lations_full_page_telemetry_retranslate.js | 164 + ...ns_full_page_telemetry_switch_languages.js | 192 + ...full_page_telemetry_translation_failure.js | 197 + ...full_page_telemetry_translation_request.js | 157 + ...ns_full_page_telemetry_unsupported_lang.js | 212 + .../browser_translations_perf_es_en.js | 109 + ...s_recent_language_memory_auto_translate.js | 82 + ...nt_language_memory_full_page_and_select.js | 103 + ...emory_full_page_and_select_multi_window.js | 135 + ..._language_memory_full_page_multi_window.js | 127 + ...memory_full_page_multi_window_multi_tab.js | 321 ++ ...cent_language_memory_full_page_navigate.js | 104 + ...t_language_memory_full_page_retranslate.js | 85 + ..._select_context_menu_engine_unsupported.js | 35 + ...ns_select_context_menu_feature_disabled.js | 114 + ...lect_context_menu_preferred_app_locales.js | 106 + ...text_menu_preferred_language_edge_cases.js | 74 + ...ct_context_menu_preferred_web_languages.js | 65 + ...menu_with_full_page_translations_active.js | 174 + ...ions_select_context_menu_with_hyperlink.js | 139 + ...lect_context_menu_with_no_text_selected.js | 37 + ..._select_context_menu_with_text_selected.js | 76 + ...er_translations_select_panel_a11y_utils.js | 87 + ...slations_select_panel_change_app_locale.js | 74 + ...nslations_select_panel_close_on_new_tab.js | 46 + ...r_translations_select_panel_copy_button.js | 95 + ..._translations_select_panel_engine_cache.js | 59 + ...s_select_panel_fallback_to_doc_language.js | 89 + ...ons_select_panel_flip_lexical_shortlist.js | 104 + ..._translations_select_panel_init_failure.js | 119 + ..._panel_modify_available_language_models.js | 163 + .../browser_translations_select_panel_pdf.js | 42 + ...r_translations_select_panel_reader_mode.js | 44 + ...retranslate_on_change_language_directly.js | 70 + ...e_on_change_language_from_dropdown_menu.js | 68 + ...r_translations_select_panel_script_tags.js | 126 + ..._panel_select_current_language_directly.js | 71 + ...ect_current_language_from_dropdown_menu.js | 71 + ...ect_same_from_and_to_languages_directly.js | 66 + ...rom_and_to_languages_from_dropdown_menu.js | 66 + ...translations_select_panel_settings_menu.js | 70 + ...select_panel_translate_full_page_button.js | 87 + ...l_translate_on_change_language_directly.js | 67 + ...e_on_change_language_from_dropdown_menu.js | 67 + ...change_language_multiple_times_directly.js | 98 + ...guage_multiple_times_from_dropdown_menu.js | 99 + ...slations_select_panel_translate_on_open.js | 86 + ...tion_failure_after_unsupported_language.js | 55 + ...elect_panel_translation_failure_on_open.js | 92 + ...anel_translation_failure_on_retranslate.js | 128 + ...tions_select_panel_unsupported_language.js | 163 + ...elemetry_change_both_languages_together.js | 333 ++ ...lemetry_change_languages_multiple_times.js | 374 ++ ...t_telemetry_init_failure_ui_then_cancel.js | 102 + ..._telemetry_init_failure_ui_then_succeed.js | 122 + ...lect_telemetry_keypresses_cancel_button.js | 174 + ...select_telemetry_keypresses_copy_button.js | 88 + ...select_telemetry_keypresses_done_button.js | 180 + ...ct_telemetry_keypresses_settings_button.js | 87 + ...t_telemetry_keypresses_translate_button.js | 121 + ...y_keypresses_translate_full_page_button.js | 118 + ...eypresses_try_again_button_init_failure.js | 106 + ...es_try_again_button_translation_failure.js | 110 + ...ranslations_select_telemetry_multi_page.js | 138 + ...ranslations_select_telemetry_primary_ui.js | 306 ++ ...slations_select_telemetry_settings_menu.js | 98 + ...etry_translation_failure_ui_then_cancel.js | 146 + ...try_translation_failure_ui_then_succeed.js | 136 + ...lure_with_full_page_translations_active.js | 212 + ...cess_with_full_page_translations_active.js | 249 + ...elect_telemetry_unsupported_language_ui.js | 162 + src/zen/tests/mochitests/translations/head.js | 4291 +++++++++++++++++ .../mochitests/translations/perftest.toml | 9 + src/zen/tests/moz.build | 4 + 214 files changed, 28247 insertions(+), 1 deletion(-) create mode 100644 scripts/import_external_tests.py create mode 100644 src/zen/tests/manifest.toml create mode 100644 src/zen/tests/mochitests/moz.build create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser.toml create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_addon_data_sent.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_antitracking_data_sent.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_back_buttons.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_error_messages.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_experiment_data_sent.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_keyboard_navigation.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_parent_menuitems.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_prefers_contrast.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_reason_dropdown.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_report_send.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_send_more_info.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_tab_key_order.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_tab_switch_handling.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_webcompat.com_fallback.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/example_report_page.html create mode 100644 src/zen/tests/mochitests/reportbrokensite/head.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/send.js create mode 100644 src/zen/tests/mochitests/reportbrokensite/sendMoreInfoTestEndpoint.html create mode 100644 src/zen/tests/mochitests/reportbrokensite/send_more_info.js create mode 100644 src/zen/tests/mochitests/safebrowsing/browser.toml create mode 100644 src/zen/tests/mochitests/safebrowsing/browser_bug400731.js create mode 100644 src/zen/tests/mochitests/safebrowsing/browser_bug415846.js create mode 100644 src/zen/tests/mochitests/safebrowsing/browser_mixedcontent_aboutblocked.js create mode 100644 src/zen/tests/mochitests/safebrowsing/browser_whitelisted.js create mode 100644 src/zen/tests/mochitests/safebrowsing/empty_file.html create mode 100644 src/zen/tests/mochitests/safebrowsing/head.js create mode 100644 src/zen/tests/mochitests/shell/browser.toml create mode 100644 src/zen/tests/mochitests/shell/browser_1119088.js create mode 100644 src/zen/tests/mochitests/shell/browser_420786.js create mode 100644 src/zen/tests/mochitests/shell/browser_633221.js create mode 100644 src/zen/tests/mochitests/shell/browser_createWindowsShortcut.js create mode 100644 src/zen/tests/mochitests/shell/browser_doesAppNeedPin.js create mode 100644 src/zen/tests/mochitests/shell/browser_headless_screenshot_1.js create mode 100644 src/zen/tests/mochitests/shell/browser_headless_screenshot_2.js create mode 100644 src/zen/tests/mochitests/shell/browser_headless_screenshot_3.js create mode 100644 src/zen/tests/mochitests/shell/browser_headless_screenshot_4.js create mode 100644 src/zen/tests/mochitests/shell/browser_headless_screenshot_cross_origin.js create mode 100644 src/zen/tests/mochitests/shell/browser_headless_screenshot_redirect.js create mode 100644 src/zen/tests/mochitests/shell/browser_processAUMID.js create mode 100644 src/zen/tests/mochitests/shell/browser_setDefaultBrowser.js create mode 100644 src/zen/tests/mochitests/shell/browser_setDefaultPDFHandler.js create mode 100644 src/zen/tests/mochitests/shell/browser_setDesktopBackgroundPreview.js create mode 100644 src/zen/tests/mochitests/shell/gtest/LimitedAccessFeatureTests.cpp create mode 100644 src/zen/tests/mochitests/shell/gtest/ShellLinkTests.cpp create mode 100644 src/zen/tests/mochitests/shell/gtest/moz.build create mode 100644 src/zen/tests/mochitests/shell/head.js create mode 100644 src/zen/tests/mochitests/shell/headless.html create mode 100644 src/zen/tests/mochitests/shell/headless_cross_origin.html create mode 100644 src/zen/tests/mochitests/shell/headless_iframe.html create mode 100644 src/zen/tests/mochitests/shell/headless_redirect.html create mode 100644 src/zen/tests/mochitests/shell/headless_redirect.html^headers^ create mode 100755 src/zen/tests/mochitests/shell/mac_desktop_image.py create mode 100644 src/zen/tests/mochitests/shell/unit/test_macOS_showSecurityPreferences.js create mode 100644 src/zen/tests/mochitests/shell/unit/xpcshell.toml create mode 100644 src/zen/tests/mochitests/tooltiptext/browser.toml create mode 100644 src/zen/tests/mochitests/tooltiptext/browser_bug329212.js create mode 100644 src/zen/tests/mochitests/tooltiptext/browser_bug331772_xul_tooltiptext_in_html.js create mode 100644 src/zen/tests/mochitests/tooltiptext/browser_bug561623.js create mode 100644 src/zen/tests/mochitests/tooltiptext/browser_bug581947.js create mode 100644 src/zen/tests/mochitests/tooltiptext/browser_input_file_tooltips.js create mode 100644 src/zen/tests/mochitests/tooltiptext/browser_nac_tooltip.js create mode 100644 src/zen/tests/mochitests/tooltiptext/browser_shadow_dom_tooltip.js create mode 100644 src/zen/tests/mochitests/tooltiptext/title_test.svg create mode 100644 src/zen/tests/mochitests/tooltiptext/xul_tooltiptext.xhtml create mode 100644 src/zen/tests/mochitests/translations/browser.toml create mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_manage_downloaded_languages.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_always_translate_languages.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_all_ui.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_error_ui.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_ui.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_languages.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_sites.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_keyboard_a11y.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_tab.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_with_lexical_shortlist.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_without_lexical_shortlist.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_content_eager.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_move_tab_to_new_window.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_multi_tab.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_lazy.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_content_eager.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_lazy.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_language_id_behavior.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_move_tab_to_new_window.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_moz_extension.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_multiple_windows.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_a11y_focus.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_bad_data.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_basic.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_manual.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_restore.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_language.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_site.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_error_view.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_revisit_view.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_basics.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_button.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_cancel.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_change_app_locale.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_active.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_inactive.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_site.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy_pending.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_unsupported.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun_revisit.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_flip_lexical_shortlist.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_fuzzing.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_gear.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_init_failure.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_modify_available_language_models.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_language.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_auto.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_basic.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_manual.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_retry.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_script_tags.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_settings_unsupported_lang.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_languages.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_tabs_before_engine_ready.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_target_language_persists_on_reopen.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_unsupported_lang.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_weblanguage_differs_from_app.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_reader_mode.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_auto_translate.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_basics.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_open_panel.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer_settings.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_retranslate.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_switch_languages.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_failure.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_request.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_unsupported_lang.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_perf_es_en.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_auto_translate.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select_multi_window.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window_multi_tab.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_navigate.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_retranslate.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_engine_unsupported.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_feature_disabled.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_app_locales.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_language_edge_cases.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_web_languages.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_full_page_translations_active.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_hyperlink.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_no_text_selected.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_text_selected.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_a11y_utils.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_change_app_locale.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_close_on_new_tab.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_copy_button.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_engine_cache.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_fallback_to_doc_language.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_flip_lexical_shortlist.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_init_failure.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_modify_available_language_models.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_pdf.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_reader_mode.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_directly.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_script_tags.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_directly.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_from_dropdown_menu.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_directly.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_from_dropdown_menu.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_settings_menu.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_full_page_button.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_directly.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_from_dropdown_menu.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_directly.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_from_dropdown_menu.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_open.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_after_unsupported_language.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_open.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_retranslate.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_unsupported_language.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_both_languages_together.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_languages_multiple_times.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_cancel.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_succeed.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_cancel_button.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_copy_button.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_done_button.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_settings_button.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_button.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_full_page_button.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_init_failure.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_translation_failure.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_multi_page.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_primary_ui.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_settings_menu.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_cancel.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_succeed.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_with_full_page_translations_active.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_success_with_full_page_translations_active.js create mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_unsupported_language_ui.js create mode 100644 src/zen/tests/mochitests/translations/head.js create mode 100644 src/zen/tests/mochitests/translations/perftest.toml diff --git a/.prettierignore b/.prettierignore index af7e85d384..df0ad852b6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -17,6 +17,8 @@ engine/ surfer.json +src/zen/tests/mochitests/* + src/browser/app/profile/*.js pnpm-lock.yaml diff --git a/locales/en-US/browser/browser/preferences/zen-preferences.ftl b/locales/en-US/browser/browser/preferences/zen-preferences.ftl index 43f48460d7..1a262658ef 100644 --- a/locales/en-US/browser/browser/preferences/zen-preferences.ftl +++ b/locales/en-US/browser/browser/preferences/zen-preferences.ftl @@ -179,6 +179,9 @@ category-zen-CKS = .tooltiptext = { pane-zen-CKS-title } pane-settings-CKS-title = { -brand-short-name } Keyboard Shortcuts +category-zen-marketplace = + .tooltiptext = Zen Mods + zen-settings-CKS-header = Customize your keyboard shortcuts zen-settings-CKS-description = Change the default keyboard shortcuts to your liking and improve your browsing experience diff --git a/scripts/import_external_tests.py b/scripts/import_external_tests.py new file mode 100644 index 0000000000..0808a2abc9 --- /dev/null +++ b/scripts/import_external_tests.py @@ -0,0 +1,115 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import os +import tomllib +import shutil + +BASE_PATH = os.path.join("src", "zen", "tests") +EXTERNAL_TESTS_MANIFEST = os.path.join(BASE_PATH, "manifest.toml") +EXTERNAL_TESTS_OUTPUT = os.path.join(BASE_PATH, "mochitests") + +FILE_PREFIX = """ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# This file is autogenerated by scripts/import_external_tests.py +# Do not edit manually. + +BROWSER_CHROME_MANIFESTS += [ +""" + +FILE_SUFFIX = "]" + +def get_tests_manifest(): + with open(EXTERNAL_TESTS_MANIFEST, "rb") as f: + return tomllib.load(f) + +def die_with_error(message): + print(f"ERROR: {message}") + exit(1) + +def validate_tests_path(path, files, ignore_list): + for ignore in ignore_list: + if ignore not in files: + die_with_error(f"Ignore file '{ignore}' not found in tests folder '{path}'") + if "browser.toml" not in files or "browser.js" in ignore_list: + die_with_error(f"'browser.toml' not found in tests folder '{path}'") + +def disable_and_replace_manifest(manifest, output_path): + toml_file = os.path.join(output_path, "browser.toml") + disabled_tests = manifest.get("disable", []) + with open(toml_file, "r") as f: + data = f.read() + for test in disabled_tests: + segment = f'["{test}"]' + if segment not in data: + die_with_error(f"Could not disable test '{test}' as it was not found in '{toml_file}'") + replace_with = f'["{test}"]\ndisabled="Disabled by import_external_tests.py"' + data = data.replace(segment, replace_with) + for replacement in manifest.get("replace-manifest", {}).keys(): + if replacement not in data: + die_with_error(f"Could not replace manifest entry '{replacement}' as it was not found in '{toml_file}'") + data = data.replace(replacement, manifest["replace-manifest"][replacement]) + with open(toml_file, "w") as f: + f.write(data) + +def import_test_suite(test_suite, source_path, output_path, ignore_list, manifest, is_direct_path=False): + print(f"Importing test suite '{test_suite}' from '{source_path}'") + tests_folder = os.path.join("engine", source_path) + if not is_direct_path: + tests_folder = os.path.join(tests_folder, "tests") + if not os.path.exists(tests_folder): + die_with_error(f"Tests folder not found: {tests_folder}") + files = os.listdir(tests_folder) + validate_tests_path(tests_folder, files, ignore_list) + if os.path.exists(output_path): + shutil.rmtree(output_path) + os.makedirs(output_path, exist_ok=True) + for item in files: + if item in ignore_list: + continue + s = os.path.join(tests_folder, item) + d = os.path.join(output_path, item) + if os.path.isdir(s): + shutil.copytree(s, d) + else: + shutil.copy2(s, d) + disable_and_replace_manifest(manifest[test_suite], output_path) + +def write_moz_build_file(manifest): + moz_build_path = os.path.join(EXTERNAL_TESTS_OUTPUT, "moz.build") + print(f"Writing moz.build file to '{moz_build_path}'") + with open(moz_build_path, "w") as f: + f.write(FILE_PREFIX) + for test_suite in manifest.keys(): + f.write(f'\t"{test_suite}/browser.toml",\n') + f.write(FILE_SUFFIX) + +def make_sure_ordered_tests(manifest): + ordered_tests = sorted(manifest.keys()) + if list(manifest.keys()) != ordered_tests: + die_with_error("Test suites in manifest.toml are not in alphabetical order.") + +def main(): + manifest = get_tests_manifest() + if os.path.exists(EXTERNAL_TESTS_OUTPUT): + shutil.rmtree(EXTERNAL_TESTS_OUTPUT) + os.makedirs(EXTERNAL_TESTS_OUTPUT, exist_ok=True) + + make_sure_ordered_tests(manifest) + for test_suite, config in manifest.items(): + import_test_suite( + test_suite=test_suite, + source_path=config["source"], + output_path=os.path.join(EXTERNAL_TESTS_OUTPUT, test_suite), + ignore_list=config.get("ignore", []), + is_direct_path=config.get("is_direct_path", False), + manifest=manifest + ) + write_moz_build_file(manifest) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/scripts/run_tests.py b/scripts/run_tests.py index 90a7995a8a..ec25791997 100644 --- a/scripts/run_tests.py +++ b/scripts/run_tests.py @@ -15,6 +15,7 @@ 'engine', 'testing', 'mochitest', 'ignorePrefs.json' ) +MOCHITEST_NAME = "mochitests" class JSONWithCommentsDecoder(json.JSONDecoder): def __init__(self, **kw): @@ -68,7 +69,9 @@ def run_mach_with_paths(test_paths): os.execvp(command[0], command) if path in ("", "all"): - test_dirs = [p for p in Path("zen/tests").iterdir() if p.is_dir()] + test_dirs = [p for p in Path("zen/tests").iterdir() if p.is_dir() and p.name != MOCHITEST_NAME] + mochitest_dirs = [p for p in Path(f"zen/tests/{MOCHITEST_NAME}").iterdir() if p.is_dir()] + test_dirs.extend(mochitest_dirs) test_paths = [str(p) for p in test_dirs] run_mach_with_paths(test_paths) else: diff --git a/src/zen/tests/manifest.toml b/src/zen/tests/manifest.toml new file mode 100644 index 0000000000..aeb652ed68 --- /dev/null +++ b/src/zen/tests/manifest.toml @@ -0,0 +1,26 @@ + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +[reportbrokensite] +source = "browser/components/reportbrokensite/test/browser" +is_direct_path = true + +[reportbrokensite.replace-manifest] +"../../../../../" = "../../../../" + +[safebrowsing] +source = "browser/components/safebrowsing/content/test" +is_direct_path = true + +[shell] +source = "browser/components/shell/test" +is_direct_path = true + +[tooltiptext] +source = "toolkit/components/tooltiptext" + +[translations] +source = "browser/components/translations/tests/browser" +is_direct_path = true diff --git a/src/zen/tests/mochitests/moz.build b/src/zen/tests/mochitests/moz.build new file mode 100644 index 0000000000..2fa5fb2a60 --- /dev/null +++ b/src/zen/tests/mochitests/moz.build @@ -0,0 +1,15 @@ + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# This file is autogenerated by scripts/import_external_tests.py +# Do not edit manually. + +BROWSER_CHROME_MANIFESTS += [ + "reportbrokensite/browser.toml", + "safebrowsing/browser.toml", + "shell/browser.toml", + "tooltiptext/browser.toml", + "translations/browser.toml", +] \ No newline at end of file diff --git a/src/zen/tests/mochitests/reportbrokensite/browser.toml b/src/zen/tests/mochitests/reportbrokensite/browser.toml new file mode 100644 index 0000000000..5681f17948 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser.toml @@ -0,0 +1,49 @@ +[DEFAULT] +tags = "report-broken-site" +support-files = [ + "example_report_page.html", + "head.js", + "sendMoreInfoTestEndpoint.html", +] + +["browser_addon_data_sent.js"] +support-files = [ "send_more_info.js" ] +skip-if = ["os == 'win' && os_version == '11.26100' && processor == 'x86_64' && opt"] # Bug 1955805 + +["browser_antitracking_data_sent.js"] +support-files = [ "send_more_info.js" ] + +["browser_back_buttons.js"] + +["browser_error_messages.js"] + +["browser_experiment_data_sent.js"] +support-files = [ "send_more_info.js" ] + +["browser_keyboard_navigation.js"] +skip-if = ["os == 'linux' && os_version == '24.04' && processor == 'x86_64' && tsan"] # Bug 1867132 + +["browser_parent_menuitems.js"] + +["browser_prefers_contrast.js"] + +["browser_reason_dropdown.js"] + +["browser_report_send.js"] +support-files = [ "send.js" ] + +["browser_send_more_info.js"] +support-files = [ + "send_more_info.js", + "../../../../toolkit/components/gfx/content/videotest.mp4", +] + +["browser_tab_key_order.js"] + +["browser_tab_switch_handling.js"] + +["browser_webcompat.com_fallback.js"] +support-files = [ + "send_more_info.js", + "../../../../toolkit/components/gfx/content/videotest.mp4", +] diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_addon_data_sent.js b/src/zen/tests/mochitests/reportbrokensite/browser_addon_data_sent.js new file mode 100644 index 0000000000..c7fb557d1c --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_addon_data_sent.js @@ -0,0 +1,99 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests to ensure that the right data is sent for + * private windows and when ETP blocks content. + */ + +/* import-globals-from send.js */ +/* import-globals-from send_more_info.js */ + +"use strict"; + +const { AddonTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/AddonTestUtils.sys.mjs" +); +AddonTestUtils.initMochitest(this); + +Services.scriptloader.loadSubScript( + getRootDirectory(gTestPath) + "send_more_info.js", + this +); + +add_common_setup(); + +const TEMP_ID = "testtempaddon@tests.mozilla.org"; +const TEMP_NAME = "Temporary Addon"; +const TEMP_VERSION = "0.1.0"; + +const PERM_ID = "testpermaddon@tests.mozilla.org"; +const PERM_NAME = "Permanent Addon"; +const PERM_VERSION = "0.2.0"; + +const DISABLED_ID = "testdisabledaddon@tests.mozilla.org"; +const DISABLED_NAME = "Disabled Addon"; +const DISABLED_VERSION = "0.3.0"; + +const EXPECTED_ADDONS = [ + { id: PERM_ID, name: PERM_NAME, temporary: false, version: PERM_VERSION }, + { id: TEMP_ID, name: TEMP_NAME, temporary: true, version: TEMP_VERSION }, +]; + +function loadAddon(id, name, version, isTemp = false) { + return ExtensionTestUtils.loadExtension({ + manifest: { + browser_specific_settings: { gecko: { id } }, + name, + version, + }, + useAddonManager: isTemp ? "temporary" : "permanent", + }); +} + +async function installAddons() { + const temp = await loadAddon(TEMP_ID, TEMP_NAME, TEMP_VERSION, true); + await temp.startup(); + + const perm = await loadAddon(PERM_ID, PERM_NAME, PERM_VERSION); + await perm.startup(); + + const dis = await loadAddon(DISABLED_ID, DISABLED_NAME, DISABLED_VERSION); + await dis.startup(); + await (await AddonManager.getAddonByID(DISABLED_ID)).disable(); + + return async () => { + await temp.unload(); + await perm.unload(); + await dis.unload(); + }; +} + +add_task(async function testSendButton() { + ensureReportBrokenSitePreffedOn(); + ensureReasonOptional(); + const addonCleanup = await installAddons(); + + const tab = await openTab(REPORTABLE_PAGE_URL); + + await testSend(tab, AppMenu(), { + addons: EXPECTED_ADDONS, + }); + + closeTab(tab); + await addonCleanup(); +}); + +add_task(async function testSendingMoreInfo() { + ensureReportBrokenSitePreffedOn(); + ensureSendMoreInfoEnabled(); + const addonCleanup = await installAddons(); + + const tab = await openTab(REPORTABLE_PAGE_URL); + + await testSendMoreInfo(tab, HelpMenu(), { + addons: EXPECTED_ADDONS, + }); + + closeTab(tab); + await addonCleanup(); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_antitracking_data_sent.js b/src/zen/tests/mochitests/reportbrokensite/browser_antitracking_data_sent.js new file mode 100644 index 0000000000..675c583561 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_antitracking_data_sent.js @@ -0,0 +1,117 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests to ensure that the right data is sent for + * private windows and when ETP blocks content. + */ + +/* import-globals-from send.js */ +/* import-globals-from send_more_info.js */ + +"use strict"; + +Services.scriptloader.loadSubScript( + getRootDirectory(gTestPath) + "send_more_info.js", + this +); + +add_common_setup(); + +add_task(setupStrictETP); + +add_task(async function testSendButton() { + ensureReportBrokenSitePreffedOn(); + ensureReasonOptional(); + + const win = await BrowserTestUtils.openNewBrowserWindow({ private: true }); + const blockedPromise = waitForContentBlockingEvent(3, win); + const tab = await openTab(REPORTABLE_PAGE_URL3, win); + await blockedPromise; + + await testSend(tab, AppMenu(win), { + breakageCategory: "adblocker", + description: "another test description", + antitracking: { + blockList: "strict", + isPrivateBrowsing: true, + hasTrackingContentBlocked: true, + hasMixedActiveContentBlocked: true, + hasMixedDisplayContentBlocked: true, + btpHasPurgedSite: false, + etpCategory: "strict", + }, + frameworks: { + fastclick: true, + marfeel: true, + mobify: true, + }, + }); + + await BrowserTestUtils.closeWindow(win); +}); + +add_task(async function testSendingMoreInfo() { + ensureReportBrokenSitePreffedOn(); + ensureSendMoreInfoEnabled(); + + const win = await BrowserTestUtils.openNewBrowserWindow({ private: true }); + const blockedPromise = waitForContentBlockingEvent(3, win); + const tab = await openTab(REPORTABLE_PAGE_URL3, win); + await blockedPromise; + + await testSendMoreInfo(tab, HelpMenu(win), { + antitracking: { + blockList: "strict", + isPrivateBrowsing: true, + hasTrackingContentBlocked: true, + hasMixedActiveContentBlocked: true, + hasMixedDisplayContentBlocked: true, + btpHasPurgedSite: false, + etpCategory: "strict", + }, + frameworks: { fastclick: true, mobify: true, marfeel: true }, + consoleLog: [ + { + level: "error", + log(actual) { + // "Blocked loading mixed display content http://example.com/tests/image/test/mochitest/blue.png" + return ( + Array.isArray(actual) && + actual.length == 1 && + actual[0].includes("blue.png") + ); + }, + pos: "0:1", + uri: REPORTABLE_PAGE_URL3, + }, + { + level: "error", + log(actual) { + // "Blocked loading mixed active content http://tracking.example.org/browser/browser/base/content/test/protectionsUI/benignPage.html", + return ( + Array.isArray(actual) && + actual.length == 1 && + actual[0].includes("benignPage.html") + ); + }, + pos: "0:1", + uri: REPORTABLE_PAGE_URL3, + }, + { + level: "warn", + log(actual) { + // "The resource at https://trackertest.org/ was blocked because content blocking is enabled.", + return ( + Array.isArray(actual) && + actual.length == 1 && + actual[0].includes("trackertest.org") + ); + }, + pos: "0:1", + uri: REPORTABLE_PAGE_URL3, + }, + ], + }); + + await BrowserTestUtils.closeWindow(win); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_back_buttons.js b/src/zen/tests/mochitests/reportbrokensite/browser_back_buttons.js new file mode 100644 index 0000000000..c004442c24 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_back_buttons.js @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests to ensure that Report Broken Site popups will be + * reset to whichever tab the user is on as they change + * between windows and tabs. */ + +"use strict"; + +add_common_setup(); + +add_task(async function testBackButtonsAreAdded() { + ensureReportBrokenSitePreffedOn(); + + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + let rbs = await AppMenu().openReportBrokenSite(); + rbs.isBackButtonEnabled(); + await rbs.clickBack(); + await rbs.close(); + + rbs = await HelpMenu().openReportBrokenSite(); + ok(!rbs.backButton, "Back button is not shown for Help Menu"); + await rbs.close(); + + rbs = await ProtectionsPanel().openReportBrokenSite(); + rbs.isBackButtonEnabled(); + await rbs.clickBack(); + await rbs.close(); + + rbs = await HelpMenu().openReportBrokenSite(); + ok(!rbs.backButton, "Back button is not shown for Help Menu"); + await rbs.close(); + }); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_error_messages.js b/src/zen/tests/mochitests/reportbrokensite/browser_error_messages.js new file mode 100644 index 0000000000..54b93cb2da --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_error_messages.js @@ -0,0 +1,64 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Test that the Report Broken Site errors messages are shown on + * the UI if the user enters an invalid URL or clicks the send + * button while it is disabled due to not selecting a "reason" + */ + +"use strict"; + +add_common_setup(); + +add_task(async function test() { + ensureReportBrokenSitePreffedOn(); + ensureReasonRequired(); + + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + for (const menu of [AppMenu(), ProtectionsPanel(), HelpMenu()]) { + const rbs = await menu.openReportBrokenSite(); + const { sendButton, URLInput } = rbs; + + rbs.isURLInvalidMessageHidden(); + rbs.isReasonNeededMessageHidden(); + + rbs.setURL(""); + window.document.activeElement.blur(); + rbs.isURLInvalidMessageShown(); + rbs.isReasonNeededMessageHidden(); + + rbs.setURL("https://asdf"); + window.document.activeElement.blur(); + rbs.isURLInvalidMessageHidden(); + rbs.isReasonNeededMessageHidden(); + + rbs.setURL("http:/ /asdf"); + window.document.activeElement.blur(); + rbs.isURLInvalidMessageShown(); + rbs.isReasonNeededMessageHidden(); + + rbs.setURL("https://asdf"); + const selectPromise = BrowserTestUtils.waitForSelectPopupShown(window); + EventUtils.synthesizeMouseAtCenter(sendButton, {}, window); + await selectPromise; + rbs.isURLInvalidMessageHidden(); + rbs.isReasonNeededMessageShown(); + await rbs.dismissDropdownPopup(); + + rbs.chooseReason("slow"); + rbs.isURLInvalidMessageHidden(); + rbs.isReasonNeededMessageHidden(); + + rbs.setURL(""); + rbs.chooseReason("choose"); + window.ownerGlobal.document.activeElement?.blur(); + const focusPromise = BrowserTestUtils.waitForEvent(URLInput, "focus"); + EventUtils.synthesizeMouseAtCenter(sendButton, {}, window); + await focusPromise; + rbs.isURLInvalidMessageShown(); + rbs.isReasonNeededMessageShown(); + + rbs.clickCancel(); + } + }); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_experiment_data_sent.js b/src/zen/tests/mochitests/reportbrokensite/browser_experiment_data_sent.js new file mode 100644 index 0000000000..3cedcd5499 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_experiment_data_sent.js @@ -0,0 +1,88 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests to ensure that the right data is sent for + * private windows and when ETP blocks content. + */ + +/* import-globals-from send.js */ +/* import-globals-from send_more_info.js */ + +"use strict"; + +Services.scriptloader.loadSubScript( + getRootDirectory(gTestPath) + "send_more_info.js", + this +); + +const { ExperimentAPI } = ChromeUtils.importESModule( + "resource://nimbus/ExperimentAPI.sys.mjs" +); +const { NimbusTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/NimbusTestUtils.sys.mjs" +); + +add_common_setup(); + +const EXPECTED_EXPERIMENTS_IN_REPORT = [ + { slug: "test-experiment", branch: "branch", kind: "nimbusExperiment" }, + { slug: "test-experiment-rollout", branch: "branch", kind: "nimbusRollout" }, +]; + +let EXPERIMENT_CLEANUPS; + +add_setup(async function () { + await ExperimentAPI.ready(); + EXPERIMENT_CLEANUPS = [ + await NimbusTestUtils.enrollWithFeatureConfig( + { featureId: "no-feature-firefox-desktop", value: {} }, + { slug: "test-experiment", branchSlug: "branch" } + ), + await NimbusTestUtils.enrollWithFeatureConfig( + { featureId: "no-feature-firefox-desktop", value: {} }, + { slug: "test-experiment-rollout", isRollout: true, branchSlug: "branch" } + ), + async () => { + ExperimentAPI.manager.store._deleteForTests("test-experiment-disabled"); + await NimbusTestUtils.flushStore(); + }, + ]; + + await NimbusTestUtils.enrollWithFeatureConfig( + { featureId: "no-feature-firefox-desktop", value: {} }, + { slug: "test-experiment-disabled" } + ); + await ExperimentAPI.manager.unenroll("test-experiment-disabled"); +}); + +add_task(async function testSendButton() { + ensureReportBrokenSitePreffedOn(); + ensureReasonOptional(); + + const tab = await openTab(REPORTABLE_PAGE_URL); + + await testSend(tab, AppMenu(), { + experiments: EXPECTED_EXPERIMENTS_IN_REPORT, + }); + + closeTab(tab); +}); + +add_task(async function testSendingMoreInfo() { + ensureReportBrokenSitePreffedOn(); + ensureSendMoreInfoEnabled(); + + const tab = await openTab(REPORTABLE_PAGE_URL); + + await testSendMoreInfo(tab, HelpMenu(), { + experiments: EXPECTED_EXPERIMENTS_IN_REPORT, + }); + + closeTab(tab); +}); + +add_task(async function teardown() { + for (const cleanup of EXPERIMENT_CLEANUPS) { + await cleanup(); + } +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_keyboard_navigation.js b/src/zen/tests/mochitests/reportbrokensite/browser_keyboard_navigation.js new file mode 100644 index 0000000000..3bf9278e46 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_keyboard_navigation.js @@ -0,0 +1,107 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests to ensure that sending or canceling reports with + * the Send and Cancel buttons work (as well as the Okay button) + */ + +"use strict"; + +add_common_setup(); + +requestLongerTimeout(2); + +async function testPressingKey(key, tabToMatch, makePromise, followUp) { + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + for (const menu of [AppMenu(), ProtectionsPanel(), HelpMenu()]) { + info( + `Opening RBS to test pressing ${key} for ${tabToMatch} on ${menu.menuDescription}` + ); + const rbs = await menu.openReportBrokenSite(); + const promise = makePromise(rbs); + if (tabToMatch) { + if (await tabTo(tabToMatch)) { + await pressKeyAndAwait(promise, key); + followUp && (await followUp(rbs)); + await rbs.close(); + ok(true, `was able to activate ${tabToMatch} with keyboard`); + } else { + await rbs.close(); + ok(false, `could not tab to ${tabToMatch}`); + } + } else { + await pressKeyAndAwait(promise, key); + followUp && (await followUp(rbs)); + await rbs.close(); + ok(true, `was able to use keyboard`); + } + } + }); +} + +add_task(async function testSendMoreInfo() { + ensureReportBrokenSitePreffedOn(); + ensureSendMoreInfoEnabled(); + await testPressingKey( + "KEY_Enter", + "#report-broken-site-popup-send-more-info-link", + rbs => rbs.waitForSendMoreInfoTab(), + () => gBrowser.removeCurrentTab() + ); +}); + +add_task(async function testCancel() { + ensureReportBrokenSitePreffedOn(); + await testPressingKey( + "KEY_Enter", + "#report-broken-site-popup-cancel-button", + rbs => BrowserTestUtils.waitForEvent(rbs.mainView, "ViewHiding") + ); +}); + +add_task(async function testSendAndOkay() { + ensureReportBrokenSitePreffedOn(); + await testPressingKey( + "KEY_Enter", + "#report-broken-site-popup-send-button", + rbs => rbs.awaitReportSentViewOpened(), + async rbs => { + await tabTo("#report-broken-site-popup-okay-button"); + const promise = BrowserTestUtils.waitForEvent(rbs.sentView, "ViewHiding"); + await pressKeyAndAwait(promise, "KEY_Enter"); + } + ); +}); + +add_task(async function testESCOnMain() { + ensureReportBrokenSitePreffedOn(); + await testPressingKey("KEY_Escape", undefined, rbs => + BrowserTestUtils.waitForEvent(rbs.mainView, "ViewHiding") + ); +}); + +add_task(async function testESCOnSent() { + ensureReportBrokenSitePreffedOn(); + await testPressingKey( + "KEY_Enter", + "#report-broken-site-popup-send-button", + rbs => rbs.awaitReportSentViewOpened(), + async rbs => { + const promise = BrowserTestUtils.waitForEvent(rbs.sentView, "ViewHiding"); + await pressKeyAndAwait(promise, "KEY_Escape"); + } + ); +}); + +add_task(async function testBackButtons() { + ensureReportBrokenSitePreffedOn(); + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + for (const menu of [AppMenu(), ProtectionsPanel()]) { + await menu.openReportBrokenSite(); + await tabTo("#report-broken-site-popup-mainView .subviewbutton-back"); + const promise = BrowserTestUtils.waitForEvent(menu.popup, "ViewShown"); + await pressKeyAndAwait(promise, "KEY_Enter"); + menu.close(); + } + }); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_parent_menuitems.js b/src/zen/tests/mochitests/reportbrokensite/browser_parent_menuitems.js new file mode 100644 index 0000000000..36f172789b --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_parent_menuitems.js @@ -0,0 +1,96 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Test that the Report Broken Site menu items are disabled + * when the active tab is not on a reportable URL, and is hidden + * when the feature is disabled via pref. Also ensure that the + * Report Broken Site item that is automatically generated in + * the app menu's help sub-menu is hidden. + */ + +"use strict"; + +add_common_setup(); + +add_task(async function testMenus() { + ensureReportBrokenSitePreffedOff(); + + const appMenu = AppMenu(); + const menus = [appMenu, ProtectionsPanel(), HelpMenu()]; + + async function forceMenuItemStateUpdate() { + ReportBrokenSite.enableOrDisableMenuitems(window); + + // the hidden/disabled state of all of the menuitems may not update until one + // is rendered; then the related 's state is propagated to them all. + await appMenu.open(); + await appMenu.close(); + } + + await BrowserTestUtils.withNewTab("about:blank", async function () { + await forceMenuItemStateUpdate(); + for (const { menuDescription, reportBrokenSite } of menus) { + isMenuItemHidden( + reportBrokenSite, + `${menuDescription} option hidden on invalid page when preffed off` + ); + } + }); + + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + await forceMenuItemStateUpdate(); + for (const { menuDescription, reportBrokenSite } of menus) { + isMenuItemHidden( + reportBrokenSite, + `${menuDescription} option hidden on valid page when preffed off` + ); + } + }); + + ensureReportBrokenSitePreffedOn(); + + await BrowserTestUtils.withNewTab("about:blank", async function () { + await forceMenuItemStateUpdate(); + for (const { menuDescription, reportBrokenSite } of menus) { + isMenuItemDisabled( + reportBrokenSite, + `${menuDescription} option disabled on invalid page when preffed on` + ); + } + }); + + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + await forceMenuItemStateUpdate(); + for (const { menuDescription, reportBrokenSite } of menus) { + isMenuItemEnabled( + reportBrokenSite, + `${menuDescription} option enabled on valid page when preffed on` + ); + } + }); + + ensureReportBrokenSitePreffedOff(); + + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + await forceMenuItemStateUpdate(); + for (const { menuDescription, reportBrokenSite } of menus) { + isMenuItemHidden( + reportBrokenSite, + `${menuDescription} option hidden again when pref toggled back off` + ); + } + }); + + ensureReportBrokenSitePreffedOn(); + ensureReportBrokenSiteDisabledByPolicy(); + + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + await forceMenuItemStateUpdate(); + for (const { menuDescription, reportBrokenSite } of menus) { + isMenuItemHidden( + reportBrokenSite, + `${menuDescription} option hidden when disabled by DisableFeedbackCommands enterprise policy` + ); + } + }); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_prefers_contrast.js b/src/zen/tests/mochitests/reportbrokensite/browser_prefers_contrast.js new file mode 100644 index 0000000000..b184b51450 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_prefers_contrast.js @@ -0,0 +1,56 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Test that the background color of the "report sent" + * view is not green in non-default contrast modes. + */ + +"use strict"; + +add_common_setup(); + +const HIGH_CONTRAST_MODE_OFF = [[PREFS.USE_ACCESSIBILITY_THEME, 0]]; + +const HIGH_CONTRAST_MODE_ON = [[PREFS.USE_ACCESSIBILITY_THEME, 1]]; + +add_task(async function testReportSentViewBGColor() { + ensureReportBrokenSitePreffedOn(); + ensureReasonDisabled(); + + await BrowserTestUtils.withNewTab( + REPORTABLE_PAGE_URL, + async function (browser) { + const { defaultView } = browser.ownerGlobal.document; + + const menu = AppMenu(); + + await SpecialPowers.pushPrefEnv({ set: HIGH_CONTRAST_MODE_OFF }); + const rbs = await menu.openReportBrokenSite(); + const { mainView, sentView } = rbs; + mainView.style.backgroundColor = "var(--background-color-success)"; + const expectedReportSentBGColor = + defaultView.getComputedStyle(mainView).backgroundColor; + mainView.style.backgroundColor = ""; + const expectedPrefersReducedBGColor = + defaultView.getComputedStyle(mainView).backgroundColor; + + await rbs.clickSend(); + is( + defaultView.getComputedStyle(sentView).backgroundColor, + expectedReportSentBGColor, + "Using green bgcolor when not prefers-contrast" + ); + await rbs.clickOkay(); + + await SpecialPowers.pushPrefEnv({ set: HIGH_CONTRAST_MODE_ON }); + await menu.openReportBrokenSite(); + await rbs.clickSend(); + is( + defaultView.getComputedStyle(sentView).backgroundColor, + expectedPrefersReducedBGColor, + "Using default bgcolor when prefers-contrast" + ); + await rbs.clickOkay(); + } + ); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_reason_dropdown.js b/src/zen/tests/mochitests/reportbrokensite/browser_reason_dropdown.js new file mode 100644 index 0000000000..365b469a7d --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_reason_dropdown.js @@ -0,0 +1,156 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests to ensure that the reason dropdown is shown or hidden + * based on its pref, and that its optional and required modes affect + * the Send button and report appropriately. + */ + +"use strict"; + +add_common_setup(); + +requestLongerTimeout(2); + +async function clickSendAndCheckPing(rbs, expectedReason = null) { + await GleanPings.brokenSiteReport.testSubmission( + () => + Assert.equal( + Glean.brokenSiteReport.breakageCategory.testGetValue(), + expectedReason + ), + () => rbs.clickSend() + ); +} + +add_task(async function testReasonDropdown() { + ensureReportBrokenSitePreffedOn(); + + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + ensureReasonDisabled(); + + let rbs = await AppMenu().openReportBrokenSite(); + await rbs.isReasonHidden(); + await rbs.isSendButtonEnabled(); + await clickSendAndCheckPing(rbs); + await rbs.clickOkay(); + + ensureReasonOptional(); + rbs = await AppMenu().openReportBrokenSite(); + await rbs.isReasonOptional(); + await rbs.isSendButtonEnabled(); + await clickSendAndCheckPing(rbs); + await rbs.clickOkay(); + + rbs = await AppMenu().openReportBrokenSite(); + await rbs.isReasonOptional(); + rbs.chooseReason("slow"); + await rbs.isSendButtonEnabled(); + await clickSendAndCheckPing(rbs, "slow"); + await rbs.clickOkay(); + + ensureReasonRequired(); + rbs = await AppMenu().openReportBrokenSite(); + await rbs.isReasonRequired(); + await rbs.isSendButtonEnabled(); + const selectPromise = BrowserTestUtils.waitForSelectPopupShown(window); + EventUtils.synthesizeMouseAtCenter(rbs.sendButton, {}, window); + await selectPromise; + rbs.chooseReason("media"); + await rbs.dismissDropdownPopup(); + await rbs.isSendButtonEnabled(); + await clickSendAndCheckPing(rbs, "media"); + await rbs.clickOkay(); + }); +}); + +async function getListItems(rbs) { + const items = Array.from(rbs.reasonInput.querySelectorAll("option")).map(i => + i.id.replace("report-broken-site-popup-reason-", "") + ); + Assert.equal(items[0], "choose", "First option is always 'choose'"); + return items.join(","); +} + +add_task(async function testReasonDropdownRandomized() { + ensureReportBrokenSitePreffedOn(); + ensureReasonOptional(); + + const USER_ID_PREF = "app.normandy.user_id"; + const RANDOMIZE_PREF = "ui.new-webcompat-reporter.reason-dropdown.randomized"; + + const origNormandyUserID = Services.prefs.getCharPref( + USER_ID_PREF, + undefined + ); + + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + // confirm that the default order is initially used + Services.prefs.setBoolPref(RANDOMIZE_PREF, false); + const rbs = await AppMenu().openReportBrokenSite(); + const defaultOrder = [ + "choose", + "checkout", + "load", + "slow", + "media", + "content", + "account", + "adblocker", + "notsupported", + "other", + ]; + Assert.deepEqual( + await getListItems(rbs), + defaultOrder, + "non-random order is correct" + ); + + // confirm that a random order happens per user + let randomOrder; + let isRandomized = false; + Services.prefs.setBoolPref(RANDOMIZE_PREF, true); + + // This becomes ClientEnvironment.randomizationId, which we can set to + // any value which results in a different order from the default ordering. + Services.prefs.setCharPref("app.normandy.user_id", "dummy"); + + // clicking cancel triggers a reset, which is when the randomization + // logic is called. so we must click cancel after pref-changes here. + rbs.clickCancel(); + await AppMenu().openReportBrokenSite(); + randomOrder = await getListItems(rbs); + Assert.notEqual( + randomOrder, + defaultOrder, + "options are randomized with pref on" + ); + + // confirm that the order doesn't change per user + isRandomized = false; + for (let attempt = 0; attempt < 5; ++attempt) { + rbs.clickCancel(); + await AppMenu().openReportBrokenSite(); + const order = await getListItems(rbs); + + if (order != randomOrder) { + isRandomized = true; + break; + } + } + Assert.ok(!isRandomized, "options keep the same order per user"); + + // confirm that the order reverts to the default if pref flipped to false + Services.prefs.setBoolPref(RANDOMIZE_PREF, false); + rbs.clickCancel(); + await AppMenu().openReportBrokenSite(); + Assert.deepEqual( + defaultOrder, + await getListItems(rbs), + "reverts to non-random order correctly" + ); + rbs.clickCancel(); + }); + + Services.prefs.setCharPref(USER_ID_PREF, origNormandyUserID); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_report_send.js b/src/zen/tests/mochitests/reportbrokensite/browser_report_send.js new file mode 100644 index 0000000000..bf849776d7 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_report_send.js @@ -0,0 +1,79 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests to ensure that sending or canceling reports with + * the Send and Cancel buttons work (as well as the Okay button) + */ + +/* import-globals-from send.js */ + +"use strict"; + +Services.scriptloader.loadSubScript( + getRootDirectory(gTestPath) + "send.js", + this +); + +add_common_setup(); + +requestLongerTimeout(10); + +async function testCancel(menu, url, description) { + let rbs = await menu.openAndPrefillReportBrokenSite(url, description); + await rbs.clickCancel(); + ok(!rbs.opened, "clicking Cancel closes Report Broken Site"); + + // re-opening the panel, the url and description should be reset + rbs = await menu.openReportBrokenSite(); + rbs.isMainViewResetToCurrentTab(); + rbs.close(); +} + +add_task(async function testSendButton() { + ensureReportBrokenSitePreffedOn(); + ensureReasonOptional(); + + const tab1 = await openTab(REPORTABLE_PAGE_URL); + + await testSend(tab1, AppMenu()); + + const tab2 = await openTab(REPORTABLE_PAGE_URL); + + await testSend(tab2, ProtectionsPanel(), { + url: "https://test.org/test/#fake", + breakageCategory: "media", + description: "test description", + }); + + closeTab(tab1); + closeTab(tab2); +}); + +add_task(async function testCancelButton() { + ensureReportBrokenSitePreffedOn(); + + const tab1 = await openTab(REPORTABLE_PAGE_URL); + + await testCancel(AppMenu()); + await testCancel(ProtectionsPanel()); + await testCancel(HelpMenu()); + + const tab2 = await openTab(REPORTABLE_PAGE_URL); + + await testCancel(AppMenu()); + await testCancel(ProtectionsPanel()); + await testCancel(HelpMenu()); + + const win2 = await BrowserTestUtils.openNewBrowserWindow(); + const tab3 = await openTab(REPORTABLE_PAGE_URL2, win2); + + await testCancel(AppMenu(win2)); + await testCancel(ProtectionsPanel(win2)); + await testCancel(HelpMenu(win2)); + + closeTab(tab3); + await BrowserTestUtils.closeWindow(win2); + + closeTab(tab1); + closeTab(tab2); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_send_more_info.js b/src/zen/tests/mochitests/reportbrokensite/browser_send_more_info.js new file mode 100644 index 0000000000..9306f5161e --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_send_more_info.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests that the send more info link appears only when its pref + * is set to true, and that when clicked it will open a tab to + * the webcompat.com endpoint and send the right data. + */ + +/* import-globals-from send_more_info.js */ + +"use strict"; + +const VIDEO_URL = `${BASE_URL}/videotest.mp4`; + +Services.scriptloader.loadSubScript( + getRootDirectory(gTestPath) + "send_more_info.js", + this +); + +add_common_setup(); + +requestLongerTimeout(2); + +add_task(async function testSendMoreInfoPref() { + ensureReportBrokenSitePreffedOn(); + + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + await changeTab(gBrowser.selectedTab, REPORTABLE_PAGE_URL); + + ensureSendMoreInfoDisabled(); + let rbs = await AppMenu().openReportBrokenSite(); + await rbs.isSendMoreInfoHidden(); + await rbs.close(); + + ensureSendMoreInfoEnabled(); + rbs = await AppMenu().openReportBrokenSite(); + await rbs.isSendMoreInfoShown(); + await rbs.close(); + }); +}); + +add_task(async function testSendingMoreInfo() { + ensureReportBrokenSitePreffedOn(); + ensureSendMoreInfoEnabled(); + + const tab = await openTab(REPORTABLE_PAGE_URL); + + await testSendMoreInfo(tab, AppMenu()); + + await changeTab(tab, REPORTABLE_PAGE_URL2); + + await testSendMoreInfo(tab, ProtectionsPanel(), { + url: "https://override.com", + description: "another", + expectNoTabDetails: true, + }); + + // also load a video to ensure system codec + // information is loaded and properly sent + const tab2 = await openTab(VIDEO_URL); + await testSendMoreInfo(tab2, HelpMenu()); + closeTab(tab2); + + closeTab(tab); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_tab_key_order.js b/src/zen/tests/mochitests/reportbrokensite/browser_tab_key_order.js new file mode 100644 index 0000000000..e02c6a8394 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_tab_key_order.js @@ -0,0 +1,132 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests of the expected tab key element focus order */ + +"use strict"; + +add_common_setup(); + +requestLongerTimeout(2); + +async function ensureTabOrder(order, win = window) { + const config = { window: win }; + for (let matches of order) { + // We need to tab through all elements in each match array in any order + if (!Array.isArray(matches)) { + matches = [matches]; + } + let matchesLeft = matches.length; + while (matchesLeft--) { + const target = await pressKeyAndGetFocus("VK_TAB", config); + let foundMatch = false; + for (const [i, selector] of matches.entries()) { + foundMatch = selector && target.matches(selector); + if (foundMatch) { + matches[i] = ""; + break; + } + } + ok( + foundMatch, + `Expected [${matches}] next, got id=${target.id}, class=${target.className}, ${target}` + ); + if (!foundMatch) { + return false; + } + } + } + return true; +} + +async function ensureExpectedTabOrder( + expectBackButton, + expectReason, + expectSendMoreInfo +) { + const { activeElement } = window.document; + is( + activeElement?.id, + "report-broken-site-popup-url", + "URL is already focused" + ); + const order = []; + if (expectReason) { + order.push("#report-broken-site-popup-reason"); + } + order.push("#report-broken-site-popup-description"); + if (expectSendMoreInfo) { + order.push("#report-broken-site-popup-send-more-info-link"); + } + // moz-button-groups swap the order of buttons to follow + // platform conventions, so the order of send/cancel will vary. + order.push([ + "#report-broken-site-popup-cancel-button", + "#report-broken-site-popup-send-button", + ]); + if (expectBackButton) { + order.push(".subviewbutton-back"); + } + order.push("#report-broken-site-popup-url"); // check that we've cycled back + return ensureTabOrder(order); +} + +async function testTabOrder(menu) { + ensureReasonDisabled(); + ensureSendMoreInfoDisabled(); + + const { showsBackButton } = menu; + + let rbs = await menu.openReportBrokenSite(); + await ensureExpectedTabOrder(showsBackButton, false, false); + await rbs.close(); + + ensureSendMoreInfoEnabled(); + rbs = await menu.openReportBrokenSite(); + await ensureExpectedTabOrder(showsBackButton, false, true); + await rbs.close(); + + ensureReasonOptional(); + rbs = await menu.openReportBrokenSite(); + await ensureExpectedTabOrder(showsBackButton, true, true); + await rbs.close(); + + ensureReasonRequired(); + rbs = await menu.openReportBrokenSite(); + await ensureExpectedTabOrder(showsBackButton, true, true); + await rbs.close(); + rbs = await menu.openReportBrokenSite(); + rbs.chooseReason("slow"); + await ensureExpectedTabOrder(showsBackButton, true, true); + await rbs.clickCancel(); + + ensureSendMoreInfoDisabled(); + rbs = await menu.openReportBrokenSite(); + await ensureExpectedTabOrder(showsBackButton, true, false); + await rbs.close(); + rbs = await menu.openReportBrokenSite(); + rbs.chooseReason("slow"); + await ensureExpectedTabOrder(showsBackButton, true, false); + await rbs.clickCancel(); + + ensureReasonOptional(); + rbs = await menu.openReportBrokenSite(); + await ensureExpectedTabOrder(showsBackButton, true, false); + await rbs.close(); + + ensureReasonDisabled(); + rbs = await menu.openReportBrokenSite(); + await ensureExpectedTabOrder(showsBackButton, false, false); + await rbs.close(); +} + +add_task(async function testTabOrdering() { + ensureReportBrokenSitePreffedOn(); + ensureSendMoreInfoEnabled(); + + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + await testTabOrder(AppMenu()); + await testTabOrder(ProtectionsPanel()); + await testTabOrder(HelpMenu()); + }); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_tab_switch_handling.js b/src/zen/tests/mochitests/reportbrokensite/browser_tab_switch_handling.js new file mode 100644 index 0000000000..db1190b893 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_tab_switch_handling.js @@ -0,0 +1,81 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests to ensure that Report Broken Site popups will be + * reset to whichever tab the user is on as they change + * between windows and tabs. */ + +"use strict"; + +add_common_setup(); + +add_task(async function testResetsProperlyOnTabSwitch() { + ensureReportBrokenSitePreffedOn(); + + const badTab = await openTab("about:blank"); + const goodTab1 = await openTab(REPORTABLE_PAGE_URL); + const goodTab2 = await openTab(REPORTABLE_PAGE_URL2); + + const appMenu = AppMenu(); + const protPanel = ProtectionsPanel(); + + let rbs = await appMenu.openReportBrokenSite(); + rbs.isMainViewResetToCurrentTab(); + rbs.close(); + + gBrowser.selectedTab = goodTab1; + + rbs = await protPanel.openReportBrokenSite(); + rbs.isMainViewResetToCurrentTab(); + rbs.close(); + + gBrowser.selectedTab = badTab; + await appMenu.open(); + appMenu.isReportBrokenSiteDisabled(); + await appMenu.close(); + + gBrowser.selectedTab = goodTab1; + rbs = await protPanel.openReportBrokenSite(); + rbs.isMainViewResetToCurrentTab(); + rbs.close(); + + closeTab(badTab); + closeTab(goodTab1); + closeTab(goodTab2); +}); + +add_task(async function testResetsProperlyOnWindowSwitch() { + ensureReportBrokenSitePreffedOn(); + + const tab1 = await openTab(REPORTABLE_PAGE_URL); + + const win2 = await BrowserTestUtils.openNewBrowserWindow(); + const tab2 = await openTab(REPORTABLE_PAGE_URL2, win2); + + const appMenu1 = AppMenu(); + const appMenu2 = ProtectionsPanel(win2); + + let rbs2 = await appMenu2.openReportBrokenSite(); + rbs2.isMainViewResetToCurrentTab(); + rbs2.close(); + + // flip back to tab1's window and ensure its URL pops up instead of tab2's URL + await switchToWindow(window); + isSelectedTab(window, tab1); // sanity check + + let rbs1 = await appMenu1.openReportBrokenSite(); + rbs1.isMainViewResetToCurrentTab(); + rbs1.close(); + + // likewise flip back to tab2's window and ensure its URL pops up instead of tab1's URL + await switchToWindow(win2); + isSelectedTab(win2, tab2); // sanity check + + rbs2 = await appMenu2.openReportBrokenSite(); + rbs2.isMainViewResetToCurrentTab(); + rbs2.close(); + + closeTab(tab1); + closeTab(tab2); + await BrowserTestUtils.closeWindow(win2); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_webcompat.com_fallback.js b/src/zen/tests/mochitests/reportbrokensite/browser_webcompat.com_fallback.js new file mode 100644 index 0000000000..4b155bbd99 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_webcompat.com_fallback.js @@ -0,0 +1,45 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests that when Report Broken Site is disabled, it will + * send the user to webcompat.com when clicked and it the + * relevant tab's report data. + */ + +/* import-globals-from send_more_info.js */ + +"use strict"; + +Services.scriptloader.loadSubScript( + getRootDirectory(gTestPath) + "send_more_info.js", + this +); + +add_common_setup(); + +const VIDEO_URL = `${BASE_URL}/videotest.mp4`; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["test.wait300msAfterTabSwitch", true]], + }); +}); + +add_task(async function testWebcompatComFallbacks() { + ensureReportBrokenSitePreffedOff(); + + const tab = await openTab(REPORTABLE_PAGE_URL); + + await testWebcompatComFallback(tab, AppMenu()); + + await changeTab(tab, REPORTABLE_PAGE_URL2); + await testWebcompatComFallback(tab, ProtectionsPanel()); + + // also load a video to ensure system codec + // information is loaded and properly sent + const tab2 = await openTab(VIDEO_URL); + await testWebcompatComFallback(tab2, HelpMenu()); + closeTab(tab2); + + closeTab(tab); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/example_report_page.html b/src/zen/tests/mochitests/reportbrokensite/example_report_page.html new file mode 100644 index 0000000000..07602e3fbe --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/example_report_page.html @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/zen/tests/mochitests/reportbrokensite/head.js b/src/zen/tests/mochitests/reportbrokensite/head.js new file mode 100644 index 0000000000..2b4c1d8eb0 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/head.js @@ -0,0 +1,897 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { CustomizableUITestUtils } = ChromeUtils.importESModule( + "resource://testing-common/CustomizableUITestUtils.sys.mjs" +); + +const { EnterprisePolicyTesting, PoliciesPrefTracker } = + ChromeUtils.importESModule( + "resource://testing-common/EnterprisePolicyTesting.sys.mjs" + ); + +const { UrlClassifierTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/UrlClassifierTestUtils.sys.mjs" +); + +const { ReportBrokenSite } = ChromeUtils.importESModule( + "moz-src:///browser/components/reportbrokensite/ReportBrokenSite.sys.mjs" +); + +const BASE_URL = + "https://example.com/browser/browser/components/reportbrokensite/test/browser/"; + +const REPORTABLE_PAGE_URL = "https://example.com"; + +const REPORTABLE_PAGE_URL2 = REPORTABLE_PAGE_URL.replace(".com", ".org"); + +const REPORTABLE_PAGE_URL3 = `${BASE_URL}example_report_page.html`; + +const NEW_REPORT_ENDPOINT_TEST_URL = `${BASE_URL}sendMoreInfoTestEndpoint.html`; + +const PREFS = { + DATAREPORTING_ENABLED: "datareporting.healthreport.uploadEnabled", + REPORTER_ENABLED: "ui.new-webcompat-reporter.enabled", + REASON: "ui.new-webcompat-reporter.reason-dropdown", + SEND_MORE_INFO: "ui.new-webcompat-reporter.send-more-info-link", + NEW_REPORT_ENDPOINT: "ui.new-webcompat-reporter.new-report-endpoint", + TOUCH_EVENTS: "dom.w3c_touch_events.enabled", + USE_ACCESSIBILITY_THEME: "ui.useAccessibilityTheme", +}; + +function add_common_setup() { + add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + [PREFS.NEW_REPORT_ENDPOINT, NEW_REPORT_ENDPOINT_TEST_URL], + + // set touch events to auto-detect, as the pref gets set to 1 somewhere + // while tests are running, making hasTouchScreen checks unreliable. + [PREFS.TOUCH_EVENTS, 2], + ], + }); + registerCleanupFunction(function () { + for (const prefName of Object.values(PREFS)) { + Services.prefs.clearUserPref(prefName); + } + }); + }); +} + +function areObjectsEqual(actual, expected, path = "") { + if (typeof expected == "function") { + try { + const passes = expected(actual); + if (!passes) { + info(`${path} not pass check function: ${actual}`); + } + return passes; + } catch (e) { + info(`${path} threw exception: + got: ${typeof actual}, ${actual} + expected: ${typeof expected}, ${expected} + exception: ${e.message} + ${e.stack}`); + return false; + } + } + + if (typeof actual != typeof expected) { + info(`${path} types do not match: + got: ${typeof actual}, ${actual} + expected: ${typeof expected}, ${expected}`); + return false; + } + if (typeof actual != "object" || actual === null || expected === null) { + if (actual !== expected) { + info(`${path} does not match + got: ${typeof actual}, ${actual} + expected: ${typeof expected}, ${expected}`); + return false; + } + return true; + } + const prefix = path ? `${path}.` : path; + for (const [key, val] of Object.entries(actual)) { + if (!(key in expected)) { + info(`Extra ${prefix}${key}: ${val}`); + return false; + } + } + let result = true; + for (const [key, expectedVal] of Object.entries(expected)) { + if (key in actual) { + if (!areObjectsEqual(actual[key], expectedVal, `${prefix}${key}`)) { + result = false; + } + } else { + info(`Missing ${prefix}${key} (${expectedVal})`); + result = false; + } + } + return result; +} + +function clickAndAwait(toClick, evt, target) { + const menuPromise = BrowserTestUtils.waitForEvent(target, evt); + EventUtils.synthesizeMouseAtCenter(toClick, {}, window); + return menuPromise; +} + +async function openTab(url, win) { + const options = { + gBrowser: + win?.gBrowser || + Services.wm.getMostRecentWindow("navigator:browser").gBrowser, + url, + }; + return BrowserTestUtils.openNewForegroundTab(options); +} + +async function changeTab(tab, url) { + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, url); + await BrowserTestUtils.browserLoaded(tab.linkedBrowser); +} + +function closeTab(tab) { + BrowserTestUtils.removeTab(tab); +} + +function switchToWindow(win) { + const promises = [ + BrowserTestUtils.waitForEvent(win, "focus"), + BrowserTestUtils.waitForEvent(win, "activate"), + ]; + win.focus(); + return Promise.all(promises); +} + +function isSelectedTab(win, tab) { + const selectedTab = win.document.querySelector(".tabbrowser-tab[selected]"); + is(selectedTab, tab); +} + +async function setupPolicyEngineWithJson(json, customSchema) { + PoliciesPrefTracker.restoreDefaultValues(); + if (typeof json != "object") { + let filePath = getTestFilePath(json ? json : "non-existing-file.json"); + return EnterprisePolicyTesting.setupPolicyEngineWithJson( + filePath, + customSchema + ); + } + return EnterprisePolicyTesting.setupPolicyEngineWithJson(json, customSchema); +} + +async function ensureReportBrokenSiteDisabledByPolicy() { + await setupPolicyEngineWithJson({ + policies: { + DisableFeedbackCommands: true, + }, + }); +} + +registerCleanupFunction(async function resetPolicies() { + if (Services.policies.status != Ci.nsIEnterprisePolicies.INACTIVE) { + await setupPolicyEngineWithJson(""); + } + EnterprisePolicyTesting.resetRunOnceState(); + PoliciesPrefTracker.restoreDefaultValues(); + PoliciesPrefTracker.stop(); +}); + +function ensureReportBrokenSitePreffedOn() { + Services.prefs.setBoolPref(PREFS.DATAREPORTING_ENABLED, true); + Services.prefs.setBoolPref(PREFS.REPORTER_ENABLED, true); + ensureReasonDisabled(); +} + +function ensureReportBrokenSitePreffedOff() { + Services.prefs.setBoolPref(PREFS.REPORTER_ENABLED, false); +} + +function ensureSendMoreInfoEnabled() { + Services.prefs.setBoolPref(PREFS.SEND_MORE_INFO, true); +} + +function ensureSendMoreInfoDisabled() { + Services.prefs.setBoolPref(PREFS.SEND_MORE_INFO, false); +} + +function ensureReasonDisabled() { + Services.prefs.setIntPref(PREFS.REASON, 0); +} + +function ensureReasonOptional() { + Services.prefs.setIntPref(PREFS.REASON, 1); +} + +function ensureReasonRequired() { + Services.prefs.setIntPref(PREFS.REASON, 2); +} + +function isMenuItemEnabled(menuItem, itemDesc) { + ok(!menuItem.hidden, `${itemDesc} menu item is shown`); + ok(!menuItem.disabled, `${itemDesc} menu item is enabled`); +} + +function isMenuItemHidden(menuItem, itemDesc) { + ok( + !menuItem || menuItem.hidden || !BrowserTestUtils.isVisible(menuItem), + `${itemDesc} menu item is hidden` + ); +} + +function isMenuItemDisabled(menuItem, itemDesc) { + ok(!menuItem.hidden, `${itemDesc} menu item is shown`); + ok(menuItem.disabled, `${itemDesc} menu item is disabled`); +} + +function waitForWebcompatComTab(gBrowser) { + return BrowserTestUtils.waitForNewTab(gBrowser, NEW_REPORT_ENDPOINT_TEST_URL); +} + +class ReportBrokenSiteHelper { + sourceMenu = undefined; + win = undefined; + + constructor(sourceMenu) { + this.sourceMenu = sourceMenu; + this.win = sourceMenu.win; + } + + getViewNode(id) { + return PanelMultiView.getViewNode(this.win.document, id); + } + + get mainView() { + return this.getViewNode("report-broken-site-popup-mainView"); + } + + get sentView() { + return this.getViewNode("report-broken-site-popup-reportSentView"); + } + + get openPanel() { + return this.mainView?.closest("panel"); + } + + get opened() { + return this.openPanel?.hasAttribute("panelopen"); + } + + async click(triggerMenuItem) { + const window = triggerMenuItem.ownerGlobal; + await EventUtils.synthesizeMouseAtCenter(triggerMenuItem, {}, window); + } + + async open(triggerMenuItem) { + const shownPromise = BrowserTestUtils.waitForEvent( + this.mainView, + "ViewShown" + ); + const focusPromise = BrowserTestUtils.waitForEvent(this.URLInput, "focus"); + await this.click(triggerMenuItem); + await shownPromise; + await focusPromise; + await BrowserTestUtils.waitForCondition( + () => this.URLInput.selectionStart === 0 + ); + } + + async #assertClickAndViewChanges(button, view, newView, newFocus) { + ok(view.closest("panel").hasAttribute("panelopen"), "Panel is open"); + ok(BrowserTestUtils.isVisible(button), "Button is visible"); + ok(!button.disabled, "Button is enabled"); + const promises = []; + if (newView) { + if (newView.nodeName == "panel") { + promises.push(BrowserTestUtils.waitForEvent(newView, "popupshown")); + } else { + promises.push(BrowserTestUtils.waitForEvent(newView, "ViewShown")); + } + } else { + promises.push(BrowserTestUtils.waitForEvent(view, "ViewHiding")); + } + if (newFocus) { + promises.push(BrowserTestUtils.waitForEvent(newFocus, "focus")); + } + EventUtils.synthesizeMouseAtCenter(button, {}, this.win); + await Promise.all(promises); + } + + async awaitReportSentViewOpened() { + await Promise.all([ + BrowserTestUtils.waitForEvent(this.sentView, "ViewShown"), + BrowserTestUtils.waitForEvent(this.okayButton, "focus"), + ]); + } + + async clickSend() { + await this.#assertClickAndViewChanges( + this.sendButton, + this.mainView, + this.sentView, + this.okayButton + ); + } + + waitForSendMoreInfoTab() { + return BrowserTestUtils.waitForNewTab( + this.win.gBrowser, + NEW_REPORT_ENDPOINT_TEST_URL + ); + } + + async clickSendMoreInfo() { + const newTabPromise = waitForWebcompatComTab(this.win.gBrowser); + EventUtils.synthesizeMouseAtCenter(this.sendMoreInfoLink, {}, this.win); + const newTab = await newTabPromise; + const receivedData = await SpecialPowers.spawn( + newTab.linkedBrowser, + [], + async function () { + await content.wrappedJSObject.messageArrived; + return content.wrappedJSObject.message; + } + ); + this.win.gBrowser.removeCurrentTab(); + return receivedData; + } + + async clickCancel() { + await this.#assertClickAndViewChanges(this.cancelButton, this.mainView); + } + + async clickOkay() { + await this.#assertClickAndViewChanges(this.okayButton, this.sentView); + } + + async clickBack() { + await this.#assertClickAndViewChanges( + this.backButton, + this.sourceMenu.popup + ); + } + + isBackButtonEnabled() { + ok(BrowserTestUtils.isVisible(this.backButton), "Back button is visible"); + ok(!this.backButton.disabled, "Back button is enabled"); + } + + close() { + if (this.opened) { + this.openPanel?.hidePopup(false); + } + this.sourceMenu?.close(); + } + + // UI element getters + get URLInput() { + return this.getViewNode("report-broken-site-popup-url"); + } + + get URLInvalidMessage() { + return this.getViewNode("report-broken-site-popup-invalid-url-msg"); + } + + get reasonInput() { + return this.getViewNode("report-broken-site-popup-reason"); + } + + get reasonDropdownPopup() { + return this.win.document.getElementById("ContentSelectDropdown").menupopup; + } + + get reasonRequiredMessage() { + return this.getViewNode("report-broken-site-popup-missing-reason-msg"); + } + + get reasonLabelRequired() { + return this.getViewNode("report-broken-site-popup-reason-label"); + } + + get reasonLabelOptional() { + return this.getViewNode("report-broken-site-popup-reason-optional-label"); + } + + get descriptionTextarea() { + return this.getViewNode("report-broken-site-popup-description"); + } + + get sendMoreInfoLink() { + return this.getViewNode("report-broken-site-popup-send-more-info-link"); + } + + get backButton() { + return this.mainView.querySelector(".subviewbutton-back"); + } + + get sendButton() { + return this.getViewNode("report-broken-site-popup-send-button"); + } + + get cancelButton() { + return this.getViewNode("report-broken-site-popup-cancel-button"); + } + + get okayButton() { + return this.getViewNode("report-broken-site-popup-okay-button"); + } + + // Test helpers + + #setInput(input, value) { + input.value = value; + input.dispatchEvent( + new UIEvent("input", { bubbles: true, view: this.win }) + ); + } + + setURL(value) { + this.#setInput(this.URLInput, value); + } + + chooseReason(value) { + const item = this.getViewNode(`report-broken-site-popup-reason-${value}`); + this.reasonInput.selectedIndex = item.index; + } + + dismissDropdownPopup() { + const popup = this.reasonDropdownPopup; + const menuPromise = BrowserTestUtils.waitForPopupEvent(popup, "hidden"); + popup.hidePopup(); + return menuPromise; + } + + setDescription(value) { + this.#setInput(this.descriptionTextarea, value); + } + + isURL(expected) { + is(this.URLInput.value, expected); + } + + isURLInvalidMessageShown() { + ok( + BrowserTestUtils.isVisible(this.URLInvalidMessage), + "'Please enter a valid URL' message is shown" + ); + } + + isURLInvalidMessageHidden() { + ok( + !BrowserTestUtils.isVisible(this.URLInvalidMessage), + "'Please enter a valid URL' message is hidden" + ); + } + + isReasonNeededMessageShown() { + ok( + BrowserTestUtils.isVisible(this.reasonRequiredMessage), + "'Please choose a reason' message is shown" + ); + } + + isReasonNeededMessageHidden() { + ok( + !BrowserTestUtils.isVisible(this.reasonRequiredMessage), + "'Please choose a reason' message is hidden" + ); + } + + isSendButtonEnabled() { + ok(BrowserTestUtils.isVisible(this.sendButton), "Send button is visible"); + ok(!this.sendButton.disabled, "Send button is enabled"); + } + + isSendButtonDisabled() { + ok(BrowserTestUtils.isVisible(this.sendButton), "Send button is visible"); + ok(this.sendButton.disabled, "Send button is disabled"); + } + + isSendMoreInfoShown() { + ok( + BrowserTestUtils.isVisible(this.sendMoreInfoLink), + "send more info is shown" + ); + } + + isSendMoreInfoHidden() { + ok( + !BrowserTestUtils.isVisible(this.sendMoreInfoLink), + "send more info is hidden" + ); + } + + isSendMoreInfoShownOrHiddenAppropriately() { + if (Services.prefs.getBoolPref(PREFS.SEND_MORE_INFO)) { + this.isSendMoreInfoShown(); + } else { + this.isSendMoreInfoHidden(); + } + } + + isReasonHidden() { + ok( + !BrowserTestUtils.isVisible(this.reasonInput), + "reason drop-down is hidden" + ); + ok( + !BrowserTestUtils.isVisible(this.reasonLabelOptional), + "optional reason label is hidden" + ); + ok( + !BrowserTestUtils.isVisible(this.reasonLabelRequired), + "required reason label is hidden" + ); + } + + isReasonRequired() { + ok( + BrowserTestUtils.isVisible(this.reasonInput), + "reason drop-down is shown" + ); + ok( + !BrowserTestUtils.isVisible(this.reasonLabelOptional), + "optional reason label is hidden" + ); + ok( + BrowserTestUtils.isVisible(this.reasonLabelRequired), + "required reason label is shown" + ); + } + + isReasonOptional() { + ok( + BrowserTestUtils.isVisible(this.reasonInput), + "reason drop-down is shown" + ); + ok( + BrowserTestUtils.isVisible(this.reasonLabelOptional), + "optional reason label is shown" + ); + ok( + !BrowserTestUtils.isVisible(this.reasonLabelRequired), + "required reason label is hidden" + ); + } + + isReasonShownOrHiddenAppropriately() { + const pref = Services.prefs.getIntPref(PREFS.REASON); + if (pref == 2) { + this.isReasonOptional(); + } else if (pref == 1) { + this.isReasonOptional(); + } else { + this.isReasonHidden(); + } + } + + isDescription(expected) { + return this.descriptionTextarea.value == expected; + } + + isMainViewResetToCurrentTab() { + this.isURL(this.win.gBrowser.selectedBrowser.currentURI.spec); + this.isDescription(""); + this.isReasonShownOrHiddenAppropriately(); + this.isSendMoreInfoShownOrHiddenAppropriately(); + } +} + +class MenuHelper { + menuDescription = undefined; + + win = undefined; + + constructor(win = window) { + this.win = win; + } + + getViewNode(id) { + return PanelMultiView.getViewNode(this.win.document, id); + } + + get showsBackButton() { + return true; + } + + get reportBrokenSite() { + throw new Error("Should be defined in derived class"); + } + + get popup() { + throw new Error("Should be defined in derived class"); + } + + get opened() { + return this.popup?.hasAttribute("panelopen"); + } + + async open() {} + + async close() {} + + isReportBrokenSiteDisabled() { + return isMenuItemDisabled(this.reportBrokenSite, this.menuDescription); + } + + isReportBrokenSiteEnabled() { + return isMenuItemEnabled(this.reportBrokenSite, this.menuDescription); + } + + isReportBrokenSiteHidden() { + return isMenuItemHidden(this.reportBrokenSite, this.menuDescription); + } + + async clickReportBrokenSiteAndAwaitWebCompatTabData() { + const newTabPromise = waitForWebcompatComTab(this.win.gBrowser); + await this.clickReportBrokenSite(); + const newTab = await newTabPromise; + const receivedData = await SpecialPowers.spawn( + newTab.linkedBrowser, + [], + async function () { + await content.wrappedJSObject.messageArrived; + return content.wrappedJSObject.message; + } + ); + + this.win.gBrowser.removeCurrentTab(); + return receivedData; + } + + async clickReportBrokenSite() { + if (!this.opened) { + await this.open(); + } + isMenuItemEnabled(this.reportBrokenSite, this.menuDescription); + const rbs = new ReportBrokenSiteHelper(this); + await rbs.click(this.reportBrokenSite); + return rbs; + } + + async openReportBrokenSite() { + if (!this.opened) { + await this.open(); + } + isMenuItemEnabled(this.reportBrokenSite, this.menuDescription); + const rbs = new ReportBrokenSiteHelper(this); + await rbs.open(this.reportBrokenSite); + return rbs; + } + + async openAndPrefillReportBrokenSite(url = null, description = "") { + let rbs = await this.openReportBrokenSite(); + rbs.isMainViewResetToCurrentTab(); + if (url) { + rbs.setURL(url); + } + if (description) { + rbs.setDescription(description); + } + return rbs; + } +} + +class AppMenuHelper extends MenuHelper { + menuDescription = "AppMenu"; + + get reportBrokenSite() { + return this.getViewNode("appMenu-report-broken-site-button"); + } + + get popup() { + return this.win.document.getElementById("appMenu-popup"); + } + + async open() { + await new CustomizableUITestUtils(this.win).openMainMenu(); + } + + async close() { + if (this.opened) { + await new CustomizableUITestUtils(this.win).hideMainMenu(); + } + } +} + +class HelpMenuHelper extends MenuHelper { + menuDescription = "Help Menu"; + + get showsBackButton() { + return false; + } + + get reportBrokenSite() { + return this.win.document.getElementById("help_reportBrokenSite"); + } + + get popup() { + return this.getViewNode("PanelUI-helpView"); + } + + get helpMenu() { + return this.win.document.getElementById("menu_HelpPopup"); + } + + async openReportBrokenSite() { + // We can't actually open the Help menu properly in testing, so the best + // we can do to open its Report Broken Site panel is to force its DOM to be + // prepared, and then soft-click the Report Broken Site menuitem to open it. + await this.open(); + const shownPromise = BrowserTestUtils.waitForEvent( + this.win, + "ViewShown", + true, + e => e.target.classList.contains("report-broken-site-view") + ); + this.reportBrokenSite.click(); + await shownPromise; + return new ReportBrokenSiteHelper(this); + } + + async clickReportBrokenSite() { + await this.open(); + this.reportBrokenSite.click(); + return new ReportBrokenSiteHelper(this); + } + + async open() { + const { helpMenu } = this; + const promise = BrowserTestUtils.waitForEvent(helpMenu, "popupshown"); + + // This event-faking method was copied from browser_title_case_menus.js. + // We can't actually open the Help menu in testing, but this lets us + // force its DOM to be properly built. + helpMenu.dispatchEvent(new MouseEvent("popupshowing", { bubbles: true })); + helpMenu.dispatchEvent(new MouseEvent("popupshown", { bubbles: true })); + + await promise; + } + + async close() { + const { helpMenu } = this; + const promise = BrowserTestUtils.waitForPopupEvent(helpMenu, "hidden"); + + // (Also copied from browser_title_case_menus.js) + // Just for good measure, we'll fire the popuphiding/popuphidden events + // after we close the menupopups. + helpMenu.dispatchEvent(new MouseEvent("popuphiding", { bubbles: true })); + helpMenu.dispatchEvent(new MouseEvent("popuphidden", { bubbles: true })); + + await promise; + } +} + +class ProtectionsPanelHelper extends MenuHelper { + menuDescription = "Protections Panel"; + + get reportBrokenSite() { + this.win.gProtectionsHandler._initializePopup(); + return this.getViewNode("protections-popup-report-broken-site-button"); + } + + get popup() { + this.win.gProtectionsHandler._initializePopup(); + return this.win.document.getElementById("protections-popup"); + } + + async open() { + const promise = BrowserTestUtils.waitForEvent( + this.win, + "popupshown", + true, + e => e.target.id == "protections-popup" + ); + this.win.gProtectionsHandler.showProtectionsPopup(); + await promise; + } + + async close() { + if (this.opened) { + const popup = this.popup; + const promise = BrowserTestUtils.waitForPopupEvent(popup, "hidden"); + PanelMultiView.hidePopup(popup, false); + await promise; + } + } +} + +function AppMenu(win = window) { + return new AppMenuHelper(win); +} + +function HelpMenu(win = window) { + return new HelpMenuHelper(win); +} + +function ProtectionsPanel(win = window) { + return new ProtectionsPanelHelper(win); +} + +function pressKeyAndAwait(event, key, config = {}) { + const win = config.window || window; + if (!event.then) { + event = BrowserTestUtils.waitForEvent(win, event, config.timeout || 200); + } + EventUtils.synthesizeKey(key, config, win); + return event; +} + +async function pressKeyAndGetFocus(key, config = {}) { + return (await pressKeyAndAwait("focus", key, config)).target; +} + +async function tabTo(match, win = window) { + const config = { window: win }; + const { activeElement } = win.document; + if (activeElement?.matches(match)) { + return activeElement; + } + let initial = await pressKeyAndGetFocus("VK_TAB", config); + let target = initial; + do { + if (target.matches(match)) { + return target; + } + target = await pressKeyAndGetFocus("VK_TAB", config); + } while (target && target !== initial); + return undefined; +} + +function filterFrameworkDetectorFails(ping, expected) { + // the framework detector's frame-script may fail to run in low memory or other + // weird corner-cases, so we ignore the results in that case if they don't match. + if (!areObjectsEqual(ping.frameworks, expected.frameworks)) { + const { fastclick, mobify, marfeel } = ping.frameworks; + if (!fastclick && !mobify && !marfeel) { + console.info("Ignoring failure to get framework data"); + expected.frameworks = ping.frameworks; + } + } +} + +async function setupStrictETP() { + await UrlClassifierTestUtils.addTestTrackers(); + registerCleanupFunction(() => { + UrlClassifierTestUtils.cleanupTestTrackers(); + }); + + await SpecialPowers.pushPrefEnv({ + set: [ + ["security.mixed_content.block_active_content", true], + ["security.mixed_content.block_display_content", true], + ["security.mixed_content.upgrade_display_content", false], + [ + "urlclassifier.trackingTable", + "content-track-digest256,mochitest2-track-simple", + ], + ["browser.contentblocking.category", "strict"], + ], + }); +} + +// copied from browser/base/content/test/protectionsUI/head.js +function waitForContentBlockingEvent(numChanges = 1, win = null) { + if (!win) { + win = window; + } + return new Promise(resolve => { + let n = 0; + let listener = { + onContentBlockingEvent(webProgress, request, event) { + n = n + 1; + info( + `Received onContentBlockingEvent event: ${event} (${n} of ${numChanges})` + ); + if (n >= numChanges) { + win.gBrowser.removeProgressListener(listener); + resolve(n); + } + }, + }; + win.gBrowser.addProgressListener(listener); + }); +} diff --git a/src/zen/tests/mochitests/reportbrokensite/send.js b/src/zen/tests/mochitests/reportbrokensite/send.js new file mode 100644 index 0000000000..d3b7b1f502 --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/send.js @@ -0,0 +1,330 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Helper methods for testing sending reports with + * the Report Broken Site feature. + */ + +/* import-globals-from head.js */ + +"use strict"; + +const { Troubleshoot } = ChromeUtils.importESModule( + "resource://gre/modules/Troubleshoot.sys.mjs" +); + +function getSysinfoProperty(propertyName, defaultValue) { + try { + return Services.sysinfo.getProperty(propertyName); + } catch (e) {} + return defaultValue; +} + +function securityStringToArray(str) { + return str ? str.split(";") : null; +} + +function getExpectedGraphicsDevices(snapshot) { + const { graphics } = snapshot; + return [ + graphics.adapterDeviceID, + graphics.adapterVendorID, + graphics.adapterDeviceID2, + graphics.adapterVendorID2, + ] + .filter(i => i) + .sort(); +} + +function compareGraphicsDevices(expected, rawActual) { + const actual = rawActual + .map(({ deviceID, vendorID }) => [deviceID, vendorID]) + .flat() + .filter(i => i) + .sort(); + return areObjectsEqual(actual, expected); +} + +function getExpectedGraphicsDrivers(snapshot) { + const { graphics } = snapshot; + const expected = []; + for (let i = 1; i < 3; ++i) { + const version = graphics[`webgl${i}Version`]; + if (version && version != "-") { + expected.push(graphics[`webgl${i}Renderer`]); + expected.push(version); + } + } + return expected.filter(i => i).sort(); +} + +function compareGraphicsDrivers(expected, rawActual) { + const actual = rawActual + .map(({ renderer, version }) => [renderer, version]) + .flat() + .filter(i => i) + .sort(); + return areObjectsEqual(actual, expected); +} + +function getExpectedGraphicsFeatures(snapshot) { + const expected = {}; + for (let { name, log, status } of snapshot.graphics.featureLog.features) { + for (const item of log?.reverse() ?? []) { + if (item.failureId && item.status == status) { + status = `${status} (${item.message || item.failureId})`; + } + } + expected[name] = status; + } + return expected; +} + +async function getExpectedWebCompatInfo(tab, snapshot, fullAppData = false) { + const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + + const { application, graphics, intl, securitySoftware } = snapshot; + + const { fissionAutoStart, memorySizeBytes, updateChannel, userAgent } = + application; + + const app = { + defaultLocales: intl.localeService.available, + defaultUseragentString: userAgent, + fissionEnabled: fissionAutoStart, + }; + if (fullAppData) { + app.applicationName = application.name; + app.osArchitecture = getSysinfoProperty("arch", null); + app.osName = getSysinfoProperty("name", null); + app.osVersion = getSysinfoProperty("version", null); + app.updateChannel = updateChannel; + app.version = application.version; + } + + const hasTouchScreen = graphics.info.ApzTouchInput == 1; + + const { registeredAntiVirus, registeredAntiSpyware, registeredFirewall } = + securitySoftware; + + const browserInfo = { + addons: [], + app, + experiments: [], + graphics: { + devicesJson(actualStr) { + const expected = getExpectedGraphicsDevices(snapshot); + // If undefined is saved to the Glean value here, we'll get the string "undefined" (invalid JSON). + // We should stop using JSON like this in bug 1875185. + if (!actualStr || actualStr == "undefined") { + return !expected.length; + } + return compareGraphicsDevices(expected, JSON.parse(actualStr)); + }, + driversJson(actualStr) { + const expected = getExpectedGraphicsDrivers(snapshot); + // If undefined is saved to the Glean value here, we'll get the string "undefined" (invalid JSON). + // We should stop using JSON like this in bug 1875185. + if (!actualStr || actualStr == "undefined") { + return !expected.length; + } + return compareGraphicsDrivers(expected, JSON.parse(actualStr)); + }, + featuresJson(actualStr) { + const expected = getExpectedGraphicsFeatures(snapshot); + // If undefined is saved to the Glean value here, we'll get the string "undefined" (invalid JSON). + // We should stop using JSON like this in bug 1875185. + if (!actualStr || actualStr == "undefined") { + return !expected.length; + } + return areObjectsEqual(JSON.parse(actualStr), expected); + }, + hasTouchScreen, + monitorsJson(actualStr) { + const expected = gfxInfo.getMonitors(); + // If undefined is saved to the Glean value here, we'll get the string "undefined" (invalid JSON). + // We should stop using JSON like this in bug 1875185. + if (!actualStr || actualStr == "undefined") { + return !expected.length; + } + return areObjectsEqual(JSON.parse(actualStr), expected); + }, + }, + prefs: { + cookieBehavior: Services.prefs.getIntPref( + "network.cookie.cookieBehavior", + -1 + ), + forcedAcceleratedLayers: Services.prefs.getBoolPref( + "layers.acceleration.force-enabled", + false + ), + globalPrivacyControlEnabled: Services.prefs.getBoolPref( + "privacy.globalprivacycontrol.enabled", + false + ), + installtriggerEnabled: Services.prefs.getBoolPref( + "extensions.InstallTrigger.enabled", + false + ), + opaqueResponseBlocking: Services.prefs.getBoolPref( + "browser.opaqueResponseBlocking", + false + ), + resistFingerprintingEnabled: Services.prefs.getBoolPref( + "privacy.resistFingerprinting", + false + ), + softwareWebrender: Services.prefs.getBoolPref( + "gfx.webrender.software", + false + ), + thirdPartyCookieBlockingEnabled: Services.prefs.getBoolPref( + "network.cookie.cookieBehavior.optInPartitioning", + false + ), + thirdPartyCookieBlockingEnabledInPbm: Services.prefs.getBoolPref( + "network.cookie.cookieBehavior.optInPartitioning.pbmode", + false + ), + }, + security: { + antispyware: securityStringToArray(registeredAntiSpyware), + antivirus: securityStringToArray(registeredAntiVirus), + firewall: securityStringToArray(registeredFirewall), + }, + system: { + isTablet: getSysinfoProperty("tablet", false), + memory: Math.round(memorySizeBytes / 1024 / 1024), + }, + }; + + const tabInfo = await tab.linkedBrowser.ownerGlobal.SpecialPowers.spawn( + tab.linkedBrowser, + [], + async function () { + return { + devicePixelRatio: `${content.devicePixelRatio}`, + antitracking: { + blockList: "basic", + isPrivateBrowsing: false, + hasTrackingContentBlocked: false, + hasMixedActiveContentBlocked: false, + hasMixedDisplayContentBlocked: false, + btpHasPurgedSite: false, + etpCategory: "standard", + }, + frameworks: { + fastclick: false, + marfeel: false, + mobify: false, + }, + languages: content.navigator.languages, + useragentString: content.navigator.userAgent, + }; + } + ); + + browserInfo.graphics.devicePixelRatio = tabInfo.devicePixelRatio; + delete tabInfo.devicePixelRatio; + + return { browserInfo, tabInfo }; +} + +function extractPingData(branch) { + const data = {}; + for (const [name, value] of Object.entries(branch)) { + data[name] = value.testGetValue(); + } + return data; +} + +function extractBrokenSiteReportFromGleanPing(Glean) { + const ping = extractPingData(Glean.brokenSiteReport); + ping.tabInfo = extractPingData(Glean.brokenSiteReportTabInfo); + ping.tabInfo.antitracking = extractPingData( + Glean.brokenSiteReportTabInfoAntitracking + ); + ping.tabInfo.frameworks = extractPingData( + Glean.brokenSiteReportTabInfoFrameworks + ); + ping.browserInfo = { + addons: Array.from(Glean.brokenSiteReportBrowserInfo.addons.testGetValue()), + app: extractPingData(Glean.brokenSiteReportBrowserInfoApp), + graphics: extractPingData(Glean.brokenSiteReportBrowserInfoGraphics), + experiments: Array.from( + Glean.brokenSiteReportBrowserInfo.experiments.testGetValue() + ), + prefs: extractPingData(Glean.brokenSiteReportBrowserInfoPrefs), + security: extractPingData(Glean.brokenSiteReportBrowserInfoSecurity), + system: extractPingData(Glean.brokenSiteReportBrowserInfoSystem), + }; + return ping; +} + +async function testSend(tab, menu, expectedOverrides = {}) { + const url = expectedOverrides.url ?? menu.win.gBrowser.currentURI.spec; + const description = expectedOverrides.description ?? ""; + const breakageCategory = expectedOverrides.breakageCategory ?? null; + + let rbs = await menu.openAndPrefillReportBrokenSite(url, description); + + const snapshot = await Troubleshoot.snapshot(); + const expected = await getExpectedWebCompatInfo(tab, snapshot); + + expected.url = url; + expected.description = description; + expected.breakageCategory = breakageCategory; + + if (expectedOverrides.addons) { + expected.browserInfo.addons = expectedOverrides.addons; + } + + if (expectedOverrides.experiments) { + expected.browserInfo.experiments = expectedOverrides.experiments; + } + + if (expectedOverrides.antitracking) { + expected.tabInfo.antitracking = expectedOverrides.antitracking; + } + + if (expectedOverrides.frameworks) { + expected.tabInfo.frameworks = expectedOverrides.frameworks; + } + + if (breakageCategory) { + rbs.chooseReason(breakageCategory); + } + + Services.fog.testResetFOG(); + await GleanPings.brokenSiteReport.testSubmission( + () => { + const ping = extractBrokenSiteReportFromGleanPing(Glean); + + // sanity checks + const { browserInfo, tabInfo } = ping; + ok(ping.url?.length, "Got a URL"); + ok( + ["basic", "strict"].includes(tabInfo.antitracking.blockList), + "Got a blockList" + ); + ok(tabInfo.useragentString?.length, "Got a final UA string"); + ok( + browserInfo.app.defaultUseragentString?.length, + "Got a default UA string" + ); + + filterFrameworkDetectorFails(ping.tabInfo, expected.tabInfo); + + ok(areObjectsEqual(ping, expected), "ping matches expectations"); + }, + () => rbs.clickSend() + ); + + await rbs.clickOkay(); + + // re-opening the panel, the url and description should be reset + rbs = await menu.openReportBrokenSite(); + rbs.isMainViewResetToCurrentTab(); + rbs.close(); +} diff --git a/src/zen/tests/mochitests/reportbrokensite/sendMoreInfoTestEndpoint.html b/src/zen/tests/mochitests/reportbrokensite/sendMoreInfoTestEndpoint.html new file mode 100644 index 0000000000..39b1b3d25a --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/sendMoreInfoTestEndpoint.html @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/src/zen/tests/mochitests/reportbrokensite/send_more_info.js b/src/zen/tests/mochitests/reportbrokensite/send_more_info.js new file mode 100644 index 0000000000..32ef77a59f --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/send_more_info.js @@ -0,0 +1,305 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Helper methods for testing the "send more info" link + * of the Report Broken Site feature. + */ + +/* import-globals-from head.js */ +/* import-globals-from send.js */ + +"use strict"; + +Services.scriptloader.loadSubScript( + getRootDirectory(gTestPath) + "send.js", + this +); + +async function reformatExpectedWebCompatInfo(tab, overrides) { + const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); + const snapshot = await Troubleshoot.snapshot(); + const expected = await getExpectedWebCompatInfo(tab, snapshot, true); + const { browserInfo, tabInfo } = expected; + const { app, graphics, prefs, security } = browserInfo; + const { + applicationName, + defaultUseragentString, + fissionEnabled, + osArchitecture, + osName, + osVersion, + updateChannel, + version, + } = app; + const { devicePixelRatio, hasTouchScreen } = graphics; + const { antitracking, languages, useragentString } = tabInfo; + + const addons = overrides.addons || []; + const experiments = overrides.experiments || []; + const atOverrides = overrides.antitracking; + const blockList = atOverrides?.blockList ?? antitracking.blockList; + const hasMixedActiveContentBlocked = + atOverrides?.hasMixedActiveContentBlocked ?? + antitracking.hasMixedActiveContentBlocked; + const hasMixedDisplayContentBlocked = + atOverrides?.hasMixedDisplayContentBlocked ?? + antitracking.hasMixedDisplayContentBlocked; + const hasTrackingContentBlocked = + atOverrides?.hasTrackingContentBlocked ?? + antitracking.hasTrackingContentBlocked; + const isPrivateBrowsing = + atOverrides?.isPrivateBrowsing ?? antitracking.isPrivateBrowsing; + const btpHasPurgedSite = + atOverrides?.btpHasPurgedSite ?? antitracking.btpHasPurgedSite; + const etpCategory = atOverrides?.etpCategory ?? antitracking.etpCategory; + + const extra_labels = []; + const frameworks = overrides.frameworks ?? { + fastclick: false, + mobify: false, + marfeel: false, + }; + + // ignore the console log unless explicily testing for it. + const consoleLog = overrides.consoleLog ?? (() => true); + + const finalPrefs = {}; + for (const [key, pref] of Object.entries({ + cookieBehavior: "network.cookie.cookieBehavior", + forcedAcceleratedLayers: "layers.acceleration.force-enabled", + globalPrivacyControlEnabled: "privacy.globalprivacycontrol.enabled", + installtriggerEnabled: "extensions.InstallTrigger.enabled", + opaqueResponseBlocking: "browser.opaqueResponseBlocking", + resistFingerprintingEnabled: "privacy.resistFingerprinting", + softwareWebrender: "gfx.webrender.software", + thirdPartyCookieBlockingEnabled: + "network.cookie.cookieBehavior.optInPartitioning", + thirdPartyCookieBlockingEnabledInPbm: + "network.cookie.cookieBehavior.optInPartitioning.pbmode", + })) { + if (key in prefs) { + finalPrefs[pref] = prefs[key]; + } + } + + const reformatted = { + blockList, + details: { + additionalData: { + addons, + applicationName, + blockList, + buildId: snapshot.application.buildID, + devicePixelRatio: parseInt(devicePixelRatio), + experiments, + finalUserAgent: useragentString, + fissionEnabled, + gfxData: { + devices(actual) { + const devices = getExpectedGraphicsDevices(snapshot); + return compareGraphicsDevices(devices, actual); + }, + drivers(actual) { + const drvs = getExpectedGraphicsDrivers(snapshot); + return compareGraphicsDrivers(drvs, actual); + }, + features(actual) { + const features = getExpectedGraphicsFeatures(snapshot); + return areObjectsEqual(actual, features); + }, + hasTouchScreen, + monitors(actual) { + return areObjectsEqual(actual, gfxInfo.getMonitors()); + }, + }, + hasMixedActiveContentBlocked, + hasMixedDisplayContentBlocked, + hasTrackingContentBlocked, + btpHasPurgedSite, + isPB: isPrivateBrowsing, + etpCategory, + languages, + locales: snapshot.intl.localeService.available, + memoryMB: browserInfo.system.memory, + osArchitecture, + osName, + osVersion, + prefs: finalPrefs, + version, + }, + blockList, + channel: updateChannel, + consoleLog, + defaultUserAgent: defaultUseragentString, + frameworks, + hasTouchScreen, + "gfx.webrender.software": prefs.softwareWebrender, + "mixed active content blocked": hasMixedActiveContentBlocked, + "mixed passive content blocked": hasMixedDisplayContentBlocked, + "tracking content blocked": hasTrackingContentBlocked + ? `true (${blockList})` + : "false", + "btp has purged site": btpHasPurgedSite, + }, + extra_labels, + src: "desktop-reporter", + utm_campaign: "report-broken-site", + utm_source: "desktop-reporter", + }; + + const { gfxData } = reformatted.details.additionalData; + for (const optional of [ + "direct2DEnabled", + "directWriteEnabled", + "directWriteVersion", + "clearTypeParameters", + "targetFrameRate", + ]) { + if (optional in snapshot.graphics) { + gfxData[optional] = snapshot.graphics[optional]; + } + } + + // We only care about this pref on Linux right now on webcompat.com. + if (AppConstants.platform != "linux") { + delete finalPrefs["layers.acceleration.force-enabled"]; + } else { + reformatted.details["layers.acceleration.force-enabled"] = + finalPrefs["layers.acceleration.force-enabled"]; + } + + // Only bother adding the security key if it has any data + if (Object.values(security).filter(e => e).length) { + reformatted.details.additionalData.sec = security; + } + + const expectedCodecs = snapshot.media.codecSupportInfo + .replaceAll(" NONE", "") + .split("\n") + .sort() + .join("\n"); + if (expectedCodecs) { + reformatted.details.additionalData.gfxData.codecSupport = rawActual => { + const actual = Object.entries(rawActual) + .map( + ([ + name, + { hardwareDecode, softwareDecode, hardwareEncode, softwareEncode }, + ]) => + ( + `${name} ` + + `${softwareDecode ? "SWDEC " : ""}` + + `${hardwareDecode ? "HWDEC " : ""}` + + `${softwareEncode ? "SWENC " : ""}` + + `${hardwareEncode ? "HWENC " : ""}` + ).trim() + ) + .sort() + .join("\n"); + return areObjectsEqual(actual, expectedCodecs); + }; + } + + if (blockList != "basic") { + extra_labels.push(`type-tracking-protection-${blockList}`); + } + + if (overrides.expectNoTabDetails) { + delete reformatted.details.frameworks; + delete reformatted.details.consoleLog; + delete reformatted.details["mixed active content blocked"]; + delete reformatted.details["mixed passive content blocked"]; + delete reformatted.details["tracking content blocked"]; + delete reformatted.details["btp has purged site"]; + } else { + const { fastclick, mobify, marfeel } = frameworks; + if (fastclick) { + extra_labels.push("type-fastclick"); + reformatted.details.fastclick = true; + } + if (mobify) { + extra_labels.push("type-mobify"); + reformatted.details.mobify = true; + } + if (marfeel) { + extra_labels.push("type-marfeel"); + reformatted.details.marfeel = true; + } + } + + extra_labels.sort(); + + return reformatted; +} + +async function testSendMoreInfo(tab, menu, expectedOverrides = {}) { + const url = expectedOverrides.url ?? menu.win.gBrowser.currentURI.spec; + const description = expectedOverrides.description ?? ""; + + let rbs = await menu.openAndPrefillReportBrokenSite(url, description); + + const receivedData = await rbs.clickSendMoreInfo(); + await checkWebcompatComPayload( + tab, + url, + description, + expectedOverrides, + receivedData + ); + + // re-opening the panel, the url and description should be reset + rbs = await menu.openReportBrokenSite(); + rbs.isMainViewResetToCurrentTab(); + rbs.close(); +} + +async function testWebcompatComFallback(tab, menu) { + const url = menu.win.gBrowser.currentURI.spec; + const receivedData = + await menu.clickReportBrokenSiteAndAwaitWebCompatTabData(); + await checkWebcompatComPayload(tab, url, "", {}, receivedData); + menu.close(); +} + +async function checkWebcompatComPayload( + tab, + url, + description, + expectedOverrides, + receivedData +) { + const expected = await reformatExpectedWebCompatInfo(tab, expectedOverrides); + expected.url = url; + expected.description = description; + + // sanity checks + const { message } = receivedData; + const { details } = message; + const { additionalData } = details; + ok(message.url?.length, "Got a URL"); + ok(["basic", "strict"].includes(details.blockList), "Got a blockList"); + ok(additionalData.applicationName?.length, "Got an app name"); + ok(additionalData.osArchitecture?.length, "Got an OS arch"); + ok(additionalData.osName?.length, "Got an OS name"); + ok(additionalData.osVersion?.length, "Got an OS version"); + ok(additionalData.version?.length, "Got an app version"); + ok(details.channel?.length, "Got an app channel"); + ok(details.defaultUserAgent?.length, "Got a default UA string"); + ok(additionalData.finalUserAgent?.length, "Got a final UA string"); + + // If we're sending any tab-specific data (which includes console logs), + // check that there is also a valid screenshot. + if ("consoleLog" in details) { + const isScreenshotValid = await new Promise(done => { + var image = new Image(); + image.onload = () => done(image.width > 0); + image.onerror = () => done(false); + image.src = receivedData.screenshot; + }); + ok(isScreenshotValid, "Got a valid screenshot"); + } + + filterFrameworkDetectorFails(message.details, expected.details); + + ok(areObjectsEqual(message, expected), "sent info matches expectations"); +} diff --git a/src/zen/tests/mochitests/safebrowsing/browser.toml b/src/zen/tests/mochitests/safebrowsing/browser.toml new file mode 100644 index 0000000000..8745e7efcc --- /dev/null +++ b/src/zen/tests/mochitests/safebrowsing/browser.toml @@ -0,0 +1,14 @@ +[DEFAULT] +support-files = [ + "head.js", + "empty_file.html", +] + +["browser_bug400731.js"] + +["browser_bug415846.js"] +skip-if = ["true"] # Bug 1248632 + +["browser_mixedcontent_aboutblocked.js"] + +["browser_whitelisted.js"] diff --git a/src/zen/tests/mochitests/safebrowsing/browser_bug400731.js b/src/zen/tests/mochitests/safebrowsing/browser_bug400731.js new file mode 100644 index 0000000000..e3861bc7a7 --- /dev/null +++ b/src/zen/tests/mochitests/safebrowsing/browser_bug400731.js @@ -0,0 +1,65 @@ +/* Check presence of the "Ignore this warning" button */ + +function checkWarningState() { + return SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + return !!content.document.getElementById("ignore_warning_link"); + }); +} + +add_task(async function testMalware() { + await new Promise(resolve => waitForDBInit(resolve)); + + await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"); + + const url = "http://www.itisatrap.org/firefox/its-an-attack.html"; + BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url); + await BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + false, + url, + true + ); + + let buttonPresent = await checkWarningState(); + ok(buttonPresent, "Ignore warning link should be present for malware"); +}); + +add_task(async function testUnwanted() { + Services.prefs.setBoolPref("browser.safebrowsing.allowOverride", false); + + // Now launch the unwanted software test + const url = "http://www.itisatrap.org/firefox/unwanted.html"; + BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url); + await BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + false, + url, + true + ); + + // Confirm that "Ignore this warning" is visible - bug 422410 + let buttonPresent = await checkWarningState(); + ok( + !buttonPresent, + "Ignore warning link should be missing for unwanted software" + ); +}); + +add_task(async function testPhishing() { + Services.prefs.setBoolPref("browser.safebrowsing.allowOverride", true); + + // Now launch the phishing test + const url = "http://www.itisatrap.org/firefox/its-a-trap.html"; + BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url); + await BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + false, + url, + true + ); + + let buttonPresent = await checkWarningState(); + ok(buttonPresent, "Ignore warning link should be present for phishing"); + + gBrowser.removeCurrentTab(); +}); diff --git a/src/zen/tests/mochitests/safebrowsing/browser_bug415846.js b/src/zen/tests/mochitests/safebrowsing/browser_bug415846.js new file mode 100644 index 0000000000..8cd2ee36f6 --- /dev/null +++ b/src/zen/tests/mochitests/safebrowsing/browser_bug415846.js @@ -0,0 +1,98 @@ +/* Check for the correct behaviour of the report web forgery/not a web forgery +menu items. + +Mac makes this astonishingly painful to test since their help menu is special magic, +but we can at least test it on the other platforms.*/ + +const NORMAL_PAGE = "http://example.com"; +const PHISH_PAGE = "http://www.itisatrap.org/firefox/its-a-trap.html"; + +/** + * Opens a new tab and browses to some URL, tests for the existence + * of the phishing menu items, and then runs a test function to check + * the state of the menu once opened. This function will take care of + * opening and closing the menu. + * + * @param url (string) + * The URL to browse the tab to. + * @param testFn (function) + * The function to run once the menu has been opened. This + * function will be passed the "reportMenu" and "errorMenu" + * DOM nodes as arguments, in that order. This function + * should not yield anything. + * @returns Promise + */ +function check_menu_at_page(url, testFn) { + return BrowserTestUtils.withNewTab( + { + gBrowser, + url: "about:blank", + }, + async function (browser) { + // We don't get load events when the DocShell redirects to error + // pages, but we do get DOMContentLoaded, so we'll wait for that. + let dclPromise = SpecialPowers.spawn(browser, [], async function () { + await ContentTaskUtils.waitForEvent(this, "DOMContentLoaded", false); + }); + BrowserTestUtils.startLoadingURIString(browser, url); + await dclPromise; + + let menu = document.getElementById("menu_HelpPopup"); + ok(menu, "Help menu should exist"); + + let reportMenu = document.getElementById( + "menu_HelpPopup_reportPhishingtoolmenu" + ); + ok(reportMenu, "Report phishing menu item should exist"); + + let errorMenu = document.getElementById( + "menu_HelpPopup_reportPhishingErrortoolmenu" + ); + ok(errorMenu, "Report phishing error menu item should exist"); + + let menuOpen = BrowserTestUtils.waitForEvent(menu, "popupshown"); + menu.openPopup(null, "", 0, 0, false, null); + await menuOpen; + + testFn(reportMenu, errorMenu); + + let menuClose = BrowserTestUtils.waitForEvent(menu, "popuphidden"); + menu.hidePopup(); + await menuClose; + } + ); +} + +/** + * Tests that we show the "Report this page" menu item at a normal + * page. + */ +add_task(async function () { + await check_menu_at_page(NORMAL_PAGE, (reportMenu, errorMenu) => { + ok( + !reportMenu.hidden, + "Report phishing menu should be visible on normal sites" + ); + ok( + errorMenu.hidden, + "Report error menu item should be hidden on normal sites" + ); + }); +}); + +/** + * Tests that we show the "Report this page is okay" menu item at + * a reported attack site. + */ +add_task(async function () { + await check_menu_at_page(PHISH_PAGE, (reportMenu, errorMenu) => { + ok( + reportMenu.hidden, + "Report phishing menu should be hidden on phishing sites" + ); + ok( + !errorMenu.hidden, + "Report error menu item should be visible on phishing sites" + ); + }); +}); diff --git a/src/zen/tests/mochitests/safebrowsing/browser_mixedcontent_aboutblocked.js b/src/zen/tests/mochitests/safebrowsing/browser_mixedcontent_aboutblocked.js new file mode 100644 index 0000000000..5057cef19b --- /dev/null +++ b/src/zen/tests/mochitests/safebrowsing/browser_mixedcontent_aboutblocked.js @@ -0,0 +1,47 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +const SECURE_CONTAINER_URL = + "https://example.com/browser/browser/components/safebrowsing/content/test/empty_file.html"; + +add_task(async function testNormalBrowsing() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.safebrowsing.only_top_level", false]], + }); + + await BrowserTestUtils.withNewTab( + SECURE_CONTAINER_URL, + async function (browser) { + // Before we load the phish url, we have to make sure the hard-coded + // black list has been added to the database. + await new Promise(resolve => waitForDBInit(resolve)); + + let promise = new Promise(resolve => { + // Register listener before loading phish URL. + let removeFunc = BrowserTestUtils.addContentEventListener( + browser, + "AboutBlockedLoaded", + () => { + removeFunc(); + resolve(); + }, + { wantUntrusted: true } + ); + }); + + await SpecialPowers.spawn( + browser, + [PHISH_URL], + async function (aPhishUrl) { + // Create an iframe which is going to load a phish url. + let iframe = content.document.createElement("iframe"); + iframe.src = aPhishUrl; + content.document.body.appendChild(iframe); + } + ); + + await promise; + ok(true, "about:blocked is successfully loaded!"); + } + ); +}); diff --git a/src/zen/tests/mochitests/safebrowsing/browser_whitelisted.js b/src/zen/tests/mochitests/safebrowsing/browser_whitelisted.js new file mode 100644 index 0000000000..eb217d618a --- /dev/null +++ b/src/zen/tests/mochitests/safebrowsing/browser_whitelisted.js @@ -0,0 +1,46 @@ +/* Ensure that hostnames in the whitelisted pref are not blocked. */ + +const PREF_WHITELISTED_HOSTNAMES = "urlclassifier.skipHostnames"; +const TEST_PAGE = "http://www.itisatrap.org/firefox/its-an-attack.html"; +var tabbrowser = null; + +registerCleanupFunction(function () { + tabbrowser = null; + Services.prefs.clearUserPref(PREF_WHITELISTED_HOSTNAMES); + while (gBrowser.tabs.length > 1) { + gBrowser.removeCurrentTab(); + } +}); + +function testBlockedPage() { + info("Non-whitelisted pages must be blocked"); + ok(true, "about:blocked was shown"); +} + +function testWhitelistedPage(window) { + info("Whitelisted pages must be skipped"); + var getmeout_button = window.document.getElementById("getMeOutButton"); + var ignorewarning_button = window.document.getElementById( + "ignoreWarningButton" + ); + ok(!getmeout_button, "GetMeOut button not present"); + ok(!ignorewarning_button, "IgnoreWarning button not present"); +} + +add_task(async function testNormalBrowsing() { + tabbrowser = gBrowser; + let tab = (tabbrowser.selectedTab = BrowserTestUtils.addTab(tabbrowser)); + + info("Load a test page that's whitelisted"); + Services.prefs.setCharPref( + PREF_WHITELISTED_HOSTNAMES, + "example.com,www.ItIsaTrap.org,example.net" + ); + await promiseTabLoadEvent(tab, TEST_PAGE, "load"); + testWhitelistedPage(tab.ownerGlobal); + + info("Load a test page that's no longer whitelisted"); + Services.prefs.setCharPref(PREF_WHITELISTED_HOSTNAMES, ""); + await promiseTabLoadEvent(tab, TEST_PAGE, "AboutBlockedLoaded"); + testBlockedPage(tab.ownerGlobal); +}); diff --git a/src/zen/tests/mochitests/safebrowsing/empty_file.html b/src/zen/tests/mochitests/safebrowsing/empty_file.html new file mode 100644 index 0000000000..0dc101b533 --- /dev/null +++ b/src/zen/tests/mochitests/safebrowsing/empty_file.html @@ -0,0 +1 @@ + diff --git a/src/zen/tests/mochitests/safebrowsing/head.js b/src/zen/tests/mochitests/safebrowsing/head.js new file mode 100644 index 0000000000..ffbdb18d15 --- /dev/null +++ b/src/zen/tests/mochitests/safebrowsing/head.js @@ -0,0 +1,103 @@ +// This url must sync with the table, url in SafeBrowsing.sys.mjs addMozEntries +const PHISH_TABLE = "moztest-phish-simple"; +const PHISH_URL = "https://www.itisatrap.org/firefox/its-a-trap.html"; + +/** + * Waits for a load (or custom) event to finish in a given tab. If provided + * load an uri into the tab. + * + * @param tab + * The tab to load into. + * @param [optional] url + * The url to load, or the current url. + * @param [optional] event + * The load event type to wait for. Defaults to "load". + * @return {Promise} resolved when the event is handled. + * @resolves to the received event + * @rejects if a valid load event is not received within a meaningful interval + */ +function promiseTabLoadEvent(tab, url, eventType = "load") { + info(`Wait tab event: ${eventType}`); + + function handle(loadedUrl) { + if (loadedUrl === "about:blank" || (url && loadedUrl !== url)) { + info(`Skipping spurious load event for ${loadedUrl}`); + return false; + } + + info("Tab event received: load"); + return true; + } + + let loaded; + if (eventType === "load") { + loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, handle); + } else { + // No need to use handle. + loaded = BrowserTestUtils.waitForContentEvent( + tab.linkedBrowser, + eventType, + true, + undefined, + true + ); + } + + if (url) { + BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, url); + } + + return loaded; +} + +// This function is mostly ported from classifierCommon.js +// under toolkit/components/url-classifier/tests/mochitest. +function waitForDBInit(callback) { + // Since there are two cases that may trigger the callback, + // we have to carefully avoid multiple callbacks and observer + // leaking. + let didCallback = false; + function callbackOnce() { + if (!didCallback) { + Services.obs.removeObserver(obsFunc, "mozentries-update-finished"); + callback(); + } + didCallback = true; + } + + // The first part: listen to internal event. + function obsFunc() { + ok(true, "Received internal event!"); + callbackOnce(); + } + Services.obs.addObserver(obsFunc, "mozentries-update-finished"); + + // The second part: we might have missed the event. Just do + // an internal database lookup to confirm if the url has been + // added. + let principal = Services.scriptSecurityManager.createContentPrincipal( + Services.io.newURI(PHISH_URL), + {} + ); + + let dbService = Cc["@mozilla.org/url-classifier/dbservice;1"].getService( + Ci.nsIUrlClassifierDBService + ); + dbService.lookup(principal, PHISH_TABLE, value => { + if (value === PHISH_TABLE) { + ok(true, "DB lookup success!"); + callbackOnce(); + } + }); +} + +Services.prefs.setCharPref( + "urlclassifier.malwareTable", + "moztest-malware-simple,moztest-unwanted-simple,moztest-harmful-simple" +); +Services.prefs.setCharPref("urlclassifier.phishTable", "moztest-phish-simple"); +Services.prefs.setCharPref( + "urlclassifier.blockedTable", + "moztest-block-simple" +); +SafeBrowsing.init(); diff --git a/src/zen/tests/mochitests/shell/browser.toml b/src/zen/tests/mochitests/shell/browser.toml new file mode 100644 index 0000000000..4de6e830fb --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser.toml @@ -0,0 +1,101 @@ +[DEFAULT] + +["browser_1119088.js"] +support-files = ["mac_desktop_image.py"] +run-if = ["os == 'mac'"] +tags = "os_integration" +skip-if = ["os == 'mac' && os_version == '14.70' && processor == 'x86_64'"] # Bug 1869703 + +["browser_420786.js"] +run-if = ["os == 'linux'"] + +["browser_633221.js"] +run-if = ["os == 'linux'"] + +["browser_createWindowsShortcut.js"] +run-if = ["os == 'win'"] + +["browser_doesAppNeedPin.js"] + +["browser_headless_screenshot_1.js"] +support-files = [ + "head.js", + "headless.html", +] +skip-if = [ + "os == 'win'", + "ccov", + "tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449 +] +tags = "os_integration" + +["browser_headless_screenshot_2.js"] +support-files = [ + "head.js", + "headless.html", +] +skip-if = [ + "os == 'win'", + "ccov", + "tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449 +] + +["browser_headless_screenshot_3.js"] +support-files = [ + "head.js", + "headless.html", +] +skip-if = [ + "os == 'win'", + "ccov", + "tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449 +] + +["browser_headless_screenshot_4.js"] +support-files = [ + "head.js", + "headless.html", +] +skip-if = [ + "os == 'win'", + "ccov", + "tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449 +] + +["browser_headless_screenshot_cross_origin.js"] +support-files = [ + "head.js", + "headless_cross_origin.html", + "headless_iframe.html", +] +skip-if = [ + "os == 'win'", + "ccov", + "tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449 +] + +["browser_headless_screenshot_redirect.js"] +support-files = [ + "head.js", + "headless.html", + "headless_redirect.html", + "headless_redirect.html^headers^", +] +skip-if = [ + "os == 'win'", + "ccov", + "tsan", # Bug 1429950, Bug 1583315, Bug 1696109, Bug 1701449 +] + +["browser_processAUMID.js"] +run-if = ["os == 'win'"] + +["browser_setDefaultBrowser.js"] +tags = "os_integration" + +["browser_setDefaultPDFHandler.js"] +run-if = ["os == 'win'"] +tags = "os_integration" + +["browser_setDesktopBackgroundPreview.js"] +tags = "os_integration" diff --git a/src/zen/tests/mochitests/shell/browser_1119088.js b/src/zen/tests/mochitests/shell/browser_1119088.js new file mode 100644 index 0000000000..259176b6ab --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_1119088.js @@ -0,0 +1,179 @@ +// Where we save the desktop background to (~/Pictures). +const NS_OSX_PICTURE_DOCUMENTS_DIR = "Pct"; + +// Paths used to run the CLI command (python script) that is used to +// 1) check the desktop background image matches what we set it to via +// nsIShellService::setDesktopBackground() and +// 2) revert the desktop background image to the OS default + +let kPythonPath = "/usr/bin/python"; +if (AppConstants.isPlatformAndVersionAtLeast("macosx", 23.0)) { + kPythonPath = "/usr/local/bin/python3"; +} + +const kDesktopCheckerScriptPath = + "browser/browser/components/shell/test/mac_desktop_image.py"; +const kDefaultBackgroundImage_10_14 = + "/Library/Desktop Pictures/Solid Colors/Teal.png"; +const kDefaultBackgroundImage_10_15 = + "/System/Library/Desktop Pictures/Solid Colors/Teal.png"; + +ChromeUtils.defineESModuleGetters(this, { + FileUtils: "resource://gre/modules/FileUtils.sys.mjs", +}); + +function getPythonExecutableFile() { + let python = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + info(`Using python at location ${kPythonPath}`); + python.initWithPath(kPythonPath); + return python; +} + +function createProcess() { + return Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); +} + +// Use a CLI command to set the desktop background to |imagePath|. Returns the +// exit code of the CLI command which reflects whether or not the background +// image was successfully set. Returns 0 on success. +function setDesktopBackgroundCLI(imagePath) { + let setBackgroundProcess = createProcess(); + setBackgroundProcess.init(getPythonExecutableFile()); + let args = [ + kDesktopCheckerScriptPath, + "--verbose", + "--set-background-image", + imagePath, + ]; + setBackgroundProcess.run(true, args, args.length); + return setBackgroundProcess.exitValue; +} + +// Check the desktop background is |imagePath| using a CLI command. +// Returns the exit code of the CLI command which reflects whether or not +// the provided image path matches the path of the current desktop background +// image. A return value of 0 indicates success/match. +function checkDesktopBackgroundCLI(imagePath) { + let checkBackgroundProcess = createProcess(); + checkBackgroundProcess.init(getPythonExecutableFile()); + let args = [ + kDesktopCheckerScriptPath, + "--verbose", + "--check-background-image", + imagePath, + ]; + checkBackgroundProcess.run(true, args, args.length); + return checkBackgroundProcess.exitValue; +} + +// Use the python script to set/check the desktop background is |imagePath| +function setAndCheckDesktopBackgroundCLI(imagePath) { + Assert.ok(FileUtils.File(imagePath).exists(), `${imagePath} exists`); + + let setExitCode = setDesktopBackgroundCLI(imagePath); + Assert.equal(setExitCode, 0, `Setting background via CLI to ${imagePath}`); + + let checkExitCode = checkDesktopBackgroundCLI(imagePath); + Assert.equal(checkExitCode, 0, `Checking background via CLI is ${imagePath}`); +} + +// Restore the automation default background image. i.e., the default used +// in the automated test environment, not the OS default. +function restoreDefaultBackground() { + let defaultBackgroundPath; + if (AppConstants.isPlatformAndVersionAtLeast("macosx", 19)) { + defaultBackgroundPath = kDefaultBackgroundImage_10_15; + } else { + defaultBackgroundPath = kDefaultBackgroundImage_10_14; + } + setAndCheckDesktopBackgroundCLI(defaultBackgroundPath); +} + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["test.wait300msAfterTabSwitch", true]], + }); +}); + +/** + * Tests "Set As Desktop Background" platform implementation on macOS. + * + * Sets the desktop background image to the browser logo from the about:logo + * page and verifies it was set successfully. Setting the desktop background + * (which uses the nsIShellService::setDesktopBackground() interface method) + * downloads the image to ~/Pictures using a unique file name and sets the + * desktop background to the downloaded file leaving the download in place. + * After setDesktopBackground() is called, the test uses a python script to + * validate that the current desktop background is in fact set to the + * downloaded logo. + */ +add_task(async function () { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "about:logo", + }, + async () => { + let dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService( + Ci.nsIDirectoryServiceProvider + ); + let uuidGenerator = Services.uuid; + let shellSvc = Cc["@mozilla.org/browser/shell-service;1"].getService( + Ci.nsIShellService + ); + + // Ensure we are starting with the default background. Log a + // failure if we can not set the background to the default, but + // ignore the case where the background is not already set as that + // that may be due to a previous test failure. + restoreDefaultBackground(); + + // Generate a UUID (with non-alphanumberic characters removed) to build + // up a filename for the desktop background. Use a UUID to distinguish + // between runs so we won't be confused by images that were not properly + // cleaned up after previous runs. + let uuid = uuidGenerator.generateUUID().toString().replace(/\W/g, ""); + + // Set the background image path to be $HOME/Pictures/.png. + // nsIShellService.setDesktopBackground() downloads the image to this + // path and then sets it as the desktop background image, leaving the + // image in place. + let backgroundImage = dirSvc.getFile(NS_OSX_PICTURE_DOCUMENTS_DIR, {}); + backgroundImage.append(uuid + ".png"); + if (backgroundImage.exists()) { + backgroundImage.remove(false); + } + + // For simplicity, we're going to reach in and access the image on the + // page directly, which means the page shouldn't be running in a remote + // browser. Thankfully, about:logo runs in the parent process for now. + Assert.ok( + !gBrowser.selectedBrowser.isRemoteBrowser, + "image can be accessed synchronously from the parent process" + ); + let image = gBrowser.selectedBrowser.contentDocument.images[0]; + + info(`Setting/saving desktop background to ${backgroundImage.path}`); + + // Saves the file in ~/Pictures + shellSvc.setDesktopBackground(image, 0, backgroundImage.leafName); + + await BrowserTestUtils.waitForCondition(() => backgroundImage.exists()); + info(`${backgroundImage.path} downloaded`); + Assert.ok( + FileUtils.File(backgroundImage.path).exists(), + `${backgroundImage.path} exists` + ); + + // Check that the desktop background image is the image we set above. + let exitCode = checkDesktopBackgroundCLI(backgroundImage.path); + Assert.equal(exitCode, 0, `background should be ${backgroundImage.path}`); + + // Restore the background image to the Mac default. + restoreDefaultBackground(); + + // We no longer need the downloaded image. + backgroundImage.remove(false); + } + ); +}); diff --git a/src/zen/tests/mochitests/shell/browser_420786.js b/src/zen/tests/mochitests/shell/browser_420786.js new file mode 100644 index 0000000000..b9becb49c1 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_420786.js @@ -0,0 +1,101 @@ +const DG_BACKGROUND = "/desktop/gnome/background"; +const DG_IMAGE_KEY = DG_BACKGROUND + "/picture_filename"; +const DG_OPTION_KEY = DG_BACKGROUND + "/picture_options"; +const DG_DRAW_BG_KEY = DG_BACKGROUND + "/draw_background"; + +const GS_BG_SCHEMA = "org.gnome.desktop.background"; +const GS_IMAGE_KEY = "picture-uri"; +const GS_OPTION_KEY = "picture-options"; +const GS_DRAW_BG_KEY = "draw-background"; + +add_task(async function () { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "about:logo", + }, + () => { + var brandName = Services.strings + .createBundle("chrome://branding/locale/brand.properties") + .GetStringFromName("brandShortName"); + + var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService( + Ci.nsIDirectoryServiceProvider + ); + var homeDir = dirSvc.getFile("Home", {}); + + var wpFile = homeDir.clone(); + wpFile.append(brandName + "_wallpaper.png"); + + // Backup the existing wallpaper so that this test doesn't change the user's + // settings. + var wpFileBackup = homeDir.clone(); + wpFileBackup.append(brandName + "_wallpaper.png.backup"); + + if (wpFileBackup.exists()) { + wpFileBackup.remove(false); + } + + if (wpFile.exists()) { + wpFile.copyTo(null, wpFileBackup.leafName); + } + + var shell = Cc["@mozilla.org/browser/shell-service;1"] + .getService(Ci.nsIShellService) + .QueryInterface(Ci.nsIGNOMEShellService); + + // For simplicity, we're going to reach in and access the image on the + // page directly, which means the page shouldn't be running in a remote + // browser. Thankfully, about:logo runs in the parent process for now. + Assert.ok( + !gBrowser.selectedBrowser.isRemoteBrowser, + "image can be accessed synchronously from the parent process" + ); + + var image = content.document.images[0]; + + let checkWallpaper, restoreSettings; + try { + const prevImage = shell.getGSettingsString(GS_BG_SCHEMA, GS_IMAGE_KEY); + const prevOption = shell.getGSettingsString( + GS_BG_SCHEMA, + GS_OPTION_KEY + ); + + checkWallpaper = function (position, expectedGSettingsPosition) { + shell.setDesktopBackground(image, position, ""); + ok(wpFile.exists(), "Wallpaper was written to disk"); + is( + shell.getGSettingsString(GS_BG_SCHEMA, GS_IMAGE_KEY), + encodeURI("file://" + wpFile.path), + "Wallpaper file GSettings key is correct" + ); + is( + shell.getGSettingsString(GS_BG_SCHEMA, GS_OPTION_KEY), + expectedGSettingsPosition, + "Wallpaper position GSettings key is correct" + ); + }; + + restoreSettings = function () { + shell.setGSettingsString(GS_BG_SCHEMA, GS_IMAGE_KEY, prevImage); + shell.setGSettingsString(GS_BG_SCHEMA, GS_OPTION_KEY, prevOption); + }; + } catch (e) {} + + checkWallpaper(Ci.nsIShellService.BACKGROUND_TILE, "wallpaper"); + checkWallpaper(Ci.nsIShellService.BACKGROUND_STRETCH, "stretched"); + checkWallpaper(Ci.nsIShellService.BACKGROUND_CENTER, "centered"); + checkWallpaper(Ci.nsIShellService.BACKGROUND_FILL, "zoom"); + checkWallpaper(Ci.nsIShellService.BACKGROUND_FIT, "scaled"); + checkWallpaper(Ci.nsIShellService.BACKGROUND_SPAN, "spanned"); + + restoreSettings(); + + // Restore files + if (wpFileBackup.exists()) { + wpFileBackup.moveTo(null, wpFile.leafName); + } + } + ); +}); diff --git a/src/zen/tests/mochitests/shell/browser_633221.js b/src/zen/tests/mochitests/shell/browser_633221.js new file mode 100644 index 0000000000..dbc66e2864 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_633221.js @@ -0,0 +1,11 @@ +function test() { + ShellService.setDefaultBrowser(false); + ok( + ShellService.isDefaultBrowser(true, false), + "we got here and are the default browser" + ); + ok( + ShellService.isDefaultBrowser(true, true), + "we got here and are the default browser" + ); +} diff --git a/src/zen/tests/mochitests/shell/browser_createWindowsShortcut.js b/src/zen/tests/mochitests/shell/browser_createWindowsShortcut.js new file mode 100644 index 0000000000..0b951bde24 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_createWindowsShortcut.js @@ -0,0 +1,218 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +ChromeUtils.defineESModuleGetters(this, { + FileTestUtils: "resource://testing-common/FileTestUtils.sys.mjs", + MockRegistrar: "resource://testing-common/MockRegistrar.sys.mjs", +}); + +const gBase = Services.dirsvc.get("ProfD", Ci.nsIFile); +gBase.append("CreateWindowsShortcut"); +createDirectory(gBase); + +const gTmpDir = Services.dirsvc.get("TmpD", Ci.nsIFile); + +const gDirectoryServiceProvider = { + getFile(prop, persistent) { + persistent.value = false; + + // We only expect a narrow range of calls. + let folder = gBase.clone(); + switch (prop) { + case "Progs": + folder.append("Programs"); + break; + case "Desk": + folder.append("Desktop"); + break; + case "UpdRootD": + // We really want DataRoot, but UpdateSubdir is what we usually get. + folder.append("DataRoot"); + folder.append("UpdateDir"); + folder.append("UpdateSubdir"); + break; + case "ProfD": + // Used by test infrastructure. + folder = folder.parent; + break; + case "TmpD": + // Used by FileTestUtils. + folder = gTmpDir; + break; + default: + console.error(`Access to unexpected directory '${prop}'`); + return Cr.NS_ERROR_FAILURE; + } + + createDirectory(folder); + return folder; + }, + QueryInterface: ChromeUtils.generateQI([Ci.nsIDirectoryServiceProvider]), +}; + +add_setup(() => { + Services.dirsvc + .QueryInterface(Ci.nsIDirectoryService) + .registerProvider(gDirectoryServiceProvider); +}); + +registerCleanupFunction(() => { + gBase.remove(true); + Services.dirsvc + .QueryInterface(Ci.nsIDirectoryService) + .unregisterProvider(gDirectoryServiceProvider); +}); + +add_task(async function test_CreateWindowsShortcut() { + const DEST = "browser_createWindowsShortcut_TestFile.lnk"; + + const file = FileTestUtils.getTempFile("program.exe"); + const iconPath = FileTestUtils.getTempFile("program.ico"); + + let shortcut; + + const defaults = { + shellService: Cc["@mozilla.org/toolkit/shell-service;1"].getService(), + targetFile: file, + iconFile: iconPath, + description: "made by browser_createWindowsShortcut.js", + aumid: "TESTTEST", + }; + + shortcut = Services.dirsvc.get("Progs", Ci.nsIFile); + shortcut.append(DEST); + await testShortcut({ + shortcutFile: shortcut, + relativePath: DEST, + specialFolder: "Programs", + logHeader: "STARTMENU", + ...defaults, + }); + + let subdir = Services.dirsvc.get("Progs", Ci.nsIFile); + subdir.append("Shortcut Test"); + tryRemove(subdir); + + shortcut = subdir.clone(); + shortcut.append(DEST); + await testShortcut({ + shortcutFile: shortcut, + relativePath: "Shortcut Test\\" + DEST, + specialFolder: "Programs", + logHeader: "STARTMENU", + ...defaults, + }); + tryRemove(subdir); + + shortcut = Services.dirsvc.get("Desk", Ci.nsIFile); + shortcut.append(DEST); + await testShortcut({ + shortcutFile: shortcut, + relativePath: DEST, + specialFolder: "Desktop", + logHeader: "DESKTOP", + ...defaults, + }); +}); + +async function testShortcut({ + shortcutFile, + relativePath, + specialFolder, + logHeader, + + // Generally provided by the defaults. + shellService, + targetFile, + iconFile, + description, + aumid, +}) { + // If it already exists, remove it. + tryRemove(shortcutFile); + + await shellService.createShortcut( + targetFile, + [], + description, + iconFile, + 0, + aumid, + specialFolder, + relativePath + ); + ok( + shortcutFile.exists(), + `${specialFolder}\\${relativePath}: Shortcut should exist` + ); + ok( + queryShortcutLog(relativePath, logHeader), + `${specialFolder}\\${relativePath}: Shortcut log entry was added` + ); + await shellService.deleteShortcut(specialFolder, relativePath); + ok( + !shortcutFile.exists(), + `${specialFolder}\\${relativePath}: Shortcut does not exist after deleting` + ); + ok( + !queryShortcutLog(relativePath, logHeader), + `${specialFolder}\\${relativePath}: Shortcut log entry was removed` + ); +} + +function queryShortcutLog(aShortcutName, aSection) { + const parserFactory = Cc[ + "@mozilla.org/xpcom/ini-parser-factory;1" + ].createInstance(Ci.nsIINIParserFactory); + + const dir = Services.dirsvc.get("UpdRootD", Ci.nsIFile).parent.parent; + const enumerator = dir.directoryEntries; + + for (const file of enumerator) { + // We don't know the user's SID from JS-land, so just look at all of them. + if (!file.path.match(/[^_]+_S[^_]*_shortcuts.ini/)) { + continue; + } + + const parser = parserFactory.createINIParser(file); + parser.QueryInterface(Ci.nsIINIParser); + parser.QueryInterface(Ci.nsIINIParserWriter); + + for (let i = 0; ; i++) { + try { + let string = parser.getString(aSection, `Shortcut${i}`); + if (string == aShortcutName) { + enumerator.close(); + return true; + } + } catch (e) { + // The key didn't exist, stop here. + break; + } + } + } + + enumerator.close(); + return false; +} + +function createDirectory(aFolder) { + try { + aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755); + } catch (e) { + if (e.result != Cr.NS_ERROR_FILE_ALREADY_EXISTS) { + throw e; + } + } +} + +function tryRemove(file) { + try { + file.remove(false); + return true; + } catch (e) { + return false; + } +} diff --git a/src/zen/tests/mochitests/shell/browser_doesAppNeedPin.js b/src/zen/tests/mochitests/shell/browser_doesAppNeedPin.js new file mode 100644 index 0000000000..2a261988a9 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_doesAppNeedPin.js @@ -0,0 +1,54 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +ChromeUtils.defineESModuleGetters(this, { + NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", + NimbusTestUtils: "resource://testing-common/NimbusTestUtils.sys.mjs", +}); + +let defaultValue; +add_task(async function default_need() { + defaultValue = await ShellService.doesAppNeedPin(); + + Assert.notStrictEqual( + defaultValue, + undefined, + "Got a default app need pin value" + ); +}); + +add_task(async function remote_disable() { + if (defaultValue === false) { + info("Default pin already false, so nothing to test"); + return; + } + + let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig( + { + featureId: NimbusFeatures.shellService.featureId, + value: { disablePin: true, enabled: true }, + }, + { isRollout: true } + ); + + Assert.equal( + await ShellService.doesAppNeedPin(), + false, + "Pinning disabled via nimbus" + ); + + await doCleanup(); +}); + +add_task(async function restore_default() { + if (defaultValue === undefined) { + info("No default pin value set, so nothing to test"); + return; + } + + Assert.equal( + await ShellService.doesAppNeedPin(), + defaultValue, + "Pinning restored to original" + ); +}); diff --git a/src/zen/tests/mochitests/shell/browser_headless_screenshot_1.js b/src/zen/tests/mochitests/shell/browser_headless_screenshot_1.js new file mode 100644 index 0000000000..b5f84f0f66 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_headless_screenshot_1.js @@ -0,0 +1,74 @@ +"use strict"; + +add_task(async function () { + // Test all four basic variations of the "screenshot" argument + // when a file path is specified. + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-screenshot", + screenshotPath, + ], + screenshotPath + ); + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + `-screenshot=${screenshotPath}`, + ], + screenshotPath + ); + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "--screenshot", + screenshotPath, + ], + screenshotPath + ); + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + `--screenshot=${screenshotPath}`, + ], + screenshotPath + ); + + // Test when the requested URL redirects + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless_redirect.html", + "-screenshot", + screenshotPath, + ], + screenshotPath + ); + + // Test with additional command options + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-screenshot", + screenshotPath, + "-attach-console", + ], + screenshotPath + ); + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-attach-console", + "-screenshot", + screenshotPath, + "-headless", + ], + screenshotPath + ); +}); diff --git a/src/zen/tests/mochitests/shell/browser_headless_screenshot_2.js b/src/zen/tests/mochitests/shell/browser_headless_screenshot_2.js new file mode 100644 index 0000000000..871895b45d --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_headless_screenshot_2.js @@ -0,0 +1,48 @@ +"use strict"; +add_task(async function () { + const cwdScreenshotPath = PathUtils.join( + Services.dirsvc.get("CurWorkD", Ci.nsIFile).path, + "screenshot.png" + ); + + // Test variations of the "screenshot" argument when a file path + // isn't specified. + await testFileCreationPositive( + [ + "-screenshot", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + ], + cwdScreenshotPath + ); + await testFileCreationPositive( + [ + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-screenshot", + ], + cwdScreenshotPath + ); + await testFileCreationPositive( + [ + "--screenshot", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + ], + cwdScreenshotPath + ); + await testFileCreationPositive( + [ + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "--screenshot", + ], + cwdScreenshotPath + ); + + // Test with additional command options + await testFileCreationPositive( + [ + "--screenshot", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-attach-console", + ], + cwdScreenshotPath + ); +}); diff --git a/src/zen/tests/mochitests/shell/browser_headless_screenshot_3.js b/src/zen/tests/mochitests/shell/browser_headless_screenshot_3.js new file mode 100644 index 0000000000..b55635652d --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_headless_screenshot_3.js @@ -0,0 +1,59 @@ +"use strict"; + +add_task(async function () { + const cwdScreenshotPath = PathUtils.join( + Services.dirsvc.get("CurWorkD", Ci.nsIFile).path, + "screenshot.png" + ); + + // Test invalid URL arguments (either no argument or too many arguments). + await testFileCreationNegative(["-screenshot"], cwdScreenshotPath); + await testFileCreationNegative( + [ + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "http://mochi.test:8888/headless.html", + "-screenshot", + ], + cwdScreenshotPath + ); + + // Test all four basic variations of the "window-size" argument. + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-screenshot", + "-window-size", + "800", + ], + cwdScreenshotPath + ); + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-screenshot", + "-window-size=800", + ], + cwdScreenshotPath + ); + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-screenshot", + "--window-size", + "800", + ], + cwdScreenshotPath + ); + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-screenshot", + "--window-size=800", + ], + cwdScreenshotPath + ); +}); diff --git a/src/zen/tests/mochitests/shell/browser_headless_screenshot_4.js b/src/zen/tests/mochitests/shell/browser_headless_screenshot_4.js new file mode 100644 index 0000000000..4b93ba516e --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_headless_screenshot_4.js @@ -0,0 +1,31 @@ +"use strict"; + +add_task(async function () { + const cwdScreenshotPath = PathUtils.join( + Services.dirsvc.get("CurWorkD", Ci.nsIFile).path, + "screenshot.png" + ); + // Test other variations of the "window-size" argument. + await testWindowSizePositive(800, 600); + await testWindowSizePositive(1234); + await testFileCreationNegative( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-screenshot", + "-window-size", + "hello", + ], + cwdScreenshotPath + ); + await testFileCreationNegative( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-screenshot", + "-window-size", + "800,", + ], + cwdScreenshotPath + ); +}); diff --git a/src/zen/tests/mochitests/shell/browser_headless_screenshot_cross_origin.js b/src/zen/tests/mochitests/shell/browser_headless_screenshot_cross_origin.js new file mode 100644 index 0000000000..9547773581 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_headless_screenshot_cross_origin.js @@ -0,0 +1,9 @@ +"use strict"; + +add_task(async function () { + // Test cross origin iframes work. + await testGreen( + "http://mochi.test:8888/browser/browser/components/shell/test/headless_cross_origin.html", + screenshotPath + ); +}); diff --git a/src/zen/tests/mochitests/shell/browser_headless_screenshot_redirect.js b/src/zen/tests/mochitests/shell/browser_headless_screenshot_redirect.js new file mode 100644 index 0000000000..c50b847b62 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_headless_screenshot_redirect.js @@ -0,0 +1,14 @@ +"use strict"; + +add_task(async function () { + // Test when the requested URL redirects + await testFileCreationPositive( + [ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless_redirect.html", + "-screenshot", + screenshotPath, + ], + screenshotPath + ); +}); diff --git a/src/zen/tests/mochitests/shell/browser_processAUMID.js b/src/zen/tests/mochitests/shell/browser_processAUMID.js new file mode 100644 index 0000000000..cf98316f81 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_processAUMID.js @@ -0,0 +1,27 @@ +/* Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Bug 1950734 tracks how calling PinCurrentAppToTaskbarWin11 + * on MSIX may cause the process AUMID to be unnecessarily changed. + * This test verifies that the behaviour will no longer happen + */ + +ChromeUtils.defineESModuleGetters(this, { + ShellService: "moz-src:///browser/components/shell/ShellService.sys.mjs", +}); + +add_task(async function test_processAUMID() { + let processAUMID = ShellService.checkCurrentProcessAUMIDForTesting(); + + // This function will trigger the relevant code paths that + // incorrectly changes the process AUMID on MSIX, prior to + // Bug 1950734 being fixed + await ShellService.checkPinCurrentAppToTaskbarAsync(false); + + is( + processAUMID, + ShellService.checkCurrentProcessAUMIDForTesting(), + "The process AUMID should not be changed" + ); +}); diff --git a/src/zen/tests/mochitests/shell/browser_setDefaultBrowser.js b/src/zen/tests/mochitests/shell/browser_setDefaultBrowser.js new file mode 100644 index 0000000000..731bb7f1e6 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_setDefaultBrowser.js @@ -0,0 +1,239 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +ChromeUtils.defineESModuleGetters(this, { + ASRouter: "resource:///modules/asrouter/ASRouter.sys.mjs", + ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs", + NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", + NimbusTestUtils: "resource://testing-common/NimbusTestUtils.sys.mjs", + sinon: "resource://testing-common/Sinon.sys.mjs", +}); + +const setDefaultBrowserUserChoiceStub = async () => { + throw Components.Exception("", Cr.NS_ERROR_WDBA_NO_PROGID); +}; + +const defaultAgentStub = sinon + .stub(ShellService, "defaultAgent") + .value({ setDefaultBrowserUserChoiceAsync: setDefaultBrowserUserChoiceStub }); + +const _userChoiceImpossibleTelemetryResultStub = sinon + .stub(ShellService, "_userChoiceImpossibleTelemetryResult") + .callsFake(() => null); + +const userChoiceStub = sinon + .stub(ShellService, "setAsDefaultUserChoice") + .resolves(); +const setDefaultStub = sinon.stub(); +const shellStub = sinon + .stub(ShellService, "shellService") + .value({ setDefaultBrowser: setDefaultStub }); + +const sendTriggerStub = sinon.stub(ASRouter, "sendTriggerMessage"); + +registerCleanupFunction(() => { + sinon.restore(); +}); + +let defaultUserChoice; +add_task(async function need_user_choice() { + await ShellService.setDefaultBrowser(); + defaultUserChoice = userChoiceStub.called; + + Assert.notStrictEqual( + defaultUserChoice, + undefined, + "Decided which default browser method to use" + ); + Assert.equal( + setDefaultStub.notCalled, + defaultUserChoice, + "Only one default behavior was used" + ); +}); + +add_task(async function remote_disable() { + if (defaultUserChoice === false) { + info("Default behavior already not user choice, so nothing to test"); + return; + } + + userChoiceStub.resetHistory(); + setDefaultStub.resetHistory(); + let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig( + { + featureId: NimbusFeatures.shellService.featureId, + value: { + setDefaultBrowserUserChoice: false, + enabled: true, + }, + }, + { isRollout: true } + ); + + await ShellService.setDefaultBrowser(); + + Assert.ok( + userChoiceStub.notCalled, + "Set default with user choice disabled via nimbus" + ); + Assert.ok(setDefaultStub.called, "Used plain set default instead"); + + await doCleanup(); +}); + +add_task(async function restore_default() { + if (defaultUserChoice === undefined) { + info("No default user choice behavior set, so nothing to test"); + return; + } + + userChoiceStub.resetHistory(); + setDefaultStub.resetHistory(); + + await ShellService.setDefaultBrowser(); + + Assert.equal( + userChoiceStub.called, + defaultUserChoice, + "Set default with user choice restored to original" + ); + Assert.equal( + setDefaultStub.notCalled, + defaultUserChoice, + "Plain set default behavior restored to original" + ); +}); + +add_task(async function ensure_fallback() { + if (AppConstants.platform != "win") { + info("Nothing to test on non-Windows"); + return; + } + + let userChoicePromise = Promise.resolve(); + userChoiceStub.callsFake(function (...args) { + return (userChoicePromise = userChoiceStub.wrappedMethod.apply(this, args)); + }); + userChoiceStub.resetHistory(); + setDefaultStub.resetHistory(); + let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig( + { + featureId: NimbusFeatures.shellService.featureId, + value: { + setDefaultBrowserUserChoice: true, + setDefaultPDFHandler: false, + enabled: true, + }, + }, + { isRollout: true } + ); + + await ShellService.setDefaultBrowser(); + + Assert.ok(userChoiceStub.called, "Set default with user choice called"); + + let message = ""; + await userChoicePromise.catch(err => (message = err.message || "")); + + Assert.ok( + message.includes("ErrExeProgID"), + "Set default with user choice threw an expected error" + ); + Assert.ok(setDefaultStub.called, "Fallbacked to plain set default"); + + await doCleanup(); +}); + +async function setUpNotificationTests(guidanceEnabled, oneClick) { + sinon.reset(); + const experimentCleanup = await NimbusTestUtils.enrollWithFeatureConfig( + { + featureId: NimbusFeatures.shellService.featureId, + value: { + setDefaultGuidanceNotifications: guidanceEnabled, + setDefaultBrowserUserChoice: oneClick, + setDefaultBrowserUserChoiceRegRename: oneClick, + enabled: true, + }, + }, + { isRollout: true } + ); + + const doCleanup = async () => { + await experimentCleanup(); + sinon.reset(); + }; + + await ShellService.setDefaultBrowser(); + return doCleanup; +} + +add_task( + async function show_notification_when_set_to_default_guidance_enabled_and_one_click_disabled() { + if (!AppConstants.isPlatformAndVersionAtLeast("win", 10)) { + info("Nothing to test on non-Windows or older Windows versions"); + return; + } + const doCleanup = await setUpNotificationTests( + true, // guidance enabled + false // one-click disabled + ); + + Assert.ok(setDefaultStub.called, "Fallback method used to set default"); + + Assert.equal( + sendTriggerStub.firstCall.args[0].id, + "deeplinkedToWindowsSettingsUI", + `Set to default guidance message trigger was sent` + ); + + await doCleanup(); + } +); + +add_task( + async function do_not_show_notification_when_set_to_default_guidance_disabled_and_one_click_enabled() { + if (!AppConstants.isPlatformAndVersionAtLeast("win", 10)) { + info("Nothing to test on non-Windows or older Windows versions"); + return; + } + + const doCleanup = await setUpNotificationTests( + false, // guidance disabled + true // one-click enabled + ); + + Assert.ok(setDefaultStub.notCalled, "Fallback method not called"); + + Assert.equal( + sendTriggerStub.callCount, + 0, + `Set to default guidance message trigger was not sent` + ); + + await doCleanup(); + } +); + +add_task( + async function do_not_show_notification_when_set_to_default_guidance_enabled_and_one_click_enabled() { + if (!AppConstants.isPlatformAndVersionAtLeast("win", 10)) { + info("Nothing to test on non-Windows or older Windows versions"); + return; + } + + const doCleanup = await setUpNotificationTests( + true, // guidance enabled + true // one-click enabled + ); + + Assert.ok(setDefaultStub.notCalled, "Fallback method not called"); + Assert.equal( + sendTriggerStub.callCount, + 0, + `Set to default guidance message trigger was not sent` + ); + await doCleanup(); + } +); diff --git a/src/zen/tests/mochitests/shell/browser_setDefaultPDFHandler.js b/src/zen/tests/mochitests/shell/browser_setDefaultPDFHandler.js new file mode 100644 index 0000000000..0deb2cd1e6 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_setDefaultPDFHandler.js @@ -0,0 +1,279 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +ChromeUtils.defineESModuleGetters(this, { + ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs", + NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", + NimbusTestUtils: "resource://testing-common/NimbusTestUtils.sys.mjs", + sinon: "resource://testing-common/Sinon.sys.mjs", +}); + +const setDefaultBrowserUserChoiceStub = sinon.stub(); +const setDefaultExtensionHandlersUserChoiceStub = sinon + .stub() + .callsFake(() => Promise.resolve()); + +const defaultAgentStub = sinon.stub(ShellService, "defaultAgent").value({ + setDefaultBrowserUserChoiceAsync: setDefaultBrowserUserChoiceStub, + setDefaultExtensionHandlersUserChoice: + setDefaultExtensionHandlersUserChoiceStub, +}); + +XPCOMUtils.defineLazyServiceGetter( + this, + "XreDirProvider", + "@mozilla.org/xre/directory-provider;1", + "nsIXREDirProvider" +); + +const _userChoiceImpossibleTelemetryResultStub = sinon + .stub(ShellService, "_userChoiceImpossibleTelemetryResult") + .callsFake(() => null); + +// Ensure we don't fall back to a real implementation. +const setDefaultStub = sinon.stub(); +// We'll dynamically update this as needed during the tests. +const queryCurrentDefaultHandlerForStub = sinon.stub(); +const shellStub = sinon.stub(ShellService, "shellService").value({ + setDefaultBrowser: setDefaultStub, + queryCurrentDefaultHandlerFor: queryCurrentDefaultHandlerForStub, +}); + +registerCleanupFunction(() => { + defaultAgentStub.restore(); + _userChoiceImpossibleTelemetryResultStub.restore(); + shellStub.restore(); +}); + +add_task(async function ready() { + await ExperimentAPI.ready(); +}); + +// Everything here is Windows. +Assert.equal(AppConstants.platform, "win", "Platform is Windows"); + +add_task(async function remoteEnableWithPDF() { + let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig( + { + featureId: NimbusFeatures.shellService.featureId, + value: { + setDefaultBrowserUserChoice: true, + setDefaultPDFHandlerOnlyReplaceBrowsers: false, + setDefaultPDFHandler: true, + enabled: true, + }, + }, + { isRollout: true } + ); + + Assert.equal( + NimbusFeatures.shellService.getVariable("setDefaultBrowserUserChoice"), + true + ); + Assert.equal( + NimbusFeatures.shellService.getVariable("setDefaultPDFHandler"), + true + ); + + setDefaultBrowserUserChoiceStub.resetHistory(); + await ShellService.setDefaultBrowser(); + + const aumi = XreDirProvider.getInstallHash(); + Assert.ok(setDefaultBrowserUserChoiceStub.called); + Assert.deepEqual(setDefaultBrowserUserChoiceStub.firstCall.args, [ + aumi, + [".pdf", "FirefoxPDF"], + ]); + + await doCleanup(); +}); + +add_task(async function remoteEnableWithPDF_testOnlyReplaceBrowsers() { + let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig( + { + featureId: NimbusFeatures.shellService.featureId, + value: { + setDefaultBrowserUserChoice: true, + setDefaultPDFHandlerOnlyReplaceBrowsers: true, + setDefaultPDFHandler: true, + enabled: true, + }, + }, + { isRollout: true } + ); + + Assert.equal( + NimbusFeatures.shellService.getVariable("setDefaultBrowserUserChoice"), + true + ); + Assert.equal( + NimbusFeatures.shellService.getVariable("setDefaultPDFHandler"), + true + ); + Assert.equal( + NimbusFeatures.shellService.getVariable( + "setDefaultPDFHandlerOnlyReplaceBrowsers" + ), + true + ); + + const aumi = XreDirProvider.getInstallHash(); + + // We'll take the default from a missing association or a known browser. + for (let progId of ["", "MSEdgePDF"]) { + queryCurrentDefaultHandlerForStub.callsFake(() => progId); + + setDefaultBrowserUserChoiceStub.resetHistory(); + await ShellService.setDefaultBrowser(); + + Assert.ok(setDefaultBrowserUserChoiceStub.called); + Assert.deepEqual( + setDefaultBrowserUserChoiceStub.firstCall.args, + [aumi, [".pdf", "FirefoxPDF"]], + `Will take default from missing association or known browser with ProgID '${progId}'` + ); + } + + // But not from a non-browser. + queryCurrentDefaultHandlerForStub.callsFake(() => "Acrobat.Document.DC"); + + setDefaultBrowserUserChoiceStub.resetHistory(); + await ShellService.setDefaultBrowser(); + + Assert.ok(setDefaultBrowserUserChoiceStub.called); + Assert.deepEqual( + setDefaultBrowserUserChoiceStub.firstCall.args, + [aumi, []], + `Will not take default from non-browser` + ); + + await doCleanup(); +}); + +add_task(async function remoteEnableWithoutPDF() { + let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig( + { + featureId: NimbusFeatures.shellService.featureId, + value: { + setDefaultBrowserUserChoice: true, + setDefaultPDFHandler: false, + enabled: true, + }, + }, + { isRollout: true } + ); + + Assert.equal( + NimbusFeatures.shellService.getVariable("setDefaultBrowserUserChoice"), + true + ); + Assert.equal( + NimbusFeatures.shellService.getVariable("setDefaultPDFHandler"), + false + ); + + setDefaultBrowserUserChoiceStub.resetHistory(); + await ShellService.setDefaultBrowser(); + + const aumi = XreDirProvider.getInstallHash(); + Assert.ok(setDefaultBrowserUserChoiceStub.called); + Assert.deepEqual(setDefaultBrowserUserChoiceStub.firstCall.args, [aumi, []]); + + await doCleanup(); +}); + +add_task(async function remoteDisable() { + let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig( + { + featureId: NimbusFeatures.shellService.featureId, + value: { + setDefaultBrowserUserChoice: false, + setDefaultPDFHandler: true, + enabled: false, + }, + }, + { isRollout: true } + ); + + Assert.equal( + NimbusFeatures.shellService.getVariable("setDefaultBrowserUserChoice"), + false + ); + Assert.equal( + NimbusFeatures.shellService.getVariable("setDefaultPDFHandler"), + true + ); + + setDefaultBrowserUserChoiceStub.resetHistory(); + await ShellService.setDefaultBrowser(); + + Assert.ok(setDefaultBrowserUserChoiceStub.notCalled); + Assert.ok(setDefaultStub.called); + + await doCleanup(); +}); + +add_task(async function test_setAsDefaultPDFHandler_knownBrowser() { + const sandbox = sinon.createSandbox(); + + const aumi = XreDirProvider.getInstallHash(); + const expectedArguments = [aumi, [".pdf", "FirefoxPDF"]]; + + try { + const pdfHandlerResult = { registered: true, knownBrowser: true }; + sandbox + .stub(ShellService, "getDefaultPDFHandler") + .returns(pdfHandlerResult); + + info("Testing setAsDefaultPDFHandler(true) when knownBrowser = true"); + ShellService.setAsDefaultPDFHandler(true); + Assert.ok( + setDefaultExtensionHandlersUserChoiceStub.called, + "Called default browser agent" + ); + Assert.deepEqual( + setDefaultExtensionHandlersUserChoiceStub.firstCall.args, + expectedArguments, + "Called default browser agent with expected arguments" + ); + setDefaultExtensionHandlersUserChoiceStub.resetHistory(); + + info("Testing setAsDefaultPDFHandler(false) when knownBrowser = true"); + ShellService.setAsDefaultPDFHandler(false); + Assert.ok( + setDefaultExtensionHandlersUserChoiceStub.called, + "Called default browser agent" + ); + Assert.deepEqual( + setDefaultExtensionHandlersUserChoiceStub.firstCall.args, + expectedArguments, + "Called default browser agent with expected arguments" + ); + setDefaultExtensionHandlersUserChoiceStub.resetHistory(); + + pdfHandlerResult.knownBrowser = false; + + info("Testing setAsDefaultPDFHandler(true) when knownBrowser = false"); + ShellService.setAsDefaultPDFHandler(true); + Assert.ok( + setDefaultExtensionHandlersUserChoiceStub.notCalled, + "Did not call default browser agent" + ); + setDefaultExtensionHandlersUserChoiceStub.resetHistory(); + + info("Testing setAsDefaultPDFHandler(false) when knownBrowser = false"); + ShellService.setAsDefaultPDFHandler(false); + Assert.ok( + setDefaultExtensionHandlersUserChoiceStub.called, + "Called default browser agent" + ); + Assert.deepEqual( + setDefaultExtensionHandlersUserChoiceStub.firstCall.args, + expectedArguments, + "Called default browser agent with expected arguments" + ); + setDefaultExtensionHandlersUserChoiceStub.resetHistory(); + } finally { + sandbox.restore(); + } +}); diff --git a/src/zen/tests/mochitests/shell/browser_setDesktopBackgroundPreview.js b/src/zen/tests/mochitests/shell/browser_setDesktopBackgroundPreview.js new file mode 100644 index 0000000000..b847d09980 --- /dev/null +++ b/src/zen/tests/mochitests/shell/browser_setDesktopBackgroundPreview.js @@ -0,0 +1,93 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Check whether the preview image for setDesktopBackground is rendered + * correctly, without stretching + */ + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["test.wait300msAfterTabSwitch", true]], + }); +}); + +add_task(async function () { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "about:logo", + }, + async () => { + const dialogLoad = BrowserTestUtils.domWindowOpened(null, async win => { + await BrowserTestUtils.waitForEvent(win, "load"); + Assert.equal( + win.document.documentElement.getAttribute("windowtype"), + "Shell:SetDesktopBackground", + "Opened correct window" + ); + return true; + }); + + const image = content.document.images[0]; + EventUtils.synthesizeMouseAtCenter(image, { type: "contextmenu" }); + + const menu = document.getElementById("contentAreaContextMenu"); + await BrowserTestUtils.waitForPopupEvent(menu, "shown"); + const menuClosed = BrowserTestUtils.waitForPopupEvent(menu, "hidden"); + + const menuItem = document.getElementById("context-setDesktopBackground"); + try { + menu.activateItem(menuItem); + } catch (ex) { + ok( + menuItem.hidden, + "should only fail to activate when menu item is hidden" + ); + ok( + !ShellService.canSetDesktopBackground, + "Should only hide when not able to set the desktop background" + ); + is( + AppConstants.platform, + "linux", + "Should always be able to set desktop background on non-linux platforms" + ); + todo(false, "Skipping test on this configuration"); + + menu.hidePopup(); + await menuClosed; + return; + } + + await menuClosed; + + const win = await dialogLoad; + + /* setDesktopBackground.js does a setTimeout to wait for correct + dimensions. If we don't wait here we could read the preview dimensions + before they're changed to match the screen */ + await TestUtils.waitForTick(); + + const canvas = win.document.getElementById("screen"); + const screenRatio = screen.width / screen.height; + const previewRatio = canvas.clientWidth / canvas.clientHeight; + + info(`Screen dimensions are ${screen.width}x${screen.height}`); + info(`Screen's raw ratio is ${screenRatio}`); + info( + `Preview dimensions are ${canvas.clientWidth}x${canvas.clientHeight}` + ); + info(`Preview's raw ratio is ${previewRatio}`); + + Assert.ok( + previewRatio < screenRatio + 0.01 && previewRatio > screenRatio - 0.01, + "Preview's aspect ratio is within ±.01 of screen's" + ); + + win.close(); + + await menuClosed; + } + ); +}); diff --git a/src/zen/tests/mochitests/shell/gtest/LimitedAccessFeatureTests.cpp b/src/zen/tests/mochitests/shell/gtest/LimitedAccessFeatureTests.cpp new file mode 100644 index 0000000000..ddf3a75481 --- /dev/null +++ b/src/zen/tests/mochitests/shell/gtest/LimitedAccessFeatureTests.cpp @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "gtest/gtest.h" + +#include "Windows11LimitedAccessFeatures.h" +#include "WinUtils.h" + +TEST(LimitedAccessFeature, VerifyGeneratedInfo) +{ + // If running on MSIX we have no guarantee that the + // generated LAF info will match the known values. + if (mozilla::widget::WinUtils::HasPackageIdentity()) { + return; + } + + LimitedAccessFeatureInfo knownLafInfo = { + // Win11LimitedAccessFeatureType::Taskbar + "Win11LimitedAccessFeatureType::Taskbar"_ns, // debugName + u"com.microsoft.windows.taskbar.pin"_ns, // feature + u"kRFiWpEK5uS6PMJZKmR7MQ=="_ns, // token + u"pcsmm0jrprpb2 has registered their use of "_ns // attestation + u"com.microsoft.windows.taskbar.pin with Microsoft and agrees to the "_ns + u"terms "_ns + u"of use."_ns}; + + auto generatedLafInfoResult = GenerateLimitedAccessFeatureInfo( + "Win11LimitedAccessFeatureType::Taskbar"_ns, + u"com.microsoft.windows.taskbar.pin"_ns); + ASSERT_TRUE(generatedLafInfoResult.isOk()); + LimitedAccessFeatureInfo generatedLafInfo = generatedLafInfoResult.unwrap(); + + // Check for equality between generated values and known good values + ASSERT_TRUE(knownLafInfo.debugName.Equals(generatedLafInfo.debugName)); + ASSERT_TRUE(knownLafInfo.feature.Equals(generatedLafInfo.feature)); + ASSERT_TRUE(knownLafInfo.token.Equals(generatedLafInfo.token)); + ASSERT_TRUE(knownLafInfo.attestation.Equals(generatedLafInfo.attestation)); +} diff --git a/src/zen/tests/mochitests/shell/gtest/ShellLinkTests.cpp b/src/zen/tests/mochitests/shell/gtest/ShellLinkTests.cpp new file mode 100644 index 0000000000..2cf1b8ed69 --- /dev/null +++ b/src/zen/tests/mochitests/shell/gtest/ShellLinkTests.cpp @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "gtest/gtest.h" + +#include "nsDirectoryServiceDefs.h" +#include "nsDirectoryServiceUtils.h" +#include "nsWindowsShellServiceInternal.h" +#include "nsXULAppAPI.h" + +TEST(ShellLink, NarrowCharacterArguments) +{ + nsCOMPtr exe; + nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(exe)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + RefPtr link; + rv = CreateShellLinkObject(exe, {u"test"_ns}, u"test"_ns, exe, 0, u"aumid"_ns, + getter_AddRefs(link)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + ASSERT_TRUE(link != nullptr); + + std::wstring testArgs = L"\"test\" "; + + wchar_t resultArgs[sizeof(testArgs)]; + HRESULT hr = link->GetArguments(resultArgs, sizeof(resultArgs)); + ASSERT_TRUE(SUCCEEDED(hr)); + + ASSERT_TRUE(testArgs == resultArgs); +} + +TEST(ShellLink, WideCharacterArguments) +{ + nsCOMPtr exe; + nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(exe)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + RefPtr link; + rv = CreateShellLinkObject(exe, {u"Test\\テスト用アカウント\\Test"_ns}, + u"test"_ns, exe, 0, u"aumid"_ns, + getter_AddRefs(link)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + ASSERT_TRUE(link != nullptr); + + std::wstring testArgs = L"\"Test\\テスト用アカウント\\Test\" "; + + wchar_t resultArgs[sizeof(testArgs)]; + HRESULT hr = link->GetArguments(resultArgs, sizeof(resultArgs)); + ASSERT_TRUE(SUCCEEDED(hr)); + + ASSERT_TRUE(testArgs == resultArgs); +} diff --git a/src/zen/tests/mochitests/shell/gtest/moz.build b/src/zen/tests/mochitests/shell/gtest/moz.build new file mode 100644 index 0000000000..e33786fad6 --- /dev/null +++ b/src/zen/tests/mochitests/shell/gtest/moz.build @@ -0,0 +1,15 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows": + LOCAL_INCLUDES += ["/browser/components/shell"] + + UNIFIED_SOURCES += [ + "LimitedAccessFeatureTests.cpp", + "ShellLinkTests.cpp", + ] + +FINAL_LIBRARY = "xul-gtest" diff --git a/src/zen/tests/mochitests/shell/head.js b/src/zen/tests/mochitests/shell/head.js new file mode 100644 index 0000000000..a6cebb3d12 --- /dev/null +++ b/src/zen/tests/mochitests/shell/head.js @@ -0,0 +1,159 @@ +"use strict"; + +const { Subprocess } = ChromeUtils.importESModule( + "resource://gre/modules/Subprocess.sys.mjs" +); + +const TEMP_DIR = Services.dirsvc.get("TmpD", Ci.nsIFile).path; + +const screenshotPath = PathUtils.join(TEMP_DIR, "headless_test_screenshot.png"); + +async function runFirefox(args) { + const XRE_EXECUTABLE_FILE = "XREExeF"; + const firefoxExe = Services.dirsvc.get(XRE_EXECUTABLE_FILE, Ci.nsIFile).path; + const NS_APP_PREFS_50_FILE = "PrefF"; + const mochiPrefsFile = Services.dirsvc.get(NS_APP_PREFS_50_FILE, Ci.nsIFile); + const mochiPrefsPath = mochiPrefsFile.path; + const mochiPrefsName = mochiPrefsFile.leafName; + const profilePath = PathUtils.join( + TEMP_DIR, + "headless_test_screenshot_profile" + ); + const prefsPath = PathUtils.join(profilePath, mochiPrefsName); + const firefoxArgs = ["-profile", profilePath]; + + await IOUtils.makeDirectory(profilePath); + await IOUtils.copy(mochiPrefsPath, prefsPath); + let proc = await Subprocess.call({ + command: firefoxExe, + arguments: firefoxArgs.concat(args), + // Disable leak detection to avoid intermittent failure bug 1331152. + environmentAppend: true, + environment: { + ASAN_OPTIONS: + "detect_leaks=0:quarantine_size=50331648:malloc_context_size=5", + // Don't enable Marionette. + MOZ_MARIONETTE: null, + }, + }); + let stdout; + while ((stdout = await proc.stdout.readString())) { + dump(`>>> ${stdout}\n`); + } + let { exitCode } = await proc.wait(); + is(exitCode, 0, "Firefox process should exit with code 0"); + await IOUtils.remove(profilePath, { recursive: true }); +} + +async function testFileCreationPositive(args, path) { + await runFirefox(args); + + let saved = IOUtils.exists(path); + ok(saved, "A screenshot should be saved as " + path); + if (!saved) { + return; + } + + let info = await IOUtils.stat(path); + Assert.greater(info.size, 0, "Screenshot should not be an empty file"); + await IOUtils.remove(path); +} + +async function testFileCreationNegative(args, path) { + await runFirefox(args); + + let saved = await IOUtils.exists(path); + ok(!saved, "A screenshot should not be saved"); + await IOUtils.remove(path); +} + +async function testWindowSizePositive(width, height) { + let size = String(width); + if (height) { + size += "," + height; + } + + await runFirefox([ + "-url", + "http://mochi.test:8888/browser/browser/components/shell/test/headless.html", + "-screenshot", + screenshotPath, + "-window-size", + size, + ]); + + let saved = await IOUtils.exists(screenshotPath); + ok(saved, "A screenshot should be saved in the tmp directory"); + if (!saved) { + return; + } + + let data = await IOUtils.read(screenshotPath); + await new Promise(resolve => { + let blob = new Blob([data], { type: "image/png" }); + let reader = new FileReader(); + reader.onloadend = function () { + let screenshot = new Image(); + screenshot.onload = function () { + is( + screenshot.width, + width, + "Screenshot should be " + width + " pixels wide" + ); + if (height) { + is( + screenshot.height, + height, + "Screenshot should be " + height + " pixels tall" + ); + } + resolve(); + }; + screenshot.src = reader.result; + }; + reader.readAsDataURL(blob); + }); + await IOUtils.remove(screenshotPath); +} + +async function testGreen(url, path) { + await runFirefox(["-url", url, `--screenshot=${path}`]); + + let saved = await IOUtils.exists(path); + ok(saved, "A screenshot should be saved in the tmp directory"); + if (!saved) { + return; + } + + let data = await IOUtils.read(path); + let image = await new Promise(resolve => { + let blob = new Blob([data], { type: "image/png" }); + let reader = new FileReader(); + reader.onloadend = function () { + let screenshot = new Image(); + screenshot.onload = function () { + resolve(screenshot); + }; + screenshot.src = reader.result; + }; + reader.readAsDataURL(blob); + }); + let canvas = document.createElement("canvas"); + canvas.width = image.naturalWidth; + canvas.height = image.naturalHeight; + let ctx = canvas.getContext("2d"); + ctx.drawImage(image, 0, 0); + let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + let rgba = imageData.data; + + let found = false; + for (let i = 0; i < rgba.length; i += 4) { + if (rgba[i] === 0 && rgba[i + 1] === 255 && rgba[i + 2] === 0) { + found = true; + break; + } + } + ok(found, "There should be a green pixel in the screenshot."); + + await IOUtils.remove(path); +} diff --git a/src/zen/tests/mochitests/shell/headless.html b/src/zen/tests/mochitests/shell/headless.html new file mode 100644 index 0000000000..bbde895077 --- /dev/null +++ b/src/zen/tests/mochitests/shell/headless.html @@ -0,0 +1,6 @@ + + + +Hi + + diff --git a/src/zen/tests/mochitests/shell/headless_cross_origin.html b/src/zen/tests/mochitests/shell/headless_cross_origin.html new file mode 100644 index 0000000000..3bb09aa5d8 --- /dev/null +++ b/src/zen/tests/mochitests/shell/headless_cross_origin.html @@ -0,0 +1,7 @@ + + + + +Hi + + diff --git a/src/zen/tests/mochitests/shell/headless_iframe.html b/src/zen/tests/mochitests/shell/headless_iframe.html new file mode 100644 index 0000000000..f318cbe0f3 --- /dev/null +++ b/src/zen/tests/mochitests/shell/headless_iframe.html @@ -0,0 +1,6 @@ + + + +Hi + + diff --git a/src/zen/tests/mochitests/shell/headless_redirect.html b/src/zen/tests/mochitests/shell/headless_redirect.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/zen/tests/mochitests/shell/headless_redirect.html^headers^ b/src/zen/tests/mochitests/shell/headless_redirect.html^headers^ new file mode 100644 index 0000000000..1d7db20ea5 --- /dev/null +++ b/src/zen/tests/mochitests/shell/headless_redirect.html^headers^ @@ -0,0 +1,2 @@ +HTTP 302 Moved Temporarily +Location: headless.html \ No newline at end of file diff --git a/src/zen/tests/mochitests/shell/mac_desktop_image.py b/src/zen/tests/mochitests/shell/mac_desktop_image.py new file mode 100755 index 0000000000..e3ccc77190 --- /dev/null +++ b/src/zen/tests/mochitests/shell/mac_desktop_image.py @@ -0,0 +1,168 @@ +#!/usr/bin/python +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +""" +mac_desktop_image.py + +Mac-specific utility to get/set the desktop background image or check that +the current background image path matches a provided path. + +Depends on Objective-C python binding imports which are in the python import +paths by default when using macOS's /usr/bin/python. + +Includes generous amount of logging to aid debugging for use in automated tests. +""" + +import argparse +import logging +import os +import sys + +# +# These Objective-C bindings imports are included in the import path by default +# for the Mac-bundled python installed in /usr/bin/python. They're needed to +# call the Objective-C API's to set and retrieve the current desktop background +# image. +# +from AppKit import NSScreen, NSWorkspace +from Cocoa import NSURL + + +def main(): + parser = argparse.ArgumentParser( + description="Utility to print, set, or " + + "check the path to image being used as " + + "the desktop background image. By " + + "default, prints the path to the " + + "current desktop background image." + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + help="print verbose debugging information", + default=False, + ) + group = parser.add_mutually_exclusive_group() + group.add_argument( + "-s", + "--set-background-image", + dest="newBackgroundImagePath", + required=False, + help="path to the new background image to set. A zero " + + "exit code indicates no errors occurred.", + default=None, + ) + group.add_argument( + "-c", + "--check-background-image", + dest="checkBackgroundImagePath", + required=False, + help="check if the provided background image path " + + "matches the provided path. A zero exit code " + + "indicates the paths match.", + default=None, + ) + args = parser.parse_args() + + # Using logging for verbose output + if args.verbose: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.CRITICAL) + logger = logging.getLogger("desktopImage") + + # Print what we're going to do + if args.checkBackgroundImagePath is not None: + logger.debug( + "checking provided desktop image %s matches current " + "image" % args.checkBackgroundImagePath + ) + elif args.newBackgroundImagePath is not None: + logger.debug("setting image to %s " % args.newBackgroundImagePath) + else: + logger.debug("retrieving desktop image path") + + focussedScreen = NSScreen.mainScreen() + if not focussedScreen: + raise RuntimeError("mainScreen error") + + ws = NSWorkspace.sharedWorkspace() + if not ws: + raise RuntimeError("sharedWorkspace error") + + # If we're just checking the image path, check it and then return. + # A successful exit code (0) indicates the paths match. + if args.checkBackgroundImagePath is not None: + # Get existing desktop image path and resolve it + existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) + existingImagePath = existingImageURL.path() + existingImagePathReal = os.path.realpath(existingImagePath) + logger.debug("existing desktop image: %s" % existingImagePath) + logger.debug("existing desktop image realpath: %s" % existingImagePath) + + # Resolve the path we're going to check + checkImagePathReal = os.path.realpath(args.checkBackgroundImagePath) + logger.debug("check desktop image: %s" % args.checkBackgroundImagePath) + logger.debug("check desktop image realpath: %s" % checkImagePathReal) + + if existingImagePathReal == checkImagePathReal: + print("desktop image path matches provided path") + return True + + print("desktop image path does NOT match provided path") + return False + + # Log the current desktop image + if args.verbose: + existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) + logger.debug("existing desktop image: %s" % existingImageURL.path()) + + # Set the desktop image + if args.newBackgroundImagePath is not None: + newImagePath = args.newBackgroundImagePath + if not os.path.exists(newImagePath): + logger.critical("%s does not exist" % newImagePath) + return False + if not os.access(newImagePath, os.R_OK): + logger.critical("%s is not readable" % newImagePath) + return False + + logger.debug("new desktop image to set: %s" % newImagePath) + newImageURL = NSURL.fileURLWithPath_(newImagePath) + logger.debug("new desktop image URL to set: %s" % newImageURL) + + status = False + (status, error) = ws.setDesktopImageURL_forScreen_options_error_( + newImageURL, focussedScreen, None, None + ) + if not status: + raise RuntimeError("setDesktopImageURL error") + + # Print the current desktop image + imageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) + imagePath = imageURL.path() + imagePathReal = os.path.realpath(imagePath) + logger.debug("updated desktop image URL: %s" % imageURL) + logger.debug("updated desktop image path: %s" % imagePath) + logger.debug("updated desktop image path (resolved): %s" % imagePathReal) + print(imagePathReal) + return True + + +def getCurrentDesktopImageURL(focussedScreen, workspace, logger): + imageURL = workspace.desktopImageURLForScreen_(focussedScreen) + if not imageURL: + raise RuntimeError("desktopImageURLForScreen returned invalid URL") + if not imageURL.isFileURL(): + logger.warning("desktop image URL is not a file URL") + return imageURL + + +if __name__ == "__main__": + if not main(): + sys.exit(1) + else: + sys.exit(0) diff --git a/src/zen/tests/mochitests/shell/unit/test_macOS_showSecurityPreferences.js b/src/zen/tests/mochitests/shell/unit/test_macOS_showSecurityPreferences.js new file mode 100644 index 0000000000..3b9837aace --- /dev/null +++ b/src/zen/tests/mochitests/shell/unit/test_macOS_showSecurityPreferences.js @@ -0,0 +1,40 @@ +/* Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test the macOS ShowSecurityPreferences shell service method. + */ + +"use strict"; + +// eslint-disable-next-line mozilla/no-redeclare-with-import-autofix +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +function killSystemPreferences() { + let killallFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + killallFile.initWithPath("/usr/bin/killall"); + let sysPrefsArg = ["System Preferences"]; + if (AppConstants.isPlatformAndVersionAtLeast("macosx", 22)) { + sysPrefsArg = ["System Settings"]; + } + let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + process.init(killallFile); + process.run(true, sysPrefsArg, 1); + return process.exitValue; +} + +add_setup(async function () { + info("Ensure System Preferences isn't already running"); + killSystemPreferences(); +}); + +add_task(async function test_prefsOpen() { + let shellSvc = Cc["@mozilla.org/browser/shell-service;1"].getService( + Ci.nsIMacShellService + ); + shellSvc.showSecurityPreferences("Privacy_AllFiles"); + + equal(killSystemPreferences(), 0, "Ensure System Preferences was started"); +}); diff --git a/src/zen/tests/mochitests/shell/unit/xpcshell.toml b/src/zen/tests/mochitests/shell/unit/xpcshell.toml new file mode 100644 index 0000000000..8939e6af96 --- /dev/null +++ b/src/zen/tests/mochitests/shell/unit/xpcshell.toml @@ -0,0 +1,6 @@ +[DEFAULT] +firefox-appdir = "browser" +tags = "os_integration" + +["test_macOS_showSecurityPreferences.js"] +run-if = ["os == 'mac'"] diff --git a/src/zen/tests/mochitests/tooltiptext/browser.toml b/src/zen/tests/mochitests/tooltiptext/browser.toml new file mode 100644 index 0000000000..42aca4a7a6 --- /dev/null +++ b/src/zen/tests/mochitests/tooltiptext/browser.toml @@ -0,0 +1,17 @@ +[DEFAULT] + +["browser_bug329212.js"] +support-files = ["title_test.svg"] + +["browser_bug331772_xul_tooltiptext_in_html.js"] +support-files = ["xul_tooltiptext.xhtml"] + +["browser_bug561623.js"] + +["browser_bug581947.js"] + +["browser_input_file_tooltips.js"] + +["browser_nac_tooltip.js"] + +["browser_shadow_dom_tooltip.js"] diff --git a/src/zen/tests/mochitests/tooltiptext/browser_bug329212.js b/src/zen/tests/mochitests/tooltiptext/browser_bug329212.js new file mode 100644 index 0000000000..d669e60c26 --- /dev/null +++ b/src/zen/tests/mochitests/tooltiptext/browser_bug329212.js @@ -0,0 +1,48 @@ +"use strict"; + +add_task(async function () { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "http://mochi.test:8888/browser/toolkit/components/tooltiptext/tests/title_test.svg", + }, + async function (browser) { + await SpecialPowers.spawn(browser, [""], function () { + let tttp = Cc[ + "@mozilla.org/embedcomp/default-tooltiptextprovider;1" + ].getService(Ci.nsITooltipTextProvider); + function checkElement(id, expectedTooltipText) { + let el = content.document.getElementById(id); + let textObj = {}; + let shouldHaveTooltip = expectedTooltipText !== null; + is( + tttp.getNodeText(el, textObj, {}), + shouldHaveTooltip, + "element " + + id + + " should " + + (shouldHaveTooltip ? "" : "not ") + + "have a tooltip" + ); + if (shouldHaveTooltip) { + is( + textObj.value, + expectedTooltipText, + "element " + id + " should have the right tooltip text" + ); + } + } + checkElement("svg1", "This is a non-root SVG element title"); + checkElement("text1", "\n\n\n This is a title\n\n "); + checkElement("text2", null); + checkElement("text3", null); + checkElement("link1", "\n This is a title\n "); + checkElement("text4", "\n This is a title\n "); + checkElement("link2", null); + checkElement("link3", "This is an xlink:title attribute"); + checkElement("link4", "This is an xlink:title attribute"); + checkElement("text5", null); + }); + } + ); +}); diff --git a/src/zen/tests/mochitests/tooltiptext/browser_bug331772_xul_tooltiptext_in_html.js b/src/zen/tests/mochitests/tooltiptext/browser_bug331772_xul_tooltiptext_in_html.js new file mode 100644 index 0000000000..61c50e5422 --- /dev/null +++ b/src/zen/tests/mochitests/tooltiptext/browser_bug331772_xul_tooltiptext_in_html.js @@ -0,0 +1,30 @@ +/** + * Tests that the tooltiptext attribute is used for XUL elements in an HTML doc. + */ +add_task(async function () { + await SpecialPowers.pushPermissions([ + { type: "allowXULXBL", allow: true, context: "http://mochi.test:8888" }, + ]); + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "http://mochi.test:8888/browser/toolkit/components/tooltiptext/tests/xul_tooltiptext.xhtml", + }, + async function (browser) { + await SpecialPowers.spawn(browser, [""], function () { + let textObj = {}; + let tttp = Cc[ + "@mozilla.org/embedcomp/default-tooltiptextprovider;1" + ].getService(Ci.nsITooltipTextProvider); + let xulToolbarButton = + content.document.getElementById("xulToolbarButton"); + ok( + tttp.getNodeText(xulToolbarButton, textObj, {}), + "should get tooltiptext" + ); + is(textObj.value, "XUL tooltiptext"); + }); + } + ); +}); diff --git a/src/zen/tests/mochitests/tooltiptext/browser_bug561623.js b/src/zen/tests/mochitests/tooltiptext/browser_bug561623.js new file mode 100644 index 0000000000..93f68d307f --- /dev/null +++ b/src/zen/tests/mochitests/tooltiptext/browser_bug561623.js @@ -0,0 +1,33 @@ +add_task(async function () { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "data:text/html,", + }, + async function (browser) { + await SpecialPowers.spawn(browser, [""], function () { + let tttp = Cc[ + "@mozilla.org/embedcomp/default-tooltiptextprovider;1" + ].getService(Ci.nsITooltipTextProvider); + let i = content.document.getElementById("i"); + + ok( + !tttp.getNodeText(i, {}, {}), + "No tooltip should be shown when @title is null" + ); + + i.title = "foo"; + ok( + tttp.getNodeText(i, {}, {}), + "A tooltip should be shown when @title is not the empty string" + ); + + i.pattern = "bar"; + ok( + tttp.getNodeText(i, {}, {}), + "A tooltip should be shown when @title is not the empty string" + ); + }); + } + ); +}); diff --git a/src/zen/tests/mochitests/tooltiptext/browser_bug581947.js b/src/zen/tests/mochitests/tooltiptext/browser_bug581947.js new file mode 100644 index 0000000000..0971735470 --- /dev/null +++ b/src/zen/tests/mochitests/tooltiptext/browser_bug581947.js @@ -0,0 +1,107 @@ +function check(aBrowser, aElementName, aBarred, aType) { + return SpecialPowers.spawn( + aBrowser, + [[aElementName, aBarred, aType]], + async function ([aElementName, aBarred, aType]) { + let e = content.document.createElement(aElementName); + let contentElement = content.document.getElementById("content"); + contentElement.appendChild(e); + + if (aType) { + e.type = aType; + } + + let tttp = Cc[ + "@mozilla.org/embedcomp/default-tooltiptextprovider;1" + ].getService(Ci.nsITooltipTextProvider); + ok( + !tttp.getNodeText(e, {}, {}), + "No tooltip should be shown when the element is valid" + ); + + e.setCustomValidity("foo"); + if (aBarred) { + ok( + !tttp.getNodeText(e, {}, {}), + "No tooltip should be shown when the element is barred from constraint validation" + ); + } else { + ok( + tttp.getNodeText(e, {}, {}), + e.tagName + " A tooltip should be shown when the element isn't valid" + ); + } + + e.setAttribute("title", ""); + ok( + !tttp.getNodeText(e, {}, {}), + "No tooltip should be shown if the title attribute is set" + ); + + e.removeAttribute("title"); + contentElement.setAttribute("novalidate", ""); + ok( + !tttp.getNodeText(e, {}, {}), + "No tooltip should be shown if the novalidate attribute is set on the form owner" + ); + contentElement.removeAttribute("novalidate"); + + e.remove(); + } + ); +} + +function todo_check(aBrowser, aElementName, aBarred) { + return SpecialPowers.spawn( + aBrowser, + [[aElementName, aBarred]], + async function ([aElementName]) { + let e = content.document.createElement(aElementName); + let contentElement = content.document.getElementById("content"); + contentElement.appendChild(e); + + let caught = false; + try { + e.setCustomValidity("foo"); + } catch (e) { + caught = true; + } + + todo(!caught, "setCustomValidity should exist for " + aElementName); + + e.remove(); + } + ); +} + +add_task(async function () { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "data:text/html,
", + }, + async function (browser) { + let testData = [ + /* element name, barred */ + ["input", false, null], + ["textarea", false, null], + ["button", true, "button"], + ["button", false, "submit"], + ["select", false, null], + ["output", true, null], + ["fieldset", true, null], + ["object", true, null], + ]; + + for (let data of testData) { + await check(browser, data[0], data[1], data[2]); + } + + let todo_testData = [["keygen", "false"]]; + + for (let data of todo_testData) { + await todo_check(browser, data[0], data[1]); + } + } + ); +}); diff --git a/src/zen/tests/mochitests/tooltiptext/browser_input_file_tooltips.js b/src/zen/tests/mochitests/tooltiptext/browser_input_file_tooltips.js new file mode 100644 index 0000000000..2f1385f37f --- /dev/null +++ b/src/zen/tests/mochitests/tooltiptext/browser_input_file_tooltips.js @@ -0,0 +1,131 @@ +/* eslint-disable mozilla/no-arbitrary-setTimeout */ + +let tempFile; +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ set: [["ui.tooltip.delay_ms", 0]] }); + tempFile = createTempFile(); + registerCleanupFunction(function () { + tempFile.remove(true); + }); +}); + +add_task(async function test_singlefile_selected() { + await do_test({ value: true, result: "testfile_bug1251809" }); +}); + +add_task(async function test_title_set() { + await do_test({ title: "foo", result: "foo" }); +}); + +add_task(async function test_nofile_selected() { + await do_test({ result: "No file selected." }); +}); + +add_task(async function test_multipleset_nofile_selected() { + await do_test({ multiple: true, result: "No files selected." }); +}); + +add_task(async function test_requiredset() { + await do_test({ required: true, result: "Please select a file." }); +}); + +async function do_test(test) { + info(`starting test ${JSON.stringify(test)}`); + + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + + info("Moving mouse out of the way."); + await EventUtils.synthesizeAndWaitNativeMouseMove( + tab.linkedBrowser, + 300, + 300 + ); + + info("creating input field"); + await SpecialPowers.spawn(tab.linkedBrowser, [test], async function (test) { + let doc = content.document; + let input = doc.createElement("input"); + doc.body.appendChild(input); + input.id = "test_input"; + input.setAttribute("style", "position: absolute; top: 0; left: 0;"); + input.type = "file"; + if (test.title) { + input.setAttribute("title", test.title); + } + if (test.multiple) { + input.multiple = true; + } + if (test.required) { + input.required = true; + } + }); + + if (test.value) { + info("Creating mock filepicker to select files"); + let MockFilePicker = SpecialPowers.MockFilePicker; + MockFilePicker.init(window.browsingContext); + MockFilePicker.returnValue = MockFilePicker.returnOK; + MockFilePicker.displayDirectory = FileUtils.getDir("TmpD", []); + MockFilePicker.setFiles([tempFile]); + MockFilePicker.afterOpenCallback = MockFilePicker.cleanup; + + try { + // Open the File Picker dialog (MockFilePicker) to select + // the files for the test. + await BrowserTestUtils.synthesizeMouseAtCenter( + "#test_input", + {}, + tab.linkedBrowser + ); + info("Waiting for the input to have the requisite files"); + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + let input = content.document.querySelector("#test_input"); + await ContentTaskUtils.waitForCondition( + () => input.files.length, + "The input should have at least one file selected" + ); + info(`The input has ${input.files.length} file(s) selected.`); + }); + } catch (e) {} + } else { + info("No real file selection required."); + } + + let awaitTooltipOpen = new Promise(resolve => { + let tooltipId = Services.appinfo.browserTabsRemoteAutostart + ? "remoteBrowserTooltip" + : "aHTMLTooltip"; + let tooltip = document.getElementById(tooltipId); + tooltip.addEventListener( + "popupshown", + function (event) { + resolve(event.target); + }, + { once: true } + ); + }); + info("Initial mouse move"); + await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 50, 5); + info("Waiting"); + await new Promise(resolve => setTimeout(resolve, 400)); + info("Second mouse move"); + await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 70, 5); + info("Waiting for tooltip to open"); + let tooltip = await awaitTooltipOpen; + + is( + tooltip.getAttribute("label"), + test.result, + "tooltip label should match expectation" + ); + + info("Closing tab"); + BrowserTestUtils.removeTab(tab); +} + +function createTempFile() { + let file = FileUtils.getDir("TmpD", []); + file.append("testfile_bug1251809"); + file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); + return file; +} diff --git a/src/zen/tests/mochitests/tooltiptext/browser_nac_tooltip.js b/src/zen/tests/mochitests/tooltiptext/browser_nac_tooltip.js new file mode 100644 index 0000000000..449c8b9da7 --- /dev/null +++ b/src/zen/tests/mochitests/tooltiptext/browser_nac_tooltip.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable mozilla/no-arbitrary-setTimeout */ + +"use strict"; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ set: [["ui.tooltip.delay_ms", 0]] }); +}); + +add_task(async function () { + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "data:text/html,", + }, + async function (browser) { + info("Moving mouse out of the way."); + await EventUtils.synthesizeAndWaitNativeMouseMove(browser, 300, 300); + + await SpecialPowers.spawn(browser, [], function () { + let widget = content.document.insertAnonymousContent(); + widget.root.innerHTML = ``; + let tttp = Cc[ + "@mozilla.org/embedcomp/default-tooltiptextprovider;1" + ].getService(Ci.nsITooltipTextProvider); + + let text = {}; + let dir = {}; + ok( + tttp.getNodeText(widget.root.querySelector("button"), text, dir), + "A tooltip should be shown for NAC" + ); + is(text.value, "foo", "Tooltip text should be correct"); + }); + + let awaitTooltipOpen = new Promise(resolve => { + let tooltipId = Services.appinfo.browserTabsRemoteAutostart + ? "remoteBrowserTooltip" + : "aHTMLTooltip"; + let tooltip = document.getElementById(tooltipId); + tooltip.addEventListener( + "popupshown", + function (event) { + resolve(event.target); + }, + { once: true } + ); + }); + + info("Initial mouse move"); + await EventUtils.synthesizeAndWaitNativeMouseMove(browser, 50, 5); + info("Waiting"); + await new Promise(resolve => setTimeout(resolve, 400)); + info("Second mouse move"); + await EventUtils.synthesizeAndWaitNativeMouseMove(browser, 70, 5); + info("Waiting for tooltip to open"); + let tooltip = await awaitTooltipOpen; + is( + tooltip.getAttribute("label"), + "foo", + "tooltip label should match expectation" + ); + } + ); +}); diff --git a/src/zen/tests/mochitests/tooltiptext/browser_shadow_dom_tooltip.js b/src/zen/tests/mochitests/tooltiptext/browser_shadow_dom_tooltip.js new file mode 100644 index 0000000000..4ceb918da1 --- /dev/null +++ b/src/zen/tests/mochitests/tooltiptext/browser_shadow_dom_tooltip.js @@ -0,0 +1,166 @@ +/* eslint-disable mozilla/no-arbitrary-setTimeout */ + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ set: [["ui.tooltip.delay_ms", 0]] }); +}); + +add_task(async function test_title_in_shadow_dom() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + + info("Moving mouse out of the way."); + await EventUtils.synthesizeAndWaitNativeMouseMove( + tab.linkedBrowser, + 300, + 300 + ); + + info("creating host"); + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + let doc = content.document; + let host = doc.createElement("div"); + doc.body.appendChild(host); + host.setAttribute("style", "position: absolute; top: 0; left: 0;"); + var sr = host.attachShadow({ mode: "closed" }); + sr.innerHTML = + "
shadow
"; + }); + + let awaitTooltipOpen = new Promise(resolve => { + let tooltipId = Services.appinfo.browserTabsRemoteAutostart + ? "remoteBrowserTooltip" + : "aHTMLTooltip"; + let tooltip = document.getElementById(tooltipId); + tooltip.addEventListener( + "popupshown", + function (event) { + resolve(event.target); + }, + { once: true } + ); + }); + info("Initial mouse move"); + await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 50, 5); + info("Waiting"); + await new Promise(resolve => setTimeout(resolve, 400)); + info("Second mouse move"); + await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 70, 5); + info("Waiting for tooltip to open"); + let tooltip = await awaitTooltipOpen; + + is( + tooltip.getAttribute("label"), + "shadow", + "tooltip label should match expectation" + ); + + info("Closing tab"); + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_title_in_light_dom() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + + info("Moving mouse out of the way."); + await EventUtils.synthesizeAndWaitNativeMouseMove( + tab.linkedBrowser, + 300, + 300 + ); + + info("creating host"); + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + let doc = content.document; + let host = doc.createElement("div"); + host.title = "light"; + doc.body.appendChild(host); + host.setAttribute("style", "position: absolute; top: 0; left: 0;"); + var sr = host.attachShadow({ mode: "closed" }); + sr.innerHTML = "
shadow
"; + }); + + let awaitTooltipOpen = new Promise(resolve => { + let tooltipId = Services.appinfo.browserTabsRemoteAutostart + ? "remoteBrowserTooltip" + : "aHTMLTooltip"; + let tooltip = document.getElementById(tooltipId); + tooltip.addEventListener( + "popupshown", + function (event) { + resolve(event.target); + }, + { once: true } + ); + }); + info("Initial mouse move"); + await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 50, 5); + info("Waiting"); + await new Promise(resolve => setTimeout(resolve, 400)); + info("Second mouse move"); + await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 70, 5); + info("Waiting for tooltip to open"); + let tooltip = await awaitTooltipOpen; + + is( + tooltip.getAttribute("label"), + "light", + "tooltip label should match expectation" + ); + + info("Closing tab"); + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_title_through_slot() { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + + info("Moving mouse out of the way."); + await EventUtils.synthesizeAndWaitNativeMouseMove( + tab.linkedBrowser, + 300, + 300 + ); + + info("creating host"); + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + let doc = content.document; + let host = doc.createElement("div"); + host.title = "light"; + host.innerHTML = "
light
"; + doc.body.appendChild(host); + host.setAttribute("style", "position: absolute; top: 0; left: 0;"); + var sr = host.attachShadow({ mode: "closed" }); + sr.innerHTML = + "
"; + }); + + let awaitTooltipOpen = new Promise(resolve => { + let tooltipId = Services.appinfo.browserTabsRemoteAutostart + ? "remoteBrowserTooltip" + : "aHTMLTooltip"; + let tooltip = document.getElementById(tooltipId); + tooltip.addEventListener( + "popupshown", + function (event) { + resolve(event.target); + }, + { once: true } + ); + }); + info("Initial mouse move"); + await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 50, 5); + info("Waiting"); + await new Promise(resolve => setTimeout(resolve, 400)); + info("Second mouse move"); + await EventUtils.synthesizeAndWaitNativeMouseMove(tab.linkedBrowser, 70, 5); + info("Waiting for tooltip to open"); + let tooltip = await awaitTooltipOpen; + + is( + tooltip.getAttribute("label"), + "shadow", + "tooltip label should match expectation" + ); + + info("Closing tab"); + BrowserTestUtils.removeTab(tab); +}); diff --git a/src/zen/tests/mochitests/tooltiptext/title_test.svg b/src/zen/tests/mochitests/tooltiptext/title_test.svg new file mode 100644 index 0000000000..80390a3cca --- /dev/null +++ b/src/zen/tests/mochitests/tooltiptext/title_test.svg @@ -0,0 +1,59 @@ + + This is a root SVG element's title + + + + + This is a non-root SVG element title + + + + + + This contains only <title> + + + + This is a title + + + + + This contains only <desc> + This is a desc + + + This contains nothing. + + + This link contains <title> + + This is a title + + + + + + + This text contains <title> + + This is a title + + + + + + This link contains <title> & xlink:title attr. + This is a title + + + + + This link contains xlink:title attr. + + + + This contains nothing. + + diff --git a/src/zen/tests/mochitests/tooltiptext/xul_tooltiptext.xhtml b/src/zen/tests/mochitests/tooltiptext/xul_tooltiptext.xhtml new file mode 100644 index 0000000000..8288ffc5fc --- /dev/null +++ b/src/zen/tests/mochitests/tooltiptext/xul_tooltiptext.xhtml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/src/zen/tests/mochitests/translations/browser.toml b/src/zen/tests/mochitests/translations/browser.toml new file mode 100644 index 0000000000..ae7d8a5cc2 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser.toml @@ -0,0 +1,285 @@ +[DEFAULT] +subsuite = "translations" +support-files = [ + "head.js", + "!/toolkit/components/translations/tests/browser/shared-head.js", + "!/toolkit/components/translations/tests/browser/translations-test.mjs", +] + +["browser_translations_about_preferences_manage_downloaded_languages.js"] + +["browser_translations_about_preferences_settings_always_translate_languages.js"] + +["browser_translations_about_preferences_settings_download_languages_all_ui.js"] + +["browser_translations_about_preferences_settings_download_languages_error_ui.js"] + +["browser_translations_about_preferences_settings_download_languages_ui.js"] + +["browser_translations_about_preferences_settings_never_translate_languages.js"] + +["browser_translations_about_preferences_settings_never_translate_sites.js"] + +["browser_translations_about_preferences_settings_ui.js"] + +["browser_translations_about_preferences_settings_ui_keyboard_a11y.js"] + +["browser_translations_about_preferences_settings_ui_tab.js"] + +["browser_translations_e2e_full_page_translate_with_lexical_shortlist.js"] + +["browser_translations_e2e_full_page_translate_without_lexical_shortlist.js"] + +["browser_translations_full_page_intersection_content_eager.js"] + +["browser_translations_full_page_intersection_find_bar.js"] + +["browser_translations_full_page_intersection_find_bar_move_tab_to_new_window.js"] + +["browser_translations_full_page_intersection_find_bar_multi_tab.js"] + +["browser_translations_full_page_intersection_lazy.js"] + +["browser_translations_full_page_intersection_mutations_content_eager.js"] + +["browser_translations_full_page_intersection_mutations_lazy.js"] + +["browser_translations_full_page_language_id_behavior.js"] + +["browser_translations_full_page_move_tab_to_new_window.js"] + +["browser_translations_full_page_moz_extension.js"] + +["browser_translations_full_page_multiple_windows.js"] +skip-if = ["os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && ccov"] # Bug 1893021 + +["browser_translations_full_page_panel_a11y_focus.js"] + +["browser_translations_full_page_panel_always_translate_language_bad_data.js"] + +["browser_translations_full_page_panel_always_translate_language_basic.js"] + +["browser_translations_full_page_panel_always_translate_language_manual.js"] + +["browser_translations_full_page_panel_always_translate_language_restore.js"] + +["browser_translations_full_page_panel_app_menu_never_translate_language.js"] + +["browser_translations_full_page_panel_app_menu_never_translate_site.js"] + +["browser_translations_full_page_panel_auto_translate_error_view.js"] + +["browser_translations_full_page_panel_auto_translate_revisit_view.js"] + +["browser_translations_full_page_panel_basics.js"] + +["browser_translations_full_page_panel_button.js"] + +["browser_translations_full_page_panel_cancel.js"] + +["browser_translations_full_page_panel_change_app_locale.js"] + +["browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_active.js"] + +["browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_inactive.js"] + +["browser_translations_full_page_panel_close_panel_never_translate_site.js"] + +["browser_translations_full_page_panel_engine_destroy.js"] + +["browser_translations_full_page_panel_engine_destroy_pending.js"] +skip-if = ["os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && ccov"] # Bug 1893021 + +["browser_translations_full_page_panel_engine_unsupported.js"] + +["browser_translations_full_page_panel_firstrun.js"] + +["browser_translations_full_page_panel_firstrun_revisit.js"] + +["browser_translations_full_page_panel_flip_lexical_shortlist.js"] + +["browser_translations_full_page_panel_fuzzing.js"] +skip-if = ["true"] + +["browser_translations_full_page_panel_gear.js"] + +["browser_translations_full_page_panel_init_failure.js"] + +["browser_translations_full_page_panel_modify_available_language_models.js"] + +["browser_translations_full_page_panel_never_translate_language.js"] + +["browser_translations_full_page_panel_never_translate_site_auto.js"] + +["browser_translations_full_page_panel_never_translate_site_basic.js"] + +["browser_translations_full_page_panel_never_translate_site_manual.js"] + +["browser_translations_full_page_panel_retry.js"] + +["browser_translations_full_page_panel_script_tags.js"] + +["browser_translations_full_page_panel_settings_unsupported_lang.js"] + +["browser_translations_full_page_panel_switch_languages.js"] + +["browser_translations_full_page_panel_switch_tabs_before_engine_ready.js"] + +["browser_translations_full_page_panel_target_language_persists_on_reopen.js"] + +["browser_translations_full_page_panel_unsupported_lang.js"] + +["browser_translations_full_page_panel_weblanguage_differs_from_app.js"] + +["browser_translations_full_page_reader_mode.js"] + +["browser_translations_full_page_telemetry_auto_translate.js"] + +["browser_translations_full_page_telemetry_basics.js"] + +["browser_translations_full_page_telemetry_open_panel.js"] + +["browser_translations_full_page_telemetry_panel_auto_offer.js"] + +["browser_translations_full_page_telemetry_panel_auto_offer_settings.js"] + +["browser_translations_full_page_telemetry_retranslate.js"] + +["browser_translations_full_page_telemetry_switch_languages.js"] + +["browser_translations_full_page_telemetry_translation_failure.js"] + +["browser_translations_full_page_telemetry_translation_request.js"] + +["browser_translations_full_page_telemetry_unsupported_lang.js"] + +["browser_translations_recent_language_memory_auto_translate.js"] + +["browser_translations_recent_language_memory_full_page_and_select.js"] + +["browser_translations_recent_language_memory_full_page_and_select_multi_window.js"] +skip-if = ["os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && ccov"] # Bug 1972458 + +["browser_translations_recent_language_memory_full_page_multi_window.js"] + +["browser_translations_recent_language_memory_full_page_multi_window_multi_tab.js"] + +["browser_translations_recent_language_memory_full_page_navigate.js"] + +["browser_translations_recent_language_memory_full_page_retranslate.js"] + +["browser_translations_select_context_menu_engine_unsupported.js"] + +["browser_translations_select_context_menu_feature_disabled.js"] + +["browser_translations_select_context_menu_preferred_app_locales.js"] + +["browser_translations_select_context_menu_preferred_language_edge_cases.js"] + +["browser_translations_select_context_menu_preferred_web_languages.js"] + +["browser_translations_select_context_menu_with_full_page_translations_active.js"] + +["browser_translations_select_context_menu_with_hyperlink.js"] + +["browser_translations_select_context_menu_with_no_text_selected.js"] + +["browser_translations_select_context_menu_with_text_selected.js"] + +["browser_translations_select_panel_a11y_utils.js"] + +["browser_translations_select_panel_change_app_locale.js"] + +["browser_translations_select_panel_close_on_new_tab.js"] + +["browser_translations_select_panel_copy_button.js"] + +["browser_translations_select_panel_engine_cache.js"] + +["browser_translations_select_panel_fallback_to_doc_language.js"] + +["browser_translations_select_panel_flip_lexical_shortlist.js"] + +["browser_translations_select_panel_init_failure.js"] + +["browser_translations_select_panel_modify_available_language_models.js"] + +["browser_translations_select_panel_pdf.js"] + +["browser_translations_select_panel_reader_mode.js"] + +["browser_translations_select_panel_retranslate_on_change_language_directly.js"] + +["browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js"] + +["browser_translations_select_panel_script_tags.js"] + +["browser_translations_select_panel_select_current_language_directly.js"] + +["browser_translations_select_panel_select_current_language_from_dropdown_menu.js"] + +["browser_translations_select_panel_select_same_from_and_to_languages_directly.js"] + +["browser_translations_select_panel_select_same_from_and_to_languages_from_dropdown_menu.js"] + +["browser_translations_select_panel_settings_menu.js"] + +["browser_translations_select_panel_translate_full_page_button.js"] + +["browser_translations_select_panel_translate_on_change_language_directly.js"] + +["browser_translations_select_panel_translate_on_change_language_from_dropdown_menu.js"] + +["browser_translations_select_panel_translate_on_change_language_multiple_times_directly.js"] + +["browser_translations_select_panel_translate_on_change_language_multiple_times_from_dropdown_menu.js"] + +["browser_translations_select_panel_translate_on_open.js"] + +["browser_translations_select_panel_translation_failure_after_unsupported_language.js"] + +["browser_translations_select_panel_translation_failure_on_open.js"] + +["browser_translations_select_panel_translation_failure_on_retranslate.js"] + +["browser_translations_select_panel_unsupported_language.js"] + +["browser_translations_select_telemetry_change_both_languages_together.js"] + +["browser_translations_select_telemetry_change_languages_multiple_times.js"] + +["browser_translations_select_telemetry_init_failure_ui_then_cancel.js"] + +["browser_translations_select_telemetry_init_failure_ui_then_succeed.js"] + +["browser_translations_select_telemetry_keypresses_cancel_button.js"] + +["browser_translations_select_telemetry_keypresses_copy_button.js"] + +["browser_translations_select_telemetry_keypresses_done_button.js"] + +["browser_translations_select_telemetry_keypresses_settings_button.js"] + +["browser_translations_select_telemetry_keypresses_translate_button.js"] + +["browser_translations_select_telemetry_keypresses_translate_full_page_button.js"] + +["browser_translations_select_telemetry_keypresses_try_again_button_init_failure.js"] + +["browser_translations_select_telemetry_keypresses_try_again_button_translation_failure.js"] + +["browser_translations_select_telemetry_multi_page.js"] + +["browser_translations_select_telemetry_primary_ui.js"] + +["browser_translations_select_telemetry_settings_menu.js"] + +["browser_translations_select_telemetry_translation_failure_ui_then_cancel.js"] + +["browser_translations_select_telemetry_translation_failure_ui_then_succeed.js"] + +["browser_translations_select_telemetry_translation_failure_with_full_page_translations_active.js"] + +["browser_translations_select_telemetry_translation_success_with_full_page_translations_active.js"] + +["browser_translations_select_telemetry_unsupported_language_ui.js"] diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_manage_downloaded_languages.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_manage_downloaded_languages.js new file mode 100644 index 0000000000..a6d7cce5f9 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_manage_downloaded_languages.js @@ -0,0 +1,225 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +function getFrenchModels() { + return languageModelNames([ + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ]); +} + +add_task(async function test_about_preferences_manage_languages() { + await testWithAndWithoutLexicalShortlist(async lexicalShortlistPrefs => { + const { + cleanup, + remoteClients, + elements: { + downloadAllLabel, + downloadAll, + deleteAll, + frenchLabel, + frenchDownload, + frenchDelete, + spanishLabel, + spanishDownload, + spanishDelete, + ukrainianLabel, + ukrainianDownload, + ukrainianDelete, + }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [ + ["browser.translations.newSettingsUI.enable", false], + ...lexicalShortlistPrefs, + ], + }); + + is( + downloadAllLabel.getAttribute("data-l10n-id"), + "translations-manage-download-description", + "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."); + is(ukrainianLabel.textContent, "Ukrainian", "There is a Ukrainian row."); + + await ensureVisibility({ + message: "Everything starts out as available to download", + visible: { + downloadAll, + frenchDownload, + spanishDownload, + ukrainianDownload, + }, + hidden: { deleteAll, frenchDelete, spanishDelete, ukrainianDelete }, + }); + + click(frenchDownload, "Downloading French"); + + const frenchModels = getFrenchModels(); + + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + frenchModels.length + ), + frenchModels, + "French models were downloaded." + ); + + await ensureVisibility({ + message: "French can now be deleted, and delete all is available.", + visible: { + downloadAll, + deleteAll, + frenchDelete, + spanishDownload, + ukrainianDownload, + }, + hidden: { frenchDownload, spanishDelete, ukrainianDelete }, + }); + + click(frenchDelete, "Deleting French"); + + await ensureVisibility({ + message: "Everything can be downloaded.", + visible: { + downloadAll, + frenchDownload, + spanishDownload, + ukrainianDownload, + }, + hidden: { deleteAll, frenchDelete, spanishDelete, ukrainianDelete }, + }); + + click(downloadAll, "Downloading all languages."); + + const allModels = languageModelNames(LANGUAGE_PAIRS); + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + allModels.length + ), + allModels, + "All models were downloaded." + ); + Assert.deepEqual( + await remoteClients.translationsWasm.resolvePendingDownloads(1), + ["bergamot-translator"], + "Wasm was downloaded." + ); + + await ensureVisibility({ + message: "Everything can be deleted.", + visible: { deleteAll, frenchDelete, spanishDelete, ukrainianDelete }, + hidden: { + downloadAll, + frenchDownload, + spanishDownload, + ukrainianDownload, + }, + }); + + click(deleteAll, "Deleting all languages."); + + await ensureVisibility({ + message: "Everything can be downloaded again", + visible: { + downloadAll, + frenchDownload, + spanishDownload, + ukrainianDownload, + }, + hidden: { deleteAll, frenchDelete, spanishDelete, ukrainianDelete }, + }); + + click(frenchDownload, "Downloading French."); + click(spanishDownload, "Downloading Spanish."); + click(ukrainianDownload, "Downloading Ukrainian."); + + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + allModels.length + ), + allModels, + "All models were downloaded again." + ); + + remoteClients.translationsWasm.assertNoNewDownloads(); + + await ensureVisibility({ + message: "Everything is downloaded again.", + visible: { deleteAll, frenchDelete, spanishDelete, ukrainianDelete }, + hidden: { + downloadAll, + frenchDownload, + spanishDownload, + ukrainianDownload, + }, + }); + + await cleanup(); + }); +}); + +add_task(async function test_about_preferences_download_reject() { + const { + cleanup, + remoteClients, + elements: { document, frenchDownload }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", false]], + }); + + click(frenchDownload, "Downloading French"); + + is( + maybeGetByL10nId("translations-manage-error-download", document), + null, + "No error messages are present." + ); + + const failureErrors = await captureTranslationsError(() => + remoteClients.translationModels.rejectPendingDownloads( + getFrenchModels().length + ) + ); + + ok( + !!failureErrors.length, + `The errors for download should have been reported, found ${failureErrors.length} errors` + ); + for (const { error } of failureErrors) { + is( + error?.message, + "Failed to download file.", + "The error reported was a download error." + ); + } + + await 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." + ); + + const successErrors = await captureTranslationsError(() => + remoteClients.translationModels.resolvePendingDownloads( + getFrenchModels().length + ) + ); + + is( + successErrors.length, + 0, + "Expected no errors downloading French the second time" + ); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_always_translate_languages.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_always_translate_languages.js new file mode 100644 index 0000000000..9f40003bfc --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_always_translate_languages.js @@ -0,0 +1,97 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task( + async function test_about_preferences_always_translate_language_settings() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", false]], + }); + + info("Ensuring the list of always-translate languages is empty"); + is( + getAlwaysTranslateLanguagesFromPref().length, + 0, + "The list of always-translate languages is empty" + ); + + info("Adding two languages to the alwaysTranslateLanguages pref"); + Services.prefs.setCharPref(ALWAYS_TRANSLATE_LANGS_PREF, "fr,de"); + + const dialogWindow = await waitForOpenDialogWindow( + "chrome://browser/content/preferences/dialogs/translations.xhtml", + () => { + click( + settingsButton, + "Opening the about:preferences Translations Settings" + ); + } + ); + let tree = dialogWindow.document.getElementById( + "alwaysTranslateLanguagesTree" + ); + let remove = dialogWindow.document.getElementById( + "removeAlwaysTranslateLanguage" + ); + let removeAll = dialogWindow.document.getElementById( + "removeAllAlwaysTranslateLanguages" + ); + + is( + tree.view.rowCount, + 2, + "The always-translate languages list has 2 items" + ); + ok(remove.disabled, "The 'Remove Language' button is disabled"); + ok(!removeAll.disabled, "The 'Remove All Languages' button is enabled"); + + info("Selecting the first always-translate language."); + tree.view.selection.select(0); + ok(!remove.disabled, "The 'Remove Language' button is enabled"); + + click(remove, "Clicking the remove-language button"); + is( + tree.view.rowCount, + 1, + "The always-translate languages list now contains 1 item" + ); + is( + getAlwaysTranslateLanguagesFromPref().length, + 1, + "One language tag in the pref" + ); + + info("Removing all languages from the alwaysTranslateLanguages pref"); + Services.prefs.setCharPref(ALWAYS_TRANSLATE_LANGS_PREF, ""); + is(tree.view.rowCount, 0, "The always-translate languages list is empty"); + ok(remove.disabled, "The 'Remove Language' button is disabled"); + ok(removeAll.disabled, "The 'Remove All Languages' button is disabled"); + + info("Adding more languages to the alwaysTranslateLanguages pref"); + Services.prefs.setCharPref(ALWAYS_TRANSLATE_LANGS_PREF, "fr,en,es"); + is( + tree.view.rowCount, + 3, + "The always-translate languages list has 3 items" + ); + ok(remove.disabled, "The 'Remove Language' button is disabled"); + ok(!removeAll.disabled, "The 'Remove All Languages' button is enabled"); + + click(removeAll, "Clicking the remove-all languages button"); + is(tree.view.rowCount, 0, "The always-translate languages list is empty"); + ok(remove.disabled, "The 'Remove Language' button is disabled"); + ok(removeAll.disabled, "The 'Remove All Languages' button is disabled"); + is( + getAlwaysTranslateLanguagesFromPref().length, + 0, + "There are no languages in the alwaysTranslateLanguages pref" + ); + + await waitForCloseDialogWindow(dialogWindow); + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_all_ui.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_all_ui.js new file mode 100644 index 0000000000..f9e7aab9fb --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_all_ui.js @@ -0,0 +1,159 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function test_translations_settings_download_languages_all() { + const { + cleanup, + remoteClients, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + const frenchModels = languageModelNames([ + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ]); + + const spanishModels = languageModelNames([ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + ]); + + const ukrainianModels = languageModelNames([ + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ]); + + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + const { downloadLanguageList } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + info( + "Install each language French, Spanish and Ukrainian and check if All language state changes to 'all language downloaded' by changing the all language button icon to 'remove icon'" + ); + + info("Download French language model."); + let langFr = Array.from(downloadLanguageList.querySelectorAll("label")).find( + el => el.getAttribute("value") === "fr" + ); + + let clickButton = BrowserTestUtils.waitForEvent( + langFr.parentNode.querySelector("moz-button"), + "click" + ); + langFr.parentNode.querySelector("moz-button").click(); + await clickButton; + + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + frenchModels.length + ), + frenchModels, + "French models were downloaded." + ); + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langFr, + "translations-settings-remove-icon", + "Delete icon is visible for French language hence downloaded" + ); + + info("Download Spanish language model."); + + let langEs = Array.from(downloadLanguageList.querySelectorAll("label")).find( + el => el.getAttribute("value") === "es" + ); + + clickButton = BrowserTestUtils.waitForEvent( + langEs.parentNode.querySelector("moz-button"), + "click" + ); + langEs.parentNode.querySelector("moz-button").click(); + await clickButton; + + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + spanishModels.length + ), + spanishModels, + "Spanish models were downloaded." + ); + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langEs, + "translations-settings-remove-icon", + "Delete icon is visible for Spanish language hence downloaded" + ); + + info("Download Ukrainian language model."); + + let langUk = Array.from(downloadLanguageList.querySelectorAll("label")).find( + el => el.getAttribute("value") === "uk" + ); + + clickButton = BrowserTestUtils.waitForEvent( + langUk.parentNode.querySelector("moz-button"), + "click" + ); + langUk.parentNode.querySelector("moz-button").click(); + await clickButton; + + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + ukrainianModels.length + ), + ukrainianModels, + "Ukrainian models were downloaded." + ); + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langUk, + "translations-settings-remove-icon", + "Delete icon is visible for Ukranian language hence downloaded." + ); + + // Download "All languages" is the first child + let langAll = downloadLanguageList.children[0]; + + ok( + langAll + .querySelector("moz-button") + .classList.contains("translations-settings-remove-icon"), + "Delete icon is visible for All Languages after all individual language models were downloaded." + ); + + info( + "Remove one language ensure that All Languages change state changes to 'removed' to indicate that all languages are not downloaded." + ); + + info("Remove Spanish language model."); + langEs.parentNode.querySelector("moz-button").click(); + await clickButton; + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langEs, + "translations-settings-download-icon", + "Download icon is visible for Spanish language hence removed" + ); + + ok( + langAll + .querySelector("moz-button") + .classList.contains("translations-settings-download-icon"), + "Download icon is visible for all languages i.e. all languages are not downloaded since one language, Spanish was removed." + ); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_error_ui.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_error_ui.js new file mode 100644 index 0000000000..3406256b93 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_error_ui.js @@ -0,0 +1,173 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task( + async function test_translations_settings_download_languages_error_handling() { + const { + cleanup, + remoteClients, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + const frenchModels = languageModelNames([ + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ]); + + const spanishModels = languageModelNames([ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + ]); + + const allModels = languageModelNames(LANGUAGE_PAIRS); + + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + const { downloadLanguageList } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + info("Test French language model for download error"); + + let langFr = Array.from( + downloadLanguageList.querySelectorAll("label") + ).find(el => el.getAttribute("value") === "fr"); + + let clickButton = BrowserTestUtils.waitForEvent( + langFr.parentNode.querySelector("moz-button"), + "click" + ); + langFr.parentNode.querySelector("moz-button").click(); + await clickButton; + + await captureTranslationsError(() => + remoteClients.translationModels.rejectPendingDownloads( + frenchModels.length + ) + ); + + const errorElement = gBrowser.selectedBrowser.contentDocument.querySelector( + ".translations-settings-language-error" + ); + + assertVisibility({ + message: "Moz-message-bar with error message is visible", + visible: { errorElement }, + }); + is( + document.l10n.getAttributes(errorElement).id, + "translations-settings-language-download-error", + "Error message correctly shows download error" + ); + is( + document.l10n.getAttributes(errorElement).args.name, + "French", + "Error message correctly shows download error for French language" + ); + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langFr, + "translations-settings-download-icon", + "Download icon is visible on French button" + ); + + remoteClients.translationsWasm.assertNoNewDownloads(); + + info("Download Spanish language model successfully."); + + let langEs = Array.from( + downloadLanguageList.querySelectorAll("label") + ).find(el => el.getAttribute("value") === "es"); + + clickButton = BrowserTestUtils.waitForEvent( + langEs.parentNode.querySelector("moz-button"), + "click" + ); + langEs.parentNode.querySelector("moz-button").click(); + await clickButton; + + const errorElementEs = + gBrowser.selectedBrowser.contentDocument.querySelector( + ".translations-settings-language-error" + ); + + ok( + !errorElementEs, + "Previous error is remove when new action occured, i.e. click download Spanish button" + ); + + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + spanishModels.length + ), + spanishModels, + "Spanish models were downloaded." + ); + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langEs, + "translations-settings-remove-icon", + "Delete icon is visible for Spanish language hence downloaded" + ); + + info("Test All language models download error"); + // Download "All languages" is the first child + let langAll = downloadLanguageList.children[0]; + + let clickButtonAll = BrowserTestUtils.waitForEvent( + langAll.querySelector("moz-button"), + "click" + ); + langAll.querySelector("moz-button").click(); + await clickButtonAll; + + await captureTranslationsError(() => + remoteClients.translationModels.rejectPendingDownloads(allModels.length) + ); + + await captureTranslationsError(() => + remoteClients.translationsWasm.rejectPendingDownloads(allModels.length) + ); + + remoteClients.translationsWasm.assertNoNewDownloads(); + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langAll, + "translations-settings-download-icon", + "Download icon is visible for 'all languages'" + ); + + const errorElementAll = + gBrowser.selectedBrowser.contentDocument.querySelector( + ".translations-settings-language-error" + ); + + assertVisibility({ + message: "Moz-message-bar with error message is visible", + visible: { errorElementAll }, + }); + is( + document.l10n.getAttributes(errorElementAll).id, + "translations-settings-language-download-error", + "Error message correctly shows download error" + ); + is( + document.l10n.getAttributes(errorElementAll).args.name, + "all", + "Error message correctly shows download error for all language" + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_ui.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_ui.js new file mode 100644 index 0000000000..8bc0301f14 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_ui.js @@ -0,0 +1,117 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function test_translations_settings_download_languages() { + await testWithAndWithoutLexicalShortlist(async lexicalShortlistPrefs => { + const { + cleanup, + remoteClients, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [ + ["browser.translations.newSettingsUI.enable", true], + ...lexicalShortlistPrefs, + ], + }); + + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + const { downloadLanguageList } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + info("Test French language model install and uninstall function."); + + let langFr = Array.from( + downloadLanguageList.querySelectorAll("label") + ).find(el => el.getAttribute("value") === "fr"); + + let clickButton = BrowserTestUtils.waitForEvent( + langFr.parentNode.querySelector("moz-button"), + "click" + ); + langFr.parentNode.querySelector("moz-button").click(); + await clickButton; + + const frenchModels = languageModelNames([ + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ]); + + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + frenchModels.length + ), + frenchModels, + "French models were downloaded." + ); + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langFr, + "translations-settings-remove-icon", + "Delete icon is visible on French button." + ); + + langFr.parentNode.querySelector("moz-button").click(); + await clickButton; + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langFr, + "translations-settings-download-icon", + "Download icon is visible on French Button." + ); + + info("Test 'All language' models install and uninstall function"); + + // Download "All languages" is the first child + let langAll = downloadLanguageList.children[0]; + + let clickButtonAll = BrowserTestUtils.waitForEvent( + langAll.querySelector("moz-button"), + "click" + ); + langAll.querySelector("moz-button").click(); + await clickButtonAll; + + const allModels = languageModelNames(LANGUAGE_PAIRS); + + Assert.deepEqual( + await remoteClients.translationModels.resolvePendingDownloads( + allModels.length + ), + allModels, + "All models were downloaded." + ); + Assert.deepEqual( + await remoteClients.translationsWasm.resolvePendingDownloads(1), + ["bergamot-translator"], + "Wasm was downloaded." + ); + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langAll, + "translations-settings-remove-icon", + "Delete icon is visible on 'All languages' button" + ); + + langAll.querySelector("moz-button").click(); + await clickButton; + + await TranslationsSettingsTestUtils.downaloadButtonClick( + langAll, + "translations-settings-download-icon", + "Download icon is visible on 'All Language' button." + ); + + await cleanup(); + }); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_languages.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_languages.js new file mode 100644 index 0000000000..758cfb4fba --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_languages.js @@ -0,0 +1,89 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task( + async function test_about_preferences_never_translate_language_settings() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", false]], + }); + + info("Ensuring the list of never-translate languages is empty"); + is( + getNeverTranslateLanguagesFromPref().length, + 0, + "The list of never-translate languages is empty" + ); + + info("Adding two languages to the neverTranslateLanguages pref"); + Services.prefs.setCharPref(NEVER_TRANSLATE_LANGS_PREF, "fr,de"); + + const dialogWindow = await waitForOpenDialogWindow( + "chrome://browser/content/preferences/dialogs/translations.xhtml", + () => { + click( + settingsButton, + "Opening the about:preferences Translations Settings" + ); + } + ); + let tree = dialogWindow.document.getElementById( + "neverTranslateLanguagesTree" + ); + let remove = dialogWindow.document.getElementById( + "removeNeverTranslateLanguage" + ); + let removeAll = dialogWindow.document.getElementById( + "removeAllNeverTranslateLanguages" + ); + + is(tree.view.rowCount, 2, "The never-translate languages list has 2 items"); + ok(remove.disabled, "The 'Remove Language' button is disabled"); + ok(!removeAll.disabled, "The 'Remove All Languages' button is enabled"); + + info("Selecting the first never-translate language."); + tree.view.selection.select(0); + ok(!remove.disabled, "The 'Remove Language' button is enabled"); + + click(remove, "Clicking the remove-language button"); + is( + tree.view.rowCount, + 1, + "The never-translate languages list now contains 1 item" + ); + is( + getNeverTranslateLanguagesFromPref().length, + 1, + "One language tag in the pref" + ); + + info("Removing all languages from the neverTranslateLanguages pref"); + Services.prefs.setCharPref(NEVER_TRANSLATE_LANGS_PREF, ""); + is(tree.view.rowCount, 0, "The never-translate languages list is empty"); + ok(remove.disabled, "The 'Remove Language' button is disabled"); + ok(removeAll.disabled, "The 'Remove All Languages' button is disabled"); + + info("Adding more languages to the neverTranslateLanguages pref"); + Services.prefs.setCharPref(NEVER_TRANSLATE_LANGS_PREF, "fr,en,es"); + is(tree.view.rowCount, 3, "The never-translate languages list has 3 items"); + ok(remove.disabled, "The 'Remove Language' button is disabled"); + ok(!removeAll.disabled, "The 'Remove All Languages' button is enabled"); + + click(removeAll, "Clicking the remove-all languages button"); + is(tree.view.rowCount, 0, "The never-translate languages list is empty"); + ok(remove.disabled, "The 'Remove Language' button is disabled"); + ok(removeAll.disabled, "The 'Remove All Languages' button is disabled"); + is( + getNeverTranslateLanguagesFromPref().length, + 0, + "There are no languages in the neverTranslateLanguages pref" + ); + + await waitForCloseDialogWindow(dialogWindow); + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_sites.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_sites.js new file mode 100644 index 0000000000..dea7b1c473 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_sites.js @@ -0,0 +1,124 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { PermissionTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PermissionTestUtils.sys.mjs" +); + +add_task(async function test_about_preferences_never_translate_site_settings() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", false]], + permissionsUrls: [ + "https://example.com", + "https://example.org", + "https://example.net", + ], + }); + + info("Ensuring the list of never-translate sites is empty"); + is( + getNeverTranslateSitesFromPerms().length, + 0, + "The list of never-translate sites is empty" + ); + + info("Adding two sites to the neverTranslateSites perms"); + PermissionTestUtils.add( + "https://example.com", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + PermissionTestUtils.add( + "https://example.org", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + PermissionTestUtils.add( + "https://example.net", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + + const dialogWindow = await waitForOpenDialogWindow( + "chrome://browser/content/preferences/dialogs/translations.xhtml", + () => { + click( + settingsButton, + "Opening the about:preferences Translations Settings" + ); + } + ); + let tree = dialogWindow.document.getElementById("neverTranslateSitesTree"); + let remove = dialogWindow.document.getElementById("removeNeverTranslateSite"); + let removeAll = dialogWindow.document.getElementById( + "removeAllNeverTranslateSites" + ); + + is(tree.view.rowCount, 3, "The never-translate sites list has 2 items"); + ok(remove.disabled, "The 'Remove Site' button is disabled"); + ok(!removeAll.disabled, "The 'Remove All Sites' button is enabled"); + + info("Selecting the first never-translate site."); + tree.view.selection.select(0); + ok(!remove.disabled, "The 'Remove Site' button is enabled"); + + click(remove, "Clicking the remove-site button"); + is( + tree.view.rowCount, + 2, + "The never-translate sites list now contains 2 items" + ); + is( + getNeverTranslateSitesFromPerms().length, + 2, + "There are 2 sites with permissions" + ); + + info("Removing all sites from the neverTranslateSites perms"); + PermissionTestUtils.remove("https://example.com", TRANSLATIONS_PERMISSION); + PermissionTestUtils.remove("https://example.org", TRANSLATIONS_PERMISSION); + PermissionTestUtils.remove("https://example.net", TRANSLATIONS_PERMISSION); + + is(tree.view.rowCount, 0, "The never-translate sites list is empty"); + ok(remove.disabled, "The 'Remove Site' button is disabled"); + ok(removeAll.disabled, "The 'Remove All Sites' button is disabled"); + + info("Adding more sites to the neverTranslateSites perms"); + PermissionTestUtils.add( + "https://example.org", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + PermissionTestUtils.add( + "https://example.com", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + PermissionTestUtils.add( + "https://example.net", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + + is(tree.view.rowCount, 3, "The never-translate sites list has 3 items"); + ok(remove.disabled, "The 'Remove Site' button is disabled"); + ok(!removeAll.disabled, "The 'Remove All Sites' button is enabled"); + + click(removeAll, "Clicking the remove-all sites button"); + is(tree.view.rowCount, 0, "The never-translate sites list is empty"); + ok(remove.disabled, "The 'Remove Site' button is disabled"); + ok(removeAll.disabled, "The 'Remove All Sites' button is disabled"); + is( + getNeverTranslateSitesFromPerms().length, + 0, + "There are no sites in the neverTranslateSites perms" + ); + + await waitForCloseDialogWindow(dialogWindow); + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui.js new file mode 100644 index 0000000000..733b3822b5 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui.js @@ -0,0 +1,462 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function test_translations_settings_pane_elements() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + const { + translationsSettingsBackButton, + translationsSettingsHeader, + translationsSettingsDescription, + translateAlwaysHeader, + translateNeverHeader, + alwaysTranslateMenuList, + neverTranslateMenuList, + translateNeverSiteHeader, + translateNeverSiteDesc, + downloadLanguageSection, + translateDownloadLanguagesLearnMore, + } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + const translateDownloadLanguagesHeader = + downloadLanguageSection.querySelector("h2"); + assertVisibility({ + message: "Expect paneTranslations elements to be visible.", + visible: { + translationsSettingsBackButton, + translationsSettingsHeader, + translationsSettingsDescription, + translateAlwaysHeader, + translateNeverHeader, + alwaysTranslateMenuList, + neverTranslateMenuList, + translateNeverSiteHeader, + translateNeverSiteDesc, + translateDownloadLanguagesLearnMore, + }, + hidden: { + settingsButton, + }, + }); + + info( + "In translations settings page, click on back button to go back to main preferences page." + ); + const paneEvent = BrowserTestUtils.waitForEvent( + document, + "paneshown", + false, + event => event.detail.category === "paneGeneral" + ); + + click(translationsSettingsBackButton); + await paneEvent; + + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { + settingsButton, + }, + hidden: { + translationsSettingsBackButton, + translationsSettingsHeader, + translationsSettingsDescription, + translateAlwaysHeader, + translateNeverHeader, + alwaysTranslateMenuList, + neverTranslateMenuList, + translateNeverSiteHeader, + translateNeverSiteDesc, + translateDownloadLanguagesHeader, + translateDownloadLanguagesLearnMore, + }, + }); + await cleanup(); +}); + +add_task(async function test_translations_settings_always_translate() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + const { + alwaysTranslateMenuList, + alwaysTranslateLanguageList, + alwaysTranslateMenuPopup, + } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + info("Testing the Always translate langauge settings"); + await testLanguageList( + alwaysTranslateLanguageList, + alwaysTranslateMenuList, + alwaysTranslateMenuPopup, + ALWAYS_TRANSLATE_LANGS_PREF, + "Always" + ); + await testLanguageListWithPref( + alwaysTranslateLanguageList, + ALWAYS_TRANSLATE_LANGS_PREF, + "Always" + ); + + await cleanup(); +}); + +add_task(async function test_translations_settings_never_translate() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + const { + neverTranslateMenuList, + neverTranslateLanguageList, + neverTranslateMenuPopup, + } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + info("Testing the Never translate langauge settings"); + await testLanguageList( + neverTranslateLanguageList, + neverTranslateMenuList, + neverTranslateMenuPopup, + NEVER_TRANSLATE_LANGS_PREF, + "Never" + ); + await testLanguageListWithPref( + neverTranslateLanguageList, + NEVER_TRANSLATE_LANGS_PREF, + "Never" + ); + await cleanup(); +}); +function getLangsFromPref(pref) { + let rawLangs = Services.prefs.getCharPref(pref); + if (!rawLangs) { + return []; + } + let langArr = rawLangs.split(","); + return langArr; +} + +async function testLanguageList( + languageList, + menuList, + menuPopup, + pref, + sectionName +) { + info("Ensure the Always/Never list is empty initially."); + + is( + languageList.childElementCount, + 0, + `Language list empty in ${sectionName} Translate list` + ); + + const menuItems = menuPopup.children; + + info( + "Click each language on the menulist to add it into the Always/Never list." + ); + for (const menuItem of menuItems) { + menuList.open = true; + + let clickMenu = BrowserTestUtils.waitForEvent( + menuList.querySelector("menupopup"), + "popuphidden" + ); + click(menuItem); + menuList.querySelector("menupopup").hidePopup(); + await clickMenu; + + /** Languages are always added on the top, so check the firstChild + * for newly added languages. + * the firstChild.querySelector("label").innerText is the language display name + * which is compared with the menulist display name that is selected + */ + let langElem = languageList.firstElementChild; + const displayName = getIntlDisplayName(menuItem.value); + is( + langElem.querySelector("label").innerText, + displayName, + `Language list has element ${displayName}` + ); + + const langTag = langElem.querySelector("label").getAttribute("value"); + ok( + getLangsFromPref(pref).includes(langTag), + `Perferences contains ${langTag}` + ); + } + /** The test cases has 4 languages, so check if 4 languages are added to the list */ + let langNum = languageList.childElementCount; + is(langNum, 4, "Number of languages added is 4"); + + info( + "Remove each language from the Always/Never list that we added initially." + ); + for (let i = 0; i < langNum; i++) { + // Delete the first language in the list + let langElem = languageList.children[0]; + let langName = langElem.querySelector("label").innerText; + const langTag = langElem.querySelector("label").getAttribute("value"); + let langButton = langElem.querySelector("moz-button"); + let clickButton = BrowserTestUtils.waitForEvent(langButton, "click"); + langButton.click(); + await clickButton; + + ok( + !getLangsFromPref(pref).includes(langTag), + `Perferences does not contain ${langTag}` + ); + + if (i < langNum) { + is( + languageList.childElementCount, + langNum - i - 1, + `${langName} removed from ${sectionName} Translate` + ); + } + } +} + +async function testLanguageListWithPref(languageList, pref, sectionName) { + const langs = [ + "fr", + "de", + "en", + "es", + "fr,de", + "fr,en", + "fr,es", + "de,en", + "de,en,es", + "es,fr,en", + "en,es,fr,de", + ]; + + info("Ensure the Always/Never list is empty initially."); + + is( + languageList.childElementCount, + 0, + `Language list is empty in ${sectionName} Translate list` + ); + + info( + "Add languages to the Always/Never list in translations setting by setting the ALWAYS_TRANSLATE_LANGS_PREF/NEVER_TRANSLATE_LANGS_PREF." + ); + + for (const langOptions of langs) { + Services.prefs.setCharPref(pref, langOptions); + + /** Languages are always added on the top, so check the firstChild + * for newly added languages. + * the firstChild.querySelector("label").innerText is the language display name + * which is compared with the menulist display name that is selected + */ + + const langsAdded = langOptions.split(","); + is( + languageList.childElementCount, + langsAdded.length, + `Language list has ${langsAdded.length} elements ` + ); + + let langsAddedHtml = Array.from(languageList.querySelectorAll("label")); + + for (const lang of langsAdded) { + const langFind = langsAddedHtml + .find(el => el.getAttribute("value") === lang) + .getAttribute("value"); + is(langFind, lang, `Language list has element ${lang}`); + } + } + + Services.prefs.setCharPref(pref, ""); + is( + languageList.childElementCount, + 0, + `All removed from ${sectionName} Translate` + ); +} + +const { PermissionTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PermissionTestUtils.sys.mjs" +); + +add_task(async function test_translations_settings_never_translate_site() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + const { neverTranslateSiteList } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + info("Ensuring the list of never-translate sites is empty"); + is( + getNeverTranslateSitesFromPerms().length, + 0, + "The list of never-translate sites is empty" + ); + + is( + neverTranslateSiteList.childElementCount, + 0, + "The never-translate sites html list is empty" + ); + + info("Adding sites to the neverTranslateSites perms"); + await PermissionTestUtils.add( + "https://example.com", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + await PermissionTestUtils.add( + "https://example.org", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + await PermissionTestUtils.add( + "https://example.net", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + + is( + getNeverTranslateSitesFromPerms().length, + 3, + "The list of never-translate sites has 3 elements" + ); + + is( + neverTranslateSiteList.childElementCount, + 3, + "The never-translate sites html list has 3 elements" + ); + + const permissionsUrls = [ + "https://example.com", + "https://example.org", + "https://example.net", + ]; + + info( + "Ensure that the Never translate sites in permissions settings are reflected in Never translate sites section of translations settings page" + ); + + const siteNum = neverTranslateSiteList.children.length; + for (let i = siteNum; i > 0; i--) { + is( + neverTranslateSiteList.children[i - 1].querySelector("label").textContent, + permissionsUrls[permissionsUrls.length - i], + `Never translate URL ${ + permissionsUrls[permissionsUrls.length - i] + } is added` + ); + } + + info( + "Delete each site by clicking the button in Never translate sites section of translations settings page and check if it is removed in the Never translate sites in permissions settings" + ); + for (let i = 0; i < siteNum; i++) { + // Delete the first site in the list + let siteElem = neverTranslateSiteList.children[0]; + // Delete the first language in the list + let siteName = siteElem.querySelector("label").innerText; + let siteButton = siteElem.querySelector("moz-button"); + + ok( + neverTranslateSiteList.querySelector(`label[value="${siteName}"]`), + `Site ${siteName} present in the Never transalate site list` + ); + + ok( + getNeverTranslateSitesFromPerms().find(p => p.origin === siteName), + `Site ${siteName} present in the Never transalate site permissions list` + ); + + let clickButton = BrowserTestUtils.waitForEvent(siteButton, "click"); + siteButton.click(); + await clickButton; + + ok( + !neverTranslateSiteList.querySelector(`label[value="${siteName}"]`), + `Site ${siteName} removed successfully from the Never transalate site list` + ); + + ok( + !getNeverTranslateSitesFromPerms().find(p => p.origin === siteName), + `Site ${siteName} removed from successfully from the Never transalate site permissions list` + ); + + if (i < siteNum) { + is( + neverTranslateSiteList.childElementCount, + siteNum - i - 1, + `${siteName} removed from Never Translate Site` + ); + } + const siteLen = siteNum - i - 1; + is( + getNeverTranslateSitesFromPerms().length, + siteLen, + `There are ${siteLen} site in Never translate site` + ); + } + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_keyboard_a11y.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_keyboard_a11y.js new file mode 100644 index 0000000000..b60344194f --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_keyboard_a11y.js @@ -0,0 +1,635 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { PermissionTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PermissionTestUtils.sys.mjs" +); + +add_task(async function test_translations_settings_keyboard_a11y() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + const { + translationsSettingsBackButton, + alwaysTranslateMenuList, + neverTranslateMenuList, + translateDownloadLanguagesLearnMore, + downloadLanguageList, + } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + const document = gBrowser.selectedBrowser.contentDocument; + + info("Press the Tab key to focus the first page element, the back button"); + + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + translationsSettingsBackButton.id, + "Key is focused on back button" + ); + + info( + "Press the Tab key to focus the next page element, the Always Translate Menulist button" + ); + + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + alwaysTranslateMenuList.id, + "Key is focused on Always Translate Menulist button" + ); + + info( + "Press the Tab key to focus the next page element, the Never Translate Menulist button" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + neverTranslateMenuList.id, + "Key is focused on Never Translate Menulist button" + ); + + info( + "Press the Tab key to focus the next page element, the Download Languages' Learn More link" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + translateDownloadLanguagesLearnMore.id, + "Key is focused on Download Languages' Learn More link" + ); + + info( + "Press the Tab key to focus the next page element, the Download Languages list section" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + downloadLanguageList.id, + "Key is focused on Download Languages list section" + ); + + await cleanup(); +}); + +add_task(async function test_translations_settings_keyboard_download_a11y() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + const { + translationsSettingsBackButton, + alwaysTranslateMenuList, + neverTranslateMenuList, + translateDownloadLanguagesLearnMore, + downloadLanguageList, + } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + const document = gBrowser.selectedBrowser.contentDocument; + + info("Press the Tab key to focus the first page element, the back button"); + + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + translationsSettingsBackButton.id, + "Key is focused on back button" + ); + + info( + "Press the Tab key to focus the next page element, the Always Translate Menulist button" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + alwaysTranslateMenuList.id, + "Key is focused on Always Translate Menulist button" + ); + + info( + "Press the Tab key to focus the next page element, the Never Translate Menulist button" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + neverTranslateMenuList.id, + "Key is focused on Never Translate Menulist button" + ); + + info( + "Press the Tab key to focus the next page element, the Download Languages' Learn More link" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + translateDownloadLanguagesLearnMore.id, + "Key is focused on Download Languages' Learn More link" + ); + + info( + "Press the Tab key to focus the next page element, the Download Languages list section" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + downloadLanguageList.id, + "Key is focused on Download Languages list section" + ); + + info( + "Press the Arrow Down key to focus the first language element in the Download List Section" + ); + + for (let element of downloadLanguageList.children) { + info( + "Press the Arrow Down key to focus the next language element in the Download List Section" + ); + EventUtils.synthesizeKey("KEY_ArrowDown"); + is( + document.activeElement.parentNode.id, + element.id, + "Key is focused on the language " + + element.querySelector("label").textContent + + " within the language list" + ); + } + + is( + document.activeElement.parentNode.id, + downloadLanguageList.lastElementChild.id, + "Key is focused on the last language " + + downloadLanguageList.lastElementChild.querySelector("label").textContent + + " within the language list" + ); + + info( + "Press the Arrow up key to focus the previous language element in the Download List Section" + ); + for (let i = downloadLanguageList.children.length - 2; i >= 0; i--) { + info( + "Press the Arrow up key to focus the previous language element in the Download List Section" + ); + EventUtils.synthesizeKey("KEY_ArrowUp"); + is( + document.activeElement.parentNode.id, + downloadLanguageList.children[i].id, + "Key is focused on the language " + + downloadLanguageList.children[i].querySelector("label").textContent + + " within the language list" + ); + } + + is( + document.activeElement.parentNode.id, + downloadLanguageList.firstElementChild.id, + "Key is focused on the first language within the language list" + ); + + await cleanup(); +}); + +add_task( + async function test_translations_settings_keyboard_never_translate_site_a11y() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + const { + translationsSettingsBackButton, + alwaysTranslateMenuList, + neverTranslateMenuList, + neverTranslateSiteList, + translateDownloadLanguagesLearnMore, + } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + is( + neverTranslateSiteList.childElementCount, + 0, + "The never-translate sites html list is empty" + ); + + info("Adding sites to the neverTranslateSites perms"); + await PermissionTestUtils.add( + "https://example.com", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + await PermissionTestUtils.add( + "https://example.org", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + await PermissionTestUtils.add( + "https://example.net", + TRANSLATIONS_PERMISSION, + Services.perms.DENY_ACTION + ); + + is( + getNeverTranslateSitesFromPerms().length, + 3, + "The list of never-translate sites has 3 elements" + ); + + const document = gBrowser.selectedBrowser.contentDocument; + + info("Press the Tab key to focus the first page element, the back button"); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + translationsSettingsBackButton.id, + "Key is focused on back button" + ); + + info( + "Press the Tab key to focus the next page element, the Always Translate Menulist button" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + alwaysTranslateMenuList.id, + "Key is focused on Always Translate Menulist button" + ); + + info( + "Press the Tab key to focus the next page element, the Never Translate Menulist button" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + neverTranslateMenuList.id, + "Key focus is now Never Translate List Menu button" + ); + + info( + "Press the Tab key to focus the next page element, the Never Translate Site List section" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + neverTranslateSiteList.id, + "Key focus is now Never Translate Site List" + ); + info( + "Press the Arrow Down key to focus the first site element in the Never Translate Site List" + ); + for (const site of neverTranslateSiteList.children) { + info( + "Press the Arrow Down key to focus the next site element in the Never Translate Site List" + ); + EventUtils.synthesizeKey("KEY_ArrowDown"); + is( + document.activeElement.parentNode.id, + site.id, + "Key focus is now Never Translate Site list element " + + site.querySelector("label").textContent + ); + } + is( + document.activeElement.parentNode.id, + neverTranslateSiteList.lastElementChild.id, + "Key is focused on the last site " + + neverTranslateSiteList.lastElementChild.querySelector("label") + .textContent + + " within the site list" + ); + + info( + "Press the Arrow up key to focus the previous site element in the Never Translate Site List" + ); + for (let i = neverTranslateSiteList.children.length - 2; i >= 0; i--) { + info( + "Press the Arrow up key to focus the previous site element in the Never Translate Site List" + ); + EventUtils.synthesizeKey("KEY_ArrowUp"); + is( + document.activeElement.parentNode.id, + neverTranslateSiteList.children[i].id, + "Key is focused on the site " + + neverTranslateSiteList.children[i].querySelector("label") + .textContent + + " within the site list" + ); + } + + info( + "Press the Tab key to focus the next page element, the Download Languages' Learn More link" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + translateDownloadLanguagesLearnMore.id, + "Key is focused on Download Languages' Learn More link" + ); + + await cleanup(); + } +); + +add_task( + async function test_translations_settings_keyboard_never_translate_a11y() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + const { + translationsSettingsBackButton, + alwaysTranslateMenuList, + neverTranslateMenuList, + neverTranslateLanguageList, + neverTranslateMenuPopup, + translateDownloadLanguagesLearnMore, + } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + const document = gBrowser.selectedBrowser.contentDocument; + + info("Press the Tab key to focus the first page element, the back button"); + + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + translationsSettingsBackButton.id, + "Key is focused on back button" + ); + + info( + "Press the Tab key to focus the next page element, the Always Translate Menulist button" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + alwaysTranslateMenuList.id, + "Key is focused on Always Translate Menulist button" + ); + + info( + "Press the Tab key to focus the next page element, the Never Translate Menulist button." + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + neverTranslateMenuList.id, + "Key is focused on Never Translate Menulist button" + ); + + info("Press the Arrow Down key to focus on the first list element."); + for (const menuItem of neverTranslateMenuPopup.children) { + if (AppConstants.platform === "macosx") { + info("Opening the menu popup."); + const popupPromise = BrowserTestUtils.waitForEvent( + neverTranslateMenuPopup, + "popupshown" + ); + EventUtils.synthesizeKey("KEY_ArrowDown"); + await popupPromise; + } + + EventUtils.synthesizeKey("KEY_ArrowDown"); + + if (AppConstants.platform === "macosx") { + info("Closing the menu popup."); + const popupPromise = BrowserTestUtils.waitForEvent( + neverTranslateMenuPopup, + "popuphidden" + ); + EventUtils.synthesizeKey("KEY_Enter"); + await popupPromise; + } else { + const { promise, resolve } = Promise.withResolvers(); + requestAnimationFrame(() => { + requestAnimationFrame(resolve); + }); + + EventUtils.synthesizeKey("KEY_Enter"); + await promise; + } + + is( + neverTranslateLanguageList.firstElementChild.querySelector("label") + .textContent, + menuItem.textContent, + menuItem.textContent + "is added to never translate language" + ); + } + + info( + "Press the Tab key to focus the next page element, the Never Translate list" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + neverTranslateLanguageList.id, + document.activeElement.id, + "Key is focused on Always Translate list." + ); + + info("Press the Arrow Down key to focus on the first list element."); + + for (const lang of neverTranslateLanguageList.children) { + EventUtils.synthesizeKey("KEY_ArrowDown"); + is( + document.activeElement.parentNode.id, + lang.id, + "Key is focused on " + + lang.querySelector("label").textContent + + " element of Never Translate list." + ); + } + + info( + "Press the Tab key to focus the next page element, the Download Languages' Learn More link" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + translateDownloadLanguagesLearnMore.id, + "Key is focused on Download Languages' Learn More link" + ); + + await cleanup(); + } +); + +add_task( + async function test_translations_settings_keyboard_always_translate_a11y() { + const { + cleanup, + elements: { settingsButton }, + } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + info( + "Open translations settings page by clicking on translations settings button." + ); + assertVisibility({ + message: "Expect paneGeneral elements to be visible.", + visible: { settingsButton }, + }); + + const { + translationsSettingsBackButton, + alwaysTranslateMenuList, + neverTranslateMenuList, + alwaysTranslateLanguageList, + alwaysTranslateMenuPopup, + } = + await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( + settingsButton + ); + + const document = gBrowser.selectedBrowser.contentDocument; + + info("Press the Tab key to focus the first page element, the back button"); + + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + translationsSettingsBackButton.id, + "Key is focused on back button" + ); + + info( + "Press the Tab key to focus the next page element, the Always Translate Menulist button" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + alwaysTranslateMenuList.id, + "Key is focused on Always Translate Menulist button" + ); + + info("Press the Arrow Down key to focus on the first list element."); + for (const menuItem of alwaysTranslateMenuPopup.children) { + if (AppConstants.platform === "macosx") { + info("Opening the menu popup."); + const popupPromise = BrowserTestUtils.waitForEvent( + alwaysTranslateMenuPopup, + "popupshown" + ); + EventUtils.synthesizeKey("KEY_ArrowDown"); + await popupPromise; + } + + EventUtils.synthesizeKey("KEY_ArrowDown"); + + if (AppConstants.platform === "macosx") { + info("Closing the menu popup."); + const popupPromise = BrowserTestUtils.waitForEvent( + alwaysTranslateMenuPopup, + "popuphidden" + ); + EventUtils.synthesizeKey("KEY_Enter"); + await popupPromise; + } else { + const { promise, resolve } = Promise.withResolvers(); + requestAnimationFrame(() => { + requestAnimationFrame(resolve); + }); + + EventUtils.synthesizeKey("KEY_Enter"); + await promise; + } + + is( + alwaysTranslateLanguageList.firstElementChild.querySelector("label") + .textContent, + menuItem.textContent, + menuItem.textContent + "is added to always translate language" + ); + } + + info( + "Press the Tab key to focus the next page element, the Always Translate list" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + alwaysTranslateLanguageList.id, + document.activeElement.id, + "Key is focused on Always Translate list." + ); + + info("Press the Arrow Down key to focus on the first list element."); + + for (const lang of alwaysTranslateLanguageList.children) { + EventUtils.synthesizeKey("KEY_ArrowDown"); + is( + document.activeElement.parentNode.id, + lang.id, + "Key is focused on " + + lang.querySelector("label").textContent + + " element of Always Translate list." + ); + } + + info( + "Press the Tab key to focus the next page element, the Never Translate list" + ); + EventUtils.synthesizeKey("KEY_Tab"); + is( + document.activeElement.id, + neverTranslateMenuList.id, + "Key focus is now Never Translate List Menu button" + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_tab.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_tab.js new file mode 100644 index 0000000000..51991c6662 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_tab.js @@ -0,0 +1,56 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task( + async function test_translations_settings_about_preferences_translations_tab() { + const { cleanup } = await setupAboutPreferences(LANGUAGE_PAIRS, { + prefs: [["browser.translations.newSettingsUI.enable", true]], + }); + + info( + 'Open translations settings directly with URL "about:preferences#translations" to ensure that the translations settings elements are visible. This proves that the attribute data-subpanel="true" in the translations settings elements is working' + ); + const tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "about:preferences#translations", + true // waitForLoad + ); + + const translationsPane = + content.window.gCategoryModules.get("paneTranslations"); + const { + translationsSettingsBackButton, + translationsSettingsHeader, + translationsSettingsDescription, + translateAlwaysHeader, + translateNeverHeader, + alwaysTranslateMenuList, + neverTranslateMenuList, + translateNeverSiteHeader, + translateNeverSiteDesc, + translateDownloadLanguagesLearnMore, + } = translationsPane.elements; + + assertVisibility({ + message: "Expect paneTranslations elements to be visible.", + visible: { + translationsSettingsBackButton, + translationsSettingsHeader, + translationsSettingsDescription, + translateAlwaysHeader, + translateNeverHeader, + alwaysTranslateMenuList, + neverTranslateMenuList, + translateNeverSiteHeader, + translateNeverSiteDesc, + translateDownloadLanguagesLearnMore, + }, + }); + + BrowserTestUtils.removeTab(tab); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_with_lexical_shortlist.js b/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_with_lexical_shortlist.js new file mode 100644 index 0000000000..f1e895d22e --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_with_lexical_shortlist.js @@ -0,0 +1,100 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that Lazy Full Page Translations work from Spanish to English work when + * loading pre-downloaded model and WASM artifacts from the file system with + * the useLexicalShortlist pref turned on. + */ +add_task( + async function test_lazy_full_page_translate_end_to_end_with_lexical_shortlist() { + const { cleanup, runInPage } = await loadTestPage({ + endToEndTest: true, + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.useLexicalShortlist", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton(); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + endToEndTest: true, + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await cleanup(); + } +); + +/** + * Tests that Content-Eager Full Page Translations work from Spanish to English work + * when loading pre-downloaded model and WASM artifacts from the file system with + * the useLexicalShortlist pref turned on. + */ +add_task( + async function test_content_eager_full_page_translate_end_to_end_with_lexical_shortlist() { + const { cleanup, runInPage } = await loadTestPage({ + endToEndTest: true, + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + contentEagerMode: true, + prefs: [["browser.translations.useLexicalShortlist", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton(); + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + endToEndTest: true, + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ + endToEndTest: true, + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: + "The page's H1's title should be translated because it intersects with the viewport.", + }); + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + message: + "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_without_lexical_shortlist.js b/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_without_lexical_shortlist.js new file mode 100644 index 0000000000..b1f71473c7 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_without_lexical_shortlist.js @@ -0,0 +1,100 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that Lazy Full Page Translations work from Spanish to English work when + * loading pre-downloaded model and WASM artifacts from the file system with + * the useLexicalShortlist pref turned off. + */ +add_task( + async function test_lazy_full_page_translate_end_to_end_with_lexical_shortlist() { + const { cleanup, runInPage } = await loadTestPage({ + endToEndTest: true, + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.useLexicalShortlist", false]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton(); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + endToEndTest: true, + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await cleanup(); + } +); + +/** + * Tests that Content-Eager Full Page Translations work from Spanish to English work + * when loading pre-downloaded model and WASM artifacts from the file system with + * the useLexicalShortlist pref turned off. + */ +add_task( + async function test_content_eager_full_page_translate_end_to_end_with_lexical_shortlist() { + const { cleanup, runInPage } = await loadTestPage({ + endToEndTest: true, + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + contentEagerMode: true, + prefs: [["browser.translations.useLexicalShortlist", false]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton(); + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + endToEndTest: true, + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ + endToEndTest: true, + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: + "The page's H1's title should be translated because it intersects with the viewport.", + }); + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + message: + "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_content_eager.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_content_eager.js new file mode 100644 index 0000000000..c6aa0cfddb --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_content_eager.js @@ -0,0 +1,156 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that elements with attribute translations are still picked + * up and translated once they are observed for intersection, even in content-eager mode. + */ +add_task( + async function test_nodes_entering_proximity_are_translated_in_content_eager_mode() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + contentEagerMode: true, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + message: + "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", + } + ); + + await scrollToBottomOfPage(runInPage); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await cleanup(); + } +); + +/** + * This test case ensures that translation requests for attributes leaving the viewport proximity are + * cancelled, but translation requests for content are retained in content-eager mode, even though the + * elements they belong to have left viewport proximity. + */ +add_task( + async function test_nodes_exiting_proximity_before_translation_are_cancelled_in_content_eager_mode() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + contentEagerMode: true, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton(); + + await FullPageTranslationsTestUtils.waitForAnyRequestToInitialize( + runInPage + ); + + await scrollToBottomOfPage(runInPage); + + await FullPageTranslationsTestUtils.assertPageH1ContentIsNotTranslated({ + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageH1TitleIsNotTranslated({ + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsNotTranslated( + { + runInPage, + } + ); + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + } + ); + + info("Resolving downloads after scrolling to the bottom of the page."); + await resolveDownloads(1); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + await FullPageTranslationsTestUtils.assertPageH1ContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + await FullPageTranslationsTestUtils.assertPageH1TitleIsNotTranslated({ + runInPage, + message: + "Attribute translations are always lazy based on intersection, so the page h1's title should remain untranslated.", + }); + + await scrollToTopOfPage(runInPage); + + await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar.js new file mode 100644 index 0000000000..3dc2e8e5df --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar.js @@ -0,0 +1,256 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that opening the FindBar on a page where Full-Page Translations + * is already active will enter into content-eager translations mode, allowing all content + * translations on the page to be fulfilled while attribute translations remain lazy based + * on proximity with the viewport. + */ +add_task( + async function test_findbar_open_switches_to_content_eager_mode_from_lazy_mode() { + const { cleanup, resolveDownloads, runInPage, tab } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + info( + "Opening the find bar, which should switch us into content eager mode." + ); + await openFindBar(tab); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + message: + "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", + } + ); + + await scrollToBottomOfPage(runInPage); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + info("Mutating the H1 text content and title attribute."); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + const h1 = getH1(); + + h1.innerText = "Este contenido de texto de h1 se modificó."; + h1.setAttribute("title", "Este atributo de título de h1 se modificó."); + h1.setAttribute( + "aria-label", + "Este atributo de etiqueta aria de h1 se añadió." + ); + }); + + info( + "Ensuring mutated H1 content is translated, but the mutated attributes are not." + ); + await runInPage(async TranslationsTest => { + const { getH1, getH1Title, getH1AriaLabel } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The re-mutated h1 text content is translated.", + getH1, + "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The re-mutated h1 title attribute is not translated.", + getH1Title, + "Este atributo de título de h1 se modificó." + ); + + await TranslationsTest.assertTranslationResult( + "The h1 aria-label attribute remains untranslated.", + getH1AriaLabel, + "Este atributo de etiqueta aria de h1 se añadió." + ); + }); + + info( + "Scrolling back to the top of the page so the mutated H1 intersects the viewport." + ); + await scrollToTopOfPage(runInPage); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info("Asserting the H1 is now fully translated (text and attributes)."); + await runInPage(async TranslationsTest => { + const { getH1, getH1Title, getH1AriaLabel } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The h1 text content remains translated.", + getH1, + "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The h1 title attribute is now translated after intersecting.", + getH1Title, + "ESTE ATRIBUTO DE TÍTULO DE H1 SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The h1 aria-label attribute is now translated after intersecting.", + getH1AriaLabel, + "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" + ); + }); + + await cleanup(); + } +); + +/** + * This test case ensures that closing the FindBar on a page where Full-Page Translations + * is already active will enter into lazy translations mode, ensuring that translations + * for both content and attributes are not fulfilled until the elements that they belong + * to enter proximity with the viewport. + */ +add_task( + async function test_findbar_close_switches_to_lazy_mode_from_content_eager_mode() { + const { cleanup, resolveDownloads, runInPage, tab } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + contentEagerMode: true, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + info( + "Closing the find bar, which should switch the page from content eager mode back to lazy mode." + ); + await closeFindBar(tab); + + info("Mutating the final paragraph text content and title attribute."); + await runInPage(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + const p = getFinalParagraph(); + + p.innerText = "Este contenido de texto de último párrafo se modificó."; + p.setAttribute( + "title", + "Este atributo de título de último párrafo se modificó." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info( + "Ensuring mutated final paragraph content and attributes are not translated while out of view in lazy mode." + ); + await runInPage(async TranslationsTest => { + const { getFinalParagraph, getFinalParagraphTitle } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph text content is not translated.", + getFinalParagraph, + "Este contenido de texto de último párrafo se modificó." + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph title attribute is not translated.", + getFinalParagraphTitle, + "Este atributo de título de último párrafo se modificó." + ); + }); + + info("Scrolling to the bottom of the page so the paragraph intersects."); + await scrollToBottomOfPage(runInPage); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info( + "Asserting the mutated final paragraph content and title are now translated after intersecting." + ); + await runInPage(async TranslationsTest => { + const { getFinalParagraph, getFinalParagraphTitle } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph text content is translated.", + getFinalParagraph, + "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph title attribute is translated.", + getFinalParagraphTitle, + "ESTE ATRIBUTO DE TÍTULO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_move_tab_to_new_window.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_move_tab_to_new_window.js new file mode 100644 index 0000000000..f15b734bfd --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_move_tab_to_new_window.js @@ -0,0 +1,267 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that opening the FindBar on a page where Full-Page Translations is active + * transitions into content-eager translations mode, even after moving the tab to a new window, which + * necessarily changes to a different FindBar instance. + */ +add_task( + async function test_findbar_open_switches_to_content_eager_mode_after_moving_tab_to_new_window() { + const window1 = window; + const { cleanup, resolveDownloads, runInPage, tab } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible.", + window1 + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + win: window1, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + win: window1, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + info("Moving the tab to a new window of its own."); + const window2 = await window1.gBrowser.replaceTabWithWindow(tab); + const swapDocShellPromise = BrowserTestUtils.waitForEvent( + tab.linkedBrowser, + "SwapDocShells" + ); + await swapDocShellPromise; + + const tab2 = window2.gBrowser.selectedTab; + function runInPage2(callback, data = {}) { + return ContentTask.spawn( + tab2.linkedBrowser, + { contentData: data, callbackSource: callback.toString() }, + function ({ contentData, callbackSource }) { + const TranslationsTest = ChromeUtils.importESModule( + "chrome://mochitests/content/browser/toolkit/components/translations/tests/browser/translations-test.mjs" + ); + TranslationsTest.setup({ Assert, ContentTaskUtils, content }); + // eslint-disable-next-line no-eval + let contentCallback = eval(`(${callbackSource})`); + return contentCallback(TranslationsTest, contentData); + } + ); + } + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible.", + window2 + ); + + info( + "Opening the find bar in the new window, which should switch us into content eager mode." + ); + await openFindBar(tab2, window2); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + win: window2, + fromLanguage: "es", + toLanguage: "en", + runInPage: runInPage2, + }); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + win: window2, + runInPage: runInPage2, + message: + "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", + } + ); + + await scrollToBottomOfPage(runInPage2); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( + { + win: window2, + fromLanguage: "es", + toLanguage: "en", + runInPage: runInPage2, + } + ); + + await cleanup(); + await BrowserTestUtils.closeWindow(window2); + } +); + +/** + * This test case ensures that closing the FindBar on a page where Full-Page Translations is active + * transitions into lazy translations mode, even after moving the tab to a new window, which + * necessarily changes to a different FindBar instance. + */ +add_task( + async function test_findbar_close_switches_to_lazy_mode_after_moving_tab_to_new_window() { + const window1 = window; + const { cleanup, resolveDownloads, runInPage, tab } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + contentEagerMode: true, + }); + + // Moving a tab to a new window with the findbar open appears to modify this pref. + // Pushing it to a pref env ensures that a failure will not be reported due to the pref changing. + await SpecialPowers.pushPrefEnv({ + set: [["accessibility.typeaheadfind.flashBar", 0]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible.", + window1 + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + win: window1, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + win: window1, + }); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + info("Moving the tab to a new window of its own."); + const window2 = await window1.gBrowser.replaceTabWithWindow(tab); + const swapDocShellPromise = BrowserTestUtils.waitForEvent( + tab.linkedBrowser, + "SwapDocShells" + ); + await swapDocShellPromise; + + const tab2 = window2.gBrowser.selectedTab; + function runInPage2(callback, data = {}) { + return ContentTask.spawn( + tab2.linkedBrowser, + { contentData: data, callbackSource: callback.toString() }, + function ({ contentData, callbackSource }) { + const TranslationsTest = ChromeUtils.importESModule( + "chrome://mochitests/content/browser/toolkit/components/translations/tests/browser/translations-test.mjs" + ); + TranslationsTest.setup({ Assert, ContentTaskUtils, content }); + // eslint-disable-next-line no-eval + let contentCallback = eval(`(${callbackSource})`); + return contentCallback(TranslationsTest, contentData); + } + ); + } + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible.", + window2 + ); + + info( + "Closing the find bar in the new window, which should switch the page back to lazy mode." + ); + await closeFindBar(tab2, window2); + + info("Mutating the final paragraph text content and title attribute."); + await runInPage2(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + const p = getFinalParagraph(); + + p.innerText = "Este contenido de texto de último párrafo se modificó."; + p.setAttribute( + "title", + "Este atributo de título de último párrafo se modificó." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage2 + ); + + info( + "Ensuring mutated final paragraph content and attributes are not translated while out of view in lazy mode." + ); + await runInPage2(async TranslationsTest => { + const { getFinalParagraph, getFinalParagraphTitle } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph text content is not translated.", + getFinalParagraph, + "Este contenido de texto de último párrafo se modificó." + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph title attribute is not translated.", + getFinalParagraphTitle, + "Este atributo de título de último párrafo se modificó." + ); + }); + + info("Scrolling to the bottom of the page so the paragraph intersects."); + await scrollToBottomOfPage(runInPage2); + + await resolveDownloads(1); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage2 + ); + + info( + "Asserting the mutated final paragraph content and title are now translated after intersecting." + ); + await runInPage2(async TranslationsTest => { + const { getFinalParagraph, getFinalParagraphTitle } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph text content is translated.", + getFinalParagraph, + "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph title attribute is translated.", + getFinalParagraphTitle, + "ESTE ATRIBUTO DE TÍTULO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + }); + + await SpecialPowers.popPrefEnv(); + + await cleanup(); + await BrowserTestUtils.closeWindow(window2); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_multi_tab.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_multi_tab.js new file mode 100644 index 0000000000..cb0e5d702d --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_multi_tab.js @@ -0,0 +1,256 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that when more than one tab is open to a page + * each with Full-Page Translations active, that opening the FindBar + * in one tab and transitioning to content-eager translations mode + * does not affect the other tab. + */ +add_task(async function test_findbar_open_affects_only_target_tab() { + const { + cleanup, + resolveDownloads, + runInPage: runInSpanishDotCom, + tab: spanishDotComTab, + } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage: runInSpanishDotCom, + }); + + const { + tab: spanishDotOrgTab, + runInPage: runInSpanishDotOrg, + removeTab: removeSpanishDotOrgTab, + } = await addTab(SPANISH_PAGE_URL_DOT_ORG); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + await FullPageTranslationsTestUtils.clickTranslateButton(); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage: runInSpanishDotOrg, + }); + + info("Opening the find bar in the .org tab."); + await openFindBar(spanishDotOrgTab); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage: runInSpanishDotOrg, + }); + + await switchTab(spanishDotComTab); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage: runInSpanishDotCom, + }); + + info("Mutating the final paragraph in the .com tab."); + await runInSpanishDotCom(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + const p = getFinalParagraph(); + p.innerText = "Este contenido de texto de último párrafo se modificó."; + p.setAttribute( + "title", + "Este atributo de título de último párrafo se modificó." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInSpanishDotCom + ); + + await runInSpanishDotCom(async TranslationsTest => { + const { getFinalParagraph, getFinalParagraphTitle } = + TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "Paragraph text remains untranslated in .com tab.", + getFinalParagraph, + "Este contenido de texto de último párrafo se modificó." + ); + await TranslationsTest.assertTranslationResult( + "Paragraph title remains untranslated in .com tab.", + getFinalParagraphTitle, + "Este atributo de título de último párrafo se modificó." + ); + }); + + info("Opening the find bar in the .com tab."); + await openFindBar(spanishDotComTab); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInSpanishDotCom + ); + + await runInSpanishDotCom(async TranslationsTest => { + const { getFinalParagraph, getFinalParagraphTitle } = + TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "Paragraph text translated in .com tab.", + getFinalParagraph, + "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "Paragraph title remains untranslated in .com tab.", + getFinalParagraphTitle, + "Este atributo de título de último párrafo se modificó." + ); + }); + + await removeSpanishDotOrgTab(); + await cleanup(); +}); + +/** + * This test case ensures that when more than one tab is open to a page + * each with Full-Page Translations active, that closing the FindBar + * in one tab and transitioning to lazy translations mode does not affect + * the other tab. + */ +add_task(async function test_findbar_close_affects_only_target_tab() { + const { + cleanup, + resolveDownloads, + runInPage: runInSpanishDotCom, + tab: spanishDotComTab, + } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + contentEagerMode: true, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage: runInSpanishDotCom, + }); + + const { + tab: spanishDotOrgTab, + runInPage: runInSpanishDotOrg, + removeTab: removeSpanishDotOrgTab, + } = await addTab(SPANISH_PAGE_URL_DOT_ORG); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + await FullPageTranslationsTestUtils.clickTranslateButton(); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage: runInSpanishDotOrg, + }); + + info("Opening the find bar in the .org tab."); + await openFindBar(spanishDotOrgTab); + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage: runInSpanishDotOrg, + }); + + await switchTab(spanishDotComTab); + + info("Closing the find bar in the .com tab."); + await closeFindBar(spanishDotComTab); + + info("Mutating the final paragraph in the .com tab."); + await runInSpanishDotCom(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + const p = getFinalParagraph(); + p.innerText = "Este contenido de texto de último párrafo se modificó."; + p.setAttribute( + "title", + "Este atributo de título de último párrafo se modificó." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInSpanishDotCom + ); + + await runInSpanishDotCom(async TranslationsTest => { + const { getFinalParagraph, getFinalParagraphTitle } = + TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "Paragraph text remains untranslated in .com tab.", + getFinalParagraph, + "Este contenido de texto de último párrafo se modificó." + ); + await TranslationsTest.assertTranslationResult( + "Paragraph title remains untranslated in .com tab.", + getFinalParagraphTitle, + "Este atributo de título de último párrafo se modificó." + ); + }); + + await switchTab(spanishDotOrgTab); + + info("Mutating the final paragraph in the .org tab."); + await runInSpanishDotOrg(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + const p = getFinalParagraph(); + p.innerText = "Este contenido de texto de último párrafo se modificó."; + p.setAttribute( + "title", + "Este atributo de título de último párrafo se modificó." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInSpanishDotOrg + ); + + await runInSpanishDotOrg(async TranslationsTest => { + const { getFinalParagraph, getFinalParagraphTitle } = + TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "Paragraph text translated in .org tab.", + getFinalParagraph, + "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + await TranslationsTest.assertTranslationResult( + "Paragraph title remains untranslated in .org tab.", + getFinalParagraphTitle, + "Este atributo de título de último párrafo se modificó." + ); + }); + + await removeSpanishDotOrgTab(); + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_lazy.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_lazy.js new file mode 100644 index 0000000000..9e311901ef --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_lazy.js @@ -0,0 +1,161 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that elements with translatable content and attributes are + * picked up and translated once they enter viewport proximity in lazy translations mode. + */ +add_task( + async function test_nodes_entering_proximity_are_translated_in_lazy_mode() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await scrollToBottomOfPage(runInPage); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await cleanup(); + } +); + +/** + * This test case ensures that elements with translatable content and attributes that + * exit viewport proximity are prevented from translating in lazy translations mode. + */ +add_task( + async function test_nodes_exiting_proximity_before_translation_are_cancelled_in_lazy_mode() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton(); + + await FullPageTranslationsTestUtils.waitForAnyRequestToInitialize( + runInPage + ); + + await scrollToBottomOfPage(runInPage); + + await FullPageTranslationsTestUtils.assertPageH1ContentIsNotTranslated({ + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageH1TitleIsNotTranslated({ + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsNotTranslated( + { + runInPage, + } + ); + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + } + ); + + info("Resolving downloads after scrolling to the bottom of the page."); + await resolveDownloads(1); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + await FullPageTranslationsTestUtils.assertPageH1ContentIsNotTranslated({ + runInPage, + message: "The h1 left viewport proximity before its requests completed.", + }); + await FullPageTranslationsTestUtils.assertPageH1TitleIsNotTranslated({ + runInPage, + message: "The h1 left viewport proximity before its requests completed.", + }); + + await scrollToTopOfPage(runInPage); + + await FullPageTranslationsTestUtils.assertPageH1ContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_content_eager.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_content_eager.js new file mode 100644 index 0000000000..25ba633104 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_content_eager.js @@ -0,0 +1,247 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that nodes with mutated content are picked up and translated + * regardless of their proximity to the viewport in content-eager translations mode, + * but attributes that are mutated will not be translated until the elements they + * belong to enter proximity with the viewport. + */ +add_task( + async function test_mutated_nodes_are_translated_in_content_eager_mode() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + contentEagerMode: true, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + info( + "Ensuring intersecting attributes are translated and non-intersecting attributes are not translated." + ); + await runInPage(async TranslationsTest => { + const { getH1Title, getFinalParagraphTitle } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The

title attribute is translated.", + getH1Title, + "ESTE ES EL TÍTULO DEL ENCABEZADO DE PÁGINA [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The final paragraph title attribute is not translated.", + getFinalParagraphTitle, + "Este es el título del último párrafo" + ); + }); + + info("Mutating the H1 text content and title attribute."); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + const h1 = getH1(); + + h1.innerText = "Este contenido de texto de h1 se modificó."; + h1.setAttribute("title", "Este atributo de título de h1 se modificó."); + h1.setAttribute( + "aria-label", + "Este atributo de etiqueta aria de h1 se añadió." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info("Ensuring all H1 mutations are translated."); + await runInPage(async TranslationsTest => { + const { getH1, getH1Title, getH1AriaLabel } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The mutated h1 text content is translated.", + getH1, + "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated h1 title attribute is translated.", + getH1Title, + "ESTE ATRIBUTO DE TÍTULO DE H1 SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated h1 aria-label attribute is translated.", + getH1AriaLabel, + "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" + ); + }); + + info("Mutating the final paragraph text content and attributes."); + await runInPage(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + const p = getFinalParagraph(); + + p.innerText = "Este contenido de texto de último párrafo se modificó."; + p.setAttribute( + "title", + "Este atributo de título de último párrafo se modificó." + ); + p.setAttribute( + "aria-label", + "Este atributo de etiqueta aria de último párrafo se añadió." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info( + "Ensuring that only the final paragraph's content mutations are translated." + ); + await runInPage(async TranslationsTest => { + const { + getFinalParagraph, + getFinalParagraphTitle, + getFinalParagraphAriaLabel, + } = TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph text content is translated.", + getFinalParagraph, + "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph title attribute is not translated.", + getFinalParagraphTitle, + "Este atributo de título de último párrafo se modificó." + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph aria-label attribute is not translated.", + getFinalParagraphAriaLabel, + "Este atributo de etiqueta aria de último párrafo se añadió." + ); + }); + + await scrollToBottomOfPage(runInPage); + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + await scrollToBottomOfPage(runInPage); + + info("Ensuring all final paragraph mutations are translated."); + await runInPage(async TranslationsTest => { + const { + getFinalParagraph, + getFinalParagraphTitle, + getFinalParagraphAriaLabel, + } = TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph text content remains translated.", + getFinalParagraph, + "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph title attribute is translated.", + getFinalParagraphTitle, + "ESTE ATRIBUTO DE TÍTULO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph aria-label attribute is translated.", + getFinalParagraphAriaLabel, + "ESTE ATRIBUTO DE ETIQUETA ARIA DE ÚLTIMO PÁRRAFO SE AÑADIÓ. [es to en]" + ); + }); + + info("Mutating the H1 content and title again."); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + const h1 = getH1(); + + h1.innerText = "Este contenido de texto de h1 se modificó otra vez."; + h1.setAttribute( + "title", + "Este atributo de título de h1 se modificó otra vez." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info( + "Ensuring mutated H1 content is translated, but the mutated attribute is not." + ); + await runInPage(async TranslationsTest => { + const { getH1, getH1Title, getH1AriaLabel } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The re-mutated h1 text content is translated.", + getH1, + "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ OTRA VEZ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The re-mutated h1 title attribute is not translated.", + getH1Title, + "Este atributo de título de h1 se modificó otra vez." + ); + + await TranslationsTest.assertTranslationResult( + "The h1 aria-label attribute remains previously translated.", + getH1AriaLabel, + "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" + ); + }); + + await scrollToTopOfPage(runInPage); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info("Ensuring re-mutated H1 title attribute is translated."); + await runInPage(async TranslationsTest => { + const { getH1Title } = TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The re-mutated h1 title attribute is translated.", + getH1Title, + "ESTE ATRIBUTO DE TÍTULO DE H1 SE MODIFICÓ OTRA VEZ. [es to en]" + ); + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_lazy.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_lazy.js new file mode 100644 index 0000000000..9e3c660100 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_lazy.js @@ -0,0 +1,235 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that both content and attribute mutations are not picked up + * and translated until the elements that they belong to enter proximity with the viewport. + */ +add_task( + async function test_mutated_nodes_entering_proximity_are_translated_in_lazy_mode() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + info("Mutating the H1 text content and title attribute."); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + const h1 = getH1(); + + h1.innerText = "Este contenido de texto de h1 se modificó."; + h1.setAttribute("title", "Este atributo de título de h1 se modificó."); + h1.setAttribute( + "aria-label", + "Este atributo de etiqueta aria de h1 se añadió." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info("Ensuring all H1 mutations are translated."); + await runInPage(async TranslationsTest => { + const { getH1, getH1Title, getH1AriaLabel } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The mutated h1 text content is translated.", + getH1, + "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated h1 title attribute is translated.", + getH1Title, + "ESTE ATRIBUTO DE TÍTULO DE H1 SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated h1 aria-label attribute is translated.", + getH1AriaLabel, + "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" + ); + }); + + info("Mutating the final paragraph text content and attributes."); + await runInPage(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + const p = getFinalParagraph(); + + p.innerText = "Este contenido de texto de último párrafo se modificó."; + p.setAttribute( + "title", + "Este atributo de título de último párrafo se modificó." + ); + p.setAttribute( + "aria-label", + "Este atributo de etiqueta aria de último párrafo se añadió." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info("Ensuring final paragraph mutations are NOT translated yet."); + await runInPage(async TranslationsTest => { + const { + getFinalParagraph, + getFinalParagraphTitle, + getFinalParagraphAriaLabel, + } = TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph text content is not translated.", + getFinalParagraph, + "Este contenido de texto de último párrafo se modificó." + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph title attribute is not translated.", + getFinalParagraphTitle, + "Este atributo de título de último párrafo se modificó." + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph aria-label attribute is not translated.", + getFinalParagraphAriaLabel, + "Este atributo de etiqueta aria de último párrafo se añadió." + ); + }); + + await scrollToBottomOfPage(runInPage); + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + await scrollToBottomOfPage(runInPage); + + info("Ensuring all final paragraph mutations are translated."); + await runInPage(async TranslationsTest => { + const { + getFinalParagraph, + getFinalParagraphTitle, + getFinalParagraphAriaLabel, + } = TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph text content is translated.", + getFinalParagraph, + "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph title attribute is translated.", + getFinalParagraphTitle, + "ESTE ATRIBUTO DE TÍTULO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The mutated final paragraph aria-label attribute is translated.", + getFinalParagraphAriaLabel, + "ESTE ATRIBUTO DE ETIQUETA ARIA DE ÚLTIMO PÁRRAFO SE AÑADIÓ. [es to en]" + ); + }); + + info("Mutating the H1 content and title again."); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + const h1 = getH1(); + + h1.innerText = "Este contenido de texto de h1 se modificó otra vez."; + h1.setAttribute( + "title", + "Este atributo de título de h1 se modificó otra vez." + ); + }); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info("Ensuring re-mutated H1 content is NOT translated yet."); + await runInPage(async TranslationsTest => { + const { getH1, getH1Title, getH1AriaLabel } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The re-mutated h1 text content is not translated.", + getH1, + "Este contenido de texto de h1 se modificó otra vez." + ); + + await TranslationsTest.assertTranslationResult( + "The re-mutated h1 title attribute is not translated.", + getH1Title, + "Este atributo de título de h1 se modificó otra vez." + ); + + await TranslationsTest.assertTranslationResult( + "The h1 aria-label attribute remains previously translated.", + getH1AriaLabel, + "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" + ); + }); + + await scrollToTopOfPage(runInPage); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info("Ensuring re-mutated H1 content is translated."); + await runInPage(async TranslationsTest => { + const { getH1, getH1Title, getH1AriaLabel } = + TranslationsTest.getSelectors(); + + await TranslationsTest.assertTranslationResult( + "The re-mutated h1 text content is translated.", + getH1, + "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ OTRA VEZ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The re-mutated h1 title attribute is translated.", + getH1Title, + "ESTE ATRIBUTO DE TÍTULO DE H1 SE MODIFICÓ OTRA VEZ. [es to en]" + ); + + await TranslationsTest.assertTranslationResult( + "The h1 aria-label attribute remains previously translated.", + getH1AriaLabel, + "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" + ); + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_language_id_behavior.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_language_id_behavior.js new file mode 100644 index 0000000000..cdd059e923 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_language_id_behavior.js @@ -0,0 +1,298 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Run through the test cases for how auto translation and offering translations works + * with a variety of conditions. The + * + * Keep this table up to date with TranslationParent's maybeOfferTranslation and + * shouldAutoTranslate methods. When an entry is blank "-" it has no affect on the + * outcome. + * + * ┌────┬──────────┬───────────┬───────────────────┬───────────────────┬─────────────────────────────┐ + * │ # │ Has HTML │ Detection │ Detection Content │ Always Translate │ Outcome │ + * │ │ Tag │ Agrees │ > 200 code units │ List Contains Tag │ │ + * ├────┼──────────┼───────────┼───────────────────┼───────────────────┼─────────────────────────────┤ + * │ 1 │ TRUE │ TRUE │ - │ TRUE │ Auto Translate Matching Tag │ + * │ 2 │ TRUE │ TRUE │ - │ FALSE │ Offer Matching Tag │ + * │ 3 │ TRUE │ TRUE │ - │ TRUE │ Auto Translate Matching Tag │ + * │ 4 │ TRUE │ TRUE │ - │ FALSE │ Offer Matching Tag │ + * │ 5 │ TRUE │ FALSE │ - │ TRUE │ Show Button Only │ + * │ 6 │ TRUE │ FALSE │ - │ FALSE │ Show Button Only │ + * │ 7 │ TRUE │ FALSE │ - │ TRUE │ Show Button Only │ + * │ 8 │ TRUE │ FALSE │ - │ FALSE │ Show Button Only │ + * │ 9 │ FALSE │ - │ TRUE │ TRUE │ Auto Translate Detected Tag │ + * │ 10 │ FALSE │ - │ TRUE │ FALSE │ Offer Detected Tag │ + * │ 11 │ FALSE │ - │ FALSE │ TRUE │ Show Button Only │ + * │ 12 │ FALSE │ - │ FALSE │ FALSE │ Show Button Only │ + * └────┴──────────┴───────────┴───────────────────┴───────────────────┴─────────────────────────────┘ + */ + +/** + * Request 2x longer timeout for this test. + * There are lot of test cases in this file, but it doesn't make sense to split them up. + */ +requestLongerTimeout(2); + +/** + * Definitions for the test cases. + * + * @typedef {object} Case + * @property {string} page - The page to load. + * @property {string} message - A message for the primary assertion. + * @property {string} [alwaysTranslateLanguages] - Set the pref: browser.translations.alwaysTranslateLanguages + * @property {string} [neverTranslateLanguages] - Set the pref: browser.translations.alwaysTranslateLanguages + * + * Outcomes, use only one: + * @property {string} [translatePage] - The page is expected to be translated. + * @property {string} [offerTranslation] - The page offers a translation in this language. + * @property {boolean} [buttonShown] - The button was shown to offer a translation. + */ + +/** + * @type {Case[]} + */ +const cases = [ + // HTML tag and (confident) detection agree. + { + // Case 1 - Spanish is set to auto translate. + page: SPANISH_PAGE_URL, + alwaysTranslateLanguages: "es", + translatePage: "es", + message: + "Auto-translate since the declared language and identified language agree", + }, + { + // Case 2 - Nothing is set to auto translate. + page: SPANISH_PAGE_URL, + offerTranslation: "es", + message: + "The declared language and identified language agree, offer a translation", + }, + // HTML tag and (low-confidence) detection agree. + { + // Case 3 - Spanish is set to auto translate. + page: SPANISH_PAGE_SHORT_URL, + alwaysTranslateLanguages: "es", + translatePage: "es", + message: + "The declared language and identified language agree, offer a translation even " + + "though the page has a short amount of content.", + }, + { + // Case 4 - Nothing is set to auto translate. + page: SPANISH_PAGE_SHORT_URL, + offerTranslation: "es", + message: + "The declared language and identified language agree, offer a translation", + }, + // HTML tag and (confident) detection disagree. + { + // Case 5 - Spanish is set to auto translate. + page: SPANISH_PAGE_MISMATCH_URL, + alwaysTranslateLanguages: "es", + buttonShown: true, + message: + "The declared and (confident) detected language disagree. Only show the button, do not auto-translate.", + }, + { + // Case 6 - Nothing is set to auto translate. + page: SPANISH_PAGE_MISMATCH_URL, + buttonShown: true, + message: + "The declared and (confident) detected language disagree. Only show the button, do not offer.", + }, + // HTML tag and (low-confidence) detection disagree. + { + // Case 7 - Spanish is set to auto translate. + page: SPANISH_PAGE_MISMATCH_SHORT_URL, + alwaysTranslateLanguages: "es", + buttonShown: true, + message: + "The declared and (low-confidence) detected language disagree. Only show the button, do not auto-translate.", + }, + { + // Case 8 - Nothing is set to auto translate. + page: SPANISH_PAGE_MISMATCH_SHORT_URL, + buttonShown: true, + message: + "The declared and (low-confidence) detected language disagree. Only show the button, do not offer.", + }, + // Undeclared language and (high-confidence) detection. + { + // Case 9 - Spanish is set to auto translate. + page: SPANISH_PAGE_UNDECLARED_URL, + alwaysTranslateLanguages: "es,fr", + translatePage: "es", + message: + "There is no declared language, but there is high confidence in the detected language, so go ahead and auto-translate.", + }, + { + // Case 10 - Nothing is set to auto translate. + page: SPANISH_PAGE_UNDECLARED_URL, + offerTranslation: "es", + message: + "There is no declared language, but there is high confidence in the detected language, so go ahead and offer.", + }, + // Undeclared language and (low-confidence) detection. + { + // Case 11 - Spanish is set to auto translate. + page: SPANISH_PAGE_MISMATCH_SHORT_URL, + alwaysTranslateLanguages: "es", + buttonShown: true, + message: + "A language was detected, but it was so low confidence only show the button.", + }, + { + // Case 12 - Nothing is set to auto translate. + page: SPANISH_PAGE_UNDECLARED_SHORT_URL, + buttonShown: true, + message: + "A language was detected, but it was so low confidence only show the button.", + }, +]; + +add_task(async function test_language_identification_behavior() { + for (const [caseNo, testCase] of Object.entries(cases)) { + const { + page, + message, + alwaysTranslateLanguages, + neverTranslateLanguages, + translatePage, + offerTranslation, + buttonShown, + } = testCase; + info(`Testing Case ${Number(caseNo) + 1}`); + TranslationsParent.testAutomaticPopup = true; + + // Handle this manually instead of using FullPageTranslationsTestUtils.waitForPanelPopupEvent + // as we may not actually get a popupshown event and this leads to an error on test shutdown: + // "popupshown listener on #full-page-translations-panel not removed before the end of test" + let wasPopupShown = false; + window.FullPageTranslationsPanel.elements; // De-lazify the panel. + const { promise: popupShown, resolve } = Promise.withResolvers(); + const panel = window.document.getElementById( + "full-page-translations-panel" + ); + function handlePopupShown() { + wasPopupShown = true; + panel.removeEventListener("popupshown", handlePopupShown); + resolve(); + } + panel.addEventListener("popupshown", handlePopupShown); + + const { cleanup, runInPage, win } = await loadTestPage({ + page, + languagePairs: LANGUAGE_PAIRS, + autoDownloadFromRemoteSettings: true, + contentEagerMode: true, + prefs: [ + [ + "browser.translations.alwaysTranslateLanguages", + alwaysTranslateLanguages, + ], + [ + "browser.translations.neverTranslateLanguages", + neverTranslateLanguages, + ], + ], + }); + + let outcomes = 0; + if (buttonShown) { + outcomes++; + } + if (offerTranslation) { + outcomes++; + } + if (translatePage) { + outcomes++; + } + if (outcomes !== 1) { + throw new Error("Expected only 1 main outcome."); + } + + if (buttonShown || offerTranslation || translatePage) { + await FullPageTranslationsTestUtils.assertTranslationsButton( + { + button: true, + circleArrows: false, + locale: translatePage, + icon: true, + }, + offerTranslation ? "The translation button is visible" : message + ); + } else { + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The translations button is not visible." + ); + } + + if (translatePage) { + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: translatePage, + toLanguage: "en", + runInPage, + message, + }); + await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: + "The page's H1's title should be translated because it intersects with the viewport.", + }); + + if ( + page === SPANISH_PAGE_SHORT_URL || + page === SPANISH_PAGE_MISMATCH_SHORT_URL + ) { + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: + "The page's final paragraph's title should be translated because it intersects with the viewport.", + } + ); + } else { + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + message: + "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", + } + ); + } + } else { + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInPage, + message + ); + } + + if (offerTranslation) { + await popupShown; + ok(wasPopupShown, message); + FullPageTranslationsTestUtils.assertSelectedFromLanguage({ + win, + langTag: offerTranslation, + }); + FullPageTranslationsTestUtils.assertSelectedToLanguage({ + win, + langTag: "en", + }); + } else { + is(wasPopupShown, false, "A translation was not offered"); + } + + TranslationsParent.testAutomaticPopup = false; + panel.removeEventListener("popupshown", handlePopupShown); + await cleanup(); + } +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_move_tab_to_new_window.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_move_tab_to_new_window.js new file mode 100644 index 0000000000..cd256795be --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_move_tab_to_new_window.js @@ -0,0 +1,68 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests a specific situation described in Bug 1893776 + * where the Translations panels were not initializing correctly after + * dragging a tab to become its own new window after opening the panel + * in the previous window. + */ +add_task(async function test_browser_translations_full_page_multiple_windows() { + const window1 = window; + const testPage = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible.", + window1 + ); + + info("Opening FullPageTranslationsPanel in window1"); + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + info("Moving the tab to a new window of its own"); + const window2 = await window1.gBrowser.replaceTabWithWindow(testPage.tab); + const swapDocShellPromise = BrowserTestUtils.waitForEvent( + testPage.tab.linkedBrowser, + "SwapDocShells" + ); + await swapDocShellPromise; + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible.", + window2 + ); + + info("Opening FullPageTranslationsPanel in window2"); + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + win: window2, + }); + + info("Translating the same page in window2"); + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window2, + downloadHandler: testPage.resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + "es", + "en", + window2 + ); + + await testPage.cleanup(); + await BrowserTestUtils.closeWindow(window2); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_moz_extension.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_moz_extension.js new file mode 100644 index 0000000000..42937f2703 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_moz_extension.js @@ -0,0 +1,79 @@ +/* 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_moz_extension() { + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + web_accessible_resources: ["test_page.html"], + }, + files: { + "test_page.html": ` + + + + + +

Don Quijote de La Mancha

+

— Pues, aunque mováis más brazos que los del gigante Briareo, me lo habéis de pagar.

+ + `, + }, + }); + + await extension.startup(); + + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: `moz-extension://${extension.uuid}/test_page.html`, + languagePairs: LANGUAGE_PAIRS, + }); + + const { button } = + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + is(button.getAttribute("data-l10n-id"), "urlbar-translations-button-intro"); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: + "The page's H1's title should be translated because it intersects with the viewport.", + }); + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: + "The page's final paragraph's title should be translated because it intersects with the viewport.", + } + ); + + await cleanup(); + await extension.unload(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_multiple_windows.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_multiple_windows.js new file mode 100644 index 0000000000..c0693748a5 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_multiple_windows.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Test that the full page translation panel works when multiple windows are used. + */ +add_task(async function test_browser_translations_full_page_multiple_windows() { + const window1 = window; + const testPage1 = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + const window2 = await BrowserTestUtils.openNewBrowserWindow(); + + const testPage2 = await loadTestPage({ + win: window2, + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + // Focus back to the original window first. This ensures coverage for invalid caching + // logic involving multiple windows. + await focusWindow(window1); + + info("Testing window 1"); + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: testPage1.resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage: testPage1.runInPage, + message: "Window 1 gets translated", + win: window1, + }); + + await focusWindow(window2); + + info("Testing window 2"); + await FullPageTranslationsTestUtils.openPanel({ + win: window2, + expectedFromLanguage: "es", + expectedToLanguage: "en", + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ win: window2 }); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage: testPage2.runInPage, + message: "Window 2 gets translated", + win: window2, + }); + + await testPage2.cleanup(); + await BrowserTestUtils.closeWindow(window2); + await testPage1.cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_a11y_focus.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_a11y_focus.js new file mode 100644 index 0000000000..511e91572e --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_a11y_focus.js @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the a11y focus behavior. + */ +add_task(async function test_translations_panel_a11y_focus() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + openWithKeyboard: true, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + is( + document.activeElement.getAttribute("data-l10n-id"), + "translations-panel-settings-button", + "The settings button is focused." + ); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_bad_data.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_bad_data.js new file mode 100644 index 0000000000..0e698a083e --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_bad_data.js @@ -0,0 +1,41 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that having an "always translate" set to your app locale doesn't break things. + */ +add_task(async function test_always_translate_with_bad_data() { + const { cleanup, runInPage } = await loadTestPage({ + page: ENGLISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.alwaysTranslateLanguages", "en,fr"]], + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "en", + expectedToLanguage: "", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + openFromAppMenu: true, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("en", { + checked: false, + disabled: true, + }); + await closeAllOpenPanelsAndMenus(); + + info("Checking that the page is not translated"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is not translated and in the original English.", + getH1, + '"The Wonderful Wizard of Oz" by L. Frank Baum' + ); + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_basic.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_basic.js new file mode 100644 index 0000000000..fc011e4ad8 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_basic.js @@ -0,0 +1,81 @@ +/* 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 not translated 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: "The page should be automatically translated.", + }); + + await navigate("Navigate to a different Spanish page", { + url: SPANISH_PAGE_URL_DOT_ORG, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: "The page should be automatically translated.", + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage(); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "Only the button appears" + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_manual.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_manual.js new file mode 100644 index 0000000000..033de434b2 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_manual.js @@ -0,0 +1,88 @@ +/* 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 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage(); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage(); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "Only the button appears" + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_restore.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_restore.js new file mode 100644 index 0000000000..9cc9ce099b --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_restore.js @@ -0,0 +1,109 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: "The page should be automatically translated.", + } + ); + + await navigate("Navigate to a different Spanish page", { + url: SPANISH_PAGE_URL_DOT_ORG, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: "The page should be automatically translated.", + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.clickRestoreButton(); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is reverted to have an icon." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage(); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button shows only the icon." + ); + + await navigate("Reload the page", { url: SPANISH_PAGE_URL_DOT_ORG }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button shows only the icon." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_language.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_language.js new file mode 100644 index 0000000000..fd34afbe07 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_language.js @@ -0,0 +1,42 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the effect of unchecking the never-translate-language menuitem, removing + * the language from the never-translate languages list. + * The translations button should reappear. + */ +add_task(async function test_uncheck_never_translate_language_shows_button() { + const { cleanup, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.neverTranslateLanguages", "es"]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is available" + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + openFromAppMenu: true, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_site.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_site.js new file mode 100644 index 0000000000..9ab1f8ee8f --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_site.js @@ -0,0 +1,151 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the effect of unchecking the never-translate-site menuitem, + * regranting translations permissions to this page. + * The translations button should reappear. + */ +add_task(async function test_uncheck_never_translate_site_shows_button() { + const { cleanup, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + openFromAppMenu: true, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + + await cleanup(); +}); + +/** + * Tests the effect of unchecking the never-translate-site menuitem while + * the current language is in the always-translate languages list, regranting + * translations permissions to this page. + * The page should automatically translate. + */ +add_task( + async function test_uncheck_never_translate_site_with_always_translate_language() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: BLANK_PAGE, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.alwaysTranslateLanguages", "es"]], + }); + + await navigate("Navigate to a Spanish page", { + url: SPANISH_PAGE_URL, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + openFromAppMenu: true, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_error_view.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_error_view.js new file mode 100644 index 0000000000..0e76cda526 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_error_view.js @@ -0,0 +1,88 @@ +/* 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" +); + +/** + * This tests a specific defect where the error view was not showing properly + * when navigating to an auto-translated page after visiting a page in an unsupported + * language and viewing the panel. + * + * This test case tests the case where the auto translate fails and the panel + * automatically opens the panel to show the error view. + * + * See https://bugzilla.mozilla.org/show_bug.cgi?id=1845611 for more information. + */ +add_task( + async function test_revisit_view_updates_with_auto_translate_failure() { + const { cleanup, resolveDownloads, rejectDownloads, runInPage } = + await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: [ + // Do not include French. + { fromLang: "en", toLang: "es" }, + { fromLang: "es", toLang: "en" }, + ], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await navigate("Navigate to a page in an unsupported language", { + url: FRENCH_PAGE_URL, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The translations button should be unavailable." + ); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + onOpenPanel: + FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + info("Destroy the engine process so that an error will happen."); + await EngineProcess.destroyTranslationsEngine(); + + await navigate("Navigate back to a Spanish page.", { + url: SPANISH_PAGE_URL_DOT_ORG, + downloadHandler: rejectDownloads, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewError, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_revisit_view.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_revisit_view.js new file mode 100644 index 0000000000..63d58d4864 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_revisit_view.js @@ -0,0 +1,92 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This tests a specific defect where the revisit view was not showing properly + * when navigating to an auto-translated page after visiting a page in an unsupported + * language and viewing the panel. + * + * This test case tests the case where the auto translate succeeds and the user + * manually opens the panel to show the revisit view. + * + * See https://bugzilla.mozilla.org/show_bug.cgi?id=1845611 for more information. + */ +add_task( + async function test_revisit_view_updates_with_auto_translate_success() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: [ + // Do not include French. + { fromLang: "en", toLang: "es" }, + { fromLang: "es", toLang: "en" }, + ], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await navigate("Navigate to a page in an unsupported language", { + url: FRENCH_PAGE_URL, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The translations button should be unavailable." + ); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + onOpenPanel: + FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await navigate("Navigate back to the Spanish page.", { + url: SPANISH_PAGE_URL_DOT_ORG, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + openFromAppMenu: true, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_basics.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_basics.js new file mode 100644 index 0000000000..c348a4c8a8 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_basics.js @@ -0,0 +1,69 @@ +/* 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 FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + is(button.getAttribute("data-l10n-id"), "urlbar-translations-button-intro"); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton(); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewLoading, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await resolveDownloads(1); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.clickRestoreButton(); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is reverted to have an icon." + ); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_button.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_button.js new file mode 100644 index 0000000000..209cfc18a6 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_button.js @@ -0,0 +1,77 @@ +/* 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() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button should be visible since the page can be translated from Spanish." + ); + + await navigate("Navigate to an English page.", { url: ENGLISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The button should be invisible since the page is in English." + ); + + await navigate("Navigate back to a Spanish page.", { url: SPANISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.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() { + const { cleanup, tab: spanishTab } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.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 FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The button should be invisible since the tab is in English." + ); + + await switchTab(spanishTab, "spanish tab"); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button should be visible again since the page is in Spanish." + ); + + await switchTab(englishTab, "english tab"); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "Don't show for english pages" + ); + + await removeTab(); + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_cancel.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_cancel.js new file mode 100644 index 0000000000..5267abb17b --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_cancel.js @@ -0,0 +1,29 @@ +/* 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_change_app_locale.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_change_app_locale.js new file mode 100644 index 0000000000..ad6936991a --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_change_app_locale.js @@ -0,0 +1,74 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the language display names within the FullPageTranslationsPanel + * dropdown menu lists update immediately upon the next panel open when the user's application + * locale changes. + */ +add_task( + async function test_full_page_translations_panel_change_application_locale() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + const { fromMenuList, toMenuList } = FullPageTranslationsPanel.elements; + + is( + fromMenuList.label, + "Spanish", + "The FullPageTranslationsPanel from-menu-list languages should be localized to English display names." + ); + + is( + toMenuList.label, + "English", + "The FullPageTranslationsPanel to-menu-list languages should be localized to English display names." + ); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + info("Changing the application locale from English to Spanish"); + const cleanupLocales = await mockLocales({ + appLocales: ["es"], + webLanguages: ["en"], + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + is( + fromMenuList.label, + "español", + "The FullPageTranslationsPanel from-menu-list languages should be localized to Spanish display names." + ); + + is( + toMenuList.label, + "inglés", + "The FullPageTranslationsPanel to-menu-list languages should be localized to Spanish display names." + ); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await cleanupLocales(); + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_active.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_active.js new file mode 100644 index 0000000000..1434ab33d0 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_active.js @@ -0,0 +1,159 @@ +"use strict"; + +/** + * Tests the effect of checking the never-translate-language menuitem on a page where + * translations are active (always-translate-language is enabled). + * Checking the box on the page automatically closes/hides the translations panel. + */ +add_task( + async function test_panel_closes_on_toggle_never_translate_language_with_translations_active() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is available" + ); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: "The page should be automatically translated.", + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + async () => { + await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); + } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + await cleanup(); + } +); + +/** + * Tests the effect of checking the never-translate-language menuitem on + * a page where translations are active through always-translate-language + * and inactive on a site through never-translate-site. + * Checking the box on the page automatically closes/hides the translations panel. + */ +add_task( + async function test_panel_closes_on_toggle_never_translate_language_with_always_translate_language_and_never_translate_site_active() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is available" + ); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: "The page should be automatically translated.", + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + async () => { + await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); + } + ); + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_inactive.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_inactive.js new file mode 100644 index 0000000000..be68494809 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_inactive.js @@ -0,0 +1,99 @@ +"use strict"; + +/** + * Tests the effect of checking the never-translate-language menuitem on a page where + * translations and never translate site are inactive. + * Checking the box on the page automatically closes/hides the translations panel. + */ +add_task(async function test_panel_closes_on_toggle_never_translate_language() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is available" + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + openFromAppMenu: true, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + async () => { + await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); + } + ); + await cleanup(); +}); + +/** + * Tests the effect of checking the never-translate-language menuitem on a page where + * translations are inactive (never-translate-site is enabled). + * Checking the box on the page automatically closes/hides the translations panel. + */ +add_task( + async function test_panel_closes_on_toggle_never_translate_language_with_never_translate_site_enabled() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is available" + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + openFromAppMenu: true, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + openFromAppMenu: true, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + async () => { + await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); + } + ); + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_site.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_site.js new file mode 100644 index 0000000000..75c73f2451 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_site.js @@ -0,0 +1,170 @@ +"use strict"; + +/** + * Tests the effect of checking the never-translate-site menuitem on a page where + * always-translate-language and never-translate-language are inactive. + * Checking the box on the page automatically closes/hides the translations panel. + */ +add_task(async function test_panel_closes_on_toggle_never_translate_site() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is available" + ); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + async () => { + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + } + ); + + await cleanup(); +}); + +/** + * Tests the effect of checking the never-translate-site menuitem on a page where + * translations are active (always-translate-language is enabled). + * Checking the box on the page automatically restores the page and closes/hides the translations panel. + */ +add_task( + async function test_panel_closes_on_toggle_never_translate_site_with_translations_active() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is available" + ); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: "The page should be automatically translated.", + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + async () => { + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + } + ); + + await cleanup(); + } +); + +/** + * Tests the effect of checking the never-translate-site menuitem on a page where + * translations are inactive (never-translate-language is active). + * Checking the box on the page automatically closes/hides the translations panel. + */ +add_task( + async function test_panel_closes_on_toggle_never_translate_site_with_translations_inactive() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is available" + ); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + async () => { + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy.js new file mode 100644 index 0000000000..43f1cee107 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy.js @@ -0,0 +1,64 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Manually destroy the engine, and test that the page is still translated afterwards. + */ +add_task(async function test_translations_engine_destroy() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + info("Destroy the engine process"); + await EngineProcess.destroyTranslationsEngine(); + + info("Mutate the page's content to re-trigger a translation."); + const { promise: animationPromise, resolve } = Promise.withResolvers(); + requestAnimationFrame(() => { + requestAnimationFrame(resolve); + }); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + getH1().innerText = "New text for the H1"; + }); + + await animationPromise; + + info("The engine downloads should be requested again."); + await resolveDownloads(1); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The mutated content should be translated.", + getH1, + "NEW TEXT FOR THE H1 [es to en]" + ); + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy_pending.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy_pending.js new file mode 100644 index 0000000000..a4aed29131 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy_pending.js @@ -0,0 +1,77 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Manually destroy the engine while a page is in the background, and test that the page + * is still translated after switching back to it. + */ +add_task(async function test_translations_engine_destroy_pending() { + const { + cleanup, + resolveDownloads, + runInPage, + tab: spanishTab, + } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + const { removeTab: removeEnglishTab } = await addTab( + ENGLISH_PAGE_URL, + "Creating a new tab for a page in English." + ); + + info("Destroy the engine process"); + await EngineProcess.destroyTranslationsEngine(); + + info("Mutate the page's content to re-trigger a translation."); + const { promise: animationPromise, resolve } = Promise.withResolvers(); + requestAnimationFrame(() => { + requestAnimationFrame(resolve); + }); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + getH1().innerText = "New text for the H1"; + }); + + await animationPromise; + await switchTab(spanishTab, "spanish tab"); + + info("The engine downloads should be requested again."); + await resolveDownloads(1); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The mutated content should be translated.", + getH1, + "NEW TEXT FOR THE H1 [es to en]" + ); + }); + + await removeEnglishTab(); + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_unsupported.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_unsupported.js new file mode 100644 index 0000000000..4eec51f65e --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_unsupported.js @@ -0,0 +1,59 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that the translations button does not appear when the translations + * engine is not supported. + */ +add_task(async function test_translations_button_hidden_when_cpu_unsupported() { + const { cleanup, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.simulateUnsupportedEngine", true]], + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The button is not available." + ); + + await cleanup(); +}); + +/** + * Tests that the translate-page menuitem is not available in the app menu + * when the translations engine is not supported. + */ +add_task( + async function test_translate_page_app_menu_item_hidden_when_cpu_unsupported() { + const { cleanup, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.simulateUnsupportedEngine", true]], + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + const appMenuButton = getById("PanelUI-menu-button"); + + click(appMenuButton, "Opening the app menu"); + await BrowserTestUtils.waitForEvent(window.PanelUI.mainView, "ViewShown"); + + const translateSiteButton = document.getElementById( + "appMenu-translate-button" + ); + is( + translateSiteButton.hidden, + true, + "The app-menu translate button should be hidden because when the engine is not supported." + ); + + click(appMenuButton, "Closing the app menu"); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun.js new file mode 100644 index 0000000000..1a33188932 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun.js @@ -0,0 +1,55 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that the first run message is displayed prior to performing a + * translation, but is no longer displayed after a translation occurs. + */ +add_task(async function test_translations_panel_firstrun() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await navigate("Load a different page on the same site", { + url: SPANISH_PAGE_URL_2, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await FullPageTranslationsTestUtils.openPanel({ + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.clickRestoreButton(); + + await FullPageTranslationsTestUtils.openPanel({ + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun_revisit.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun_revisit.js new file mode 100644 index 0000000000..aca7eaa08b --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun_revisit.js @@ -0,0 +1,64 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that the first-show intro message message is displayed + * when viewing the panel subsequent times on the same URL, + * when navigating to new URL, and when returning to the first URL + * after navigating away. + */ +add_task(async function test_translations_panel_firstrun() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await navigate("Navigate to a different website", { + url: SPANISH_PAGE_URL_DOT_ORG, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await navigate("Navigate back to the first website", { + url: SPANISH_PAGE_URL, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_flip_lexical_shortlist.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_flip_lexical_shortlist.js new file mode 100644 index 0000000000..234ceb0e8f --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_flip_lexical_shortlist.js @@ -0,0 +1,146 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests translations in the FullPageTranslationsPanel with the + * useLexicalShortlist pref initially set to false. It then toggles it to true, + * and then back to false, ensuring that the correct models are downloaded, and + * that the translations succeed with each flip of the pref. + */ +add_task( + async function test_full_page_translations_panel_lexical_shortlist_starting_false() { + const { tab, cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.useLexicalShortlist", false]], + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await waitForTranslationModelRecordsChanged(() => { + Services.prefs.setBoolPref( + "browser.translations.useLexicalShortlist", + true + ); + }); + + await openFindBar(tab); + + info( + "Awaiting new downloads since the active TranslationsEngine will be rebuilt." + ); + await resolveDownloads(1); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: + "The page's H1's title should be translated because it intersects with the viewport.", + }); + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + message: + "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", + } + ); + + await cleanup(); + } +); + +/** + * This test case tests translations in the FullPageTranslationsPanel with the + * useLexicalShortlist pref initially set to true. It then toggles it to false, + * and then back to true, ensuring that the correct models are downloaded, and + * that the translations succeed with each flip of the pref. + */ +add_task( + async function test_full_page_translations_panel_lexical_shortlist_starting_true() { + const { tab, cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.useLexicalShortlist", true]], + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await waitForTranslationModelRecordsChanged(() => { + Services.prefs.setBoolPref( + "browser.translations.useLexicalShortlist", + false + ); + }); + + await openFindBar(tab); + + info( + "Awaiting new downloads since the active TranslationsEngine will be rebuilt." + ); + await resolveDownloads(1); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: + "The page's H1's title should be translated because it intersects with the viewport.", + }); + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + message: + "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_fuzzing.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_fuzzing.js new file mode 100644 index 0000000000..7e73eef47d --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_fuzzing.js @@ -0,0 +1,243 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Manually destroy the engine while a page is in the background, and test that the page + * is still translated after switching back to it. + */ +add_task(async function test_translations_panel_fuzzing() { + const { + cleanup, + runInPage: runInSpanishPage, + tab: spanishTab, + } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + autoDownloadFromRemoteSettings: true, + }); + + /** + * @typedef {object} Tab + */ + + /** @type {Tab?} */ + let englishTab; + /** @type {Function?} */ + let removeEnglishTab; + /** @type {boolean} */ + let isSpanishPageTranslated = false; + /** @type {"spanish" | "english"} */ + let activeTab = "spanish"; + /** @type {boolean} */ + let isEngineMaybeDestroyed = true; + /** @type {boolean} */ + let isTitleMutated = false; + /** @type {boolean} */ + let hasVerifiedMutation = true; + + function reportOperation(name) { + info( + `\n\nOperation: ${name} ` + + JSON.stringify({ + activeTab, + englishTab: !!englishTab, + isSpanishPageTranslated, + isEngineMaybeDestroyed, + isTitleMutated, + }) + ); + } + + /** + * A list of fuzzing operations. They return false when they are a noop given the + * conditions. + * + * @type {object} - Record Promise> + */ + const operations = { + async addEnglishTab() { + if (!englishTab) { + reportOperation("addEnglishTab"); + const { removeTab, tab } = await addTab( + ENGLISH_PAGE_URL, + "Creating a new tab for a page in English." + ); + + englishTab = tab; + removeEnglishTab = removeTab; + activeTab = "english"; + return true; + } + return false; + }, + + async removeEnglishTab() { + if (removeEnglishTab) { + reportOperation("removeEnglishTab"); + await removeEnglishTab(); + + englishTab = null; + removeEnglishTab = null; + activeTab = "spanish"; + return true; + } + return false; + }, + + async translateSpanishPage() { + if (!isSpanishPageTranslated) { + reportOperation("translateSpanishPage"); + if (activeTab === "english") { + await switchTab(spanishTab, "spanish tab"); + } + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + await FullPageTranslationsTestUtils.openPanel({ + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton(); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "Translations button is fully loaded." + ); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage: runInSpanishPage, + } + ); + + isSpanishPageTranslated = true; + isEngineMaybeDestroyed = false; + activeTab = "spanish"; + return true; + } + return false; + }, + + async destroyEngineProcess() { + if ( + !isEngineMaybeDestroyed && + // Don't destroy the engine process until the mutation has been verified. + // There is an artifical race (e.g. only in tests) that happens from a new + // engine being requested, and forcefully destroyed before the it can be + // initialized. + hasVerifiedMutation + ) { + reportOperation("destroyEngineProcess"); + await EngineProcess.destroyTranslationsEngine(); + isEngineMaybeDestroyed = true; + } + return true; + }, + + async mutateSpanishPage() { + if (isSpanishPageTranslated && !isTitleMutated) { + reportOperation("mutateSpanishPage"); + + info("Mutate the page's content to re-trigger a translation."); + await runInSpanishPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + getH1().innerText = "New text for the H1"; + }); + + if (isEngineMaybeDestroyed) { + info("The engine may be recreated now."); + } + + isEngineMaybeDestroyed = false; + isTitleMutated = true; + hasVerifiedMutation = false; + return true; + } + return false; + }, + + async switchToSpanishTab() { + if (activeTab !== "spanish") { + reportOperation("switchToSpanishTab"); + await switchTab(spanishTab, "spanish tab"); + activeTab = "spanish"; + + if (isTitleMutated) { + await runInSpanishPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The mutated content should be translated.", + getH1, + "NEW TEXT FOR THE H1 [es to en]" + ); + }); + hasVerifiedMutation = true; + } + + return true; + } + return false; + }, + + async switchToEnglishTab() { + if (activeTab !== "english" && englishTab) { + reportOperation("switchToEnglishTab"); + await switchTab(englishTab, "english tab"); + activeTab = "english"; + return true; + } + return false; + }, + + async restoreSpanishPage() { + if (activeTab === "spanish" && isSpanishPageTranslated) { + reportOperation("restoreSpanishPage"); + await FullPageTranslationsTestUtils.openPanel({ + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.clickRestoreButton(); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInSpanishPage + ); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is reverted to have an icon." + ); + + isSpanishPageTranslated = false; + isTitleMutated = false; + return true; + } + return false; + }, + }; + + const fuzzSteps = 100; + info(`Starting the fuzzing with ${fuzzSteps} operations.`); + const opsArray = Object.values(operations); + + for (let i = 0; i < fuzzSteps; i++) { + // Pick a random operation and check if that it was not a noop, otherwise continue + // trying to find a valid operation. + // eslint-disable-next-line + while (true) { + const operation = opsArray[Math.floor(Math.random() * opsArray.length)]; + if (await operation()) { + break; + } + } + } + + if (removeEnglishTab) { + await removeEnglishTab(); + } + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_gear.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_gear.js new file mode 100644 index 0000000000..574895a845 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_gear.js @@ -0,0 +1,34 @@ +/* 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, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.clickManageLanguages(); + + await 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/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_init_failure.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_init_failure.js new file mode 100644 index 0000000000..34986726b8 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_init_failure.js @@ -0,0 +1,25 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies that the proper error message is displayed in + * the FullPageTranslationsPanel if the panel tries to open, but the language + * dropdown menus fail to initialize. + */ +add_task(async function test_full_page_translations_panel_init_failure() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + TranslationsPanelShared.simulateLangListError(); + await FullPageTranslationsTestUtils.openPanel({ + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewInitFailure, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_modify_available_language_models.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_modify_available_language_models.js new file mode 100644 index 0000000000..d0f9aafd0a --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_modify_available_language_models.js @@ -0,0 +1,148 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test verifies that when language models are added or removed from Remote Settings, + * then the list of available languages is immediately reflected in the FullPageTranslationsPanel's + * dropdown menu lists upon the panel's next open. + */ +add_task( + async function test_full_page_translations_panel_modify_available_language_models() { + const { runInPage, remoteClients, cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + autoDownloadFromRemoteSettings: true, + }); + + const { fromMenuList, toMenuList } = FullPageTranslationsPanel.elements; + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + ok( + !fromMenuList.querySelector('[value="ja"]'), + "The FullPageTranslationsPanel has no selection for Japanese in the from-menu-list." + ); + ok( + !toMenuList.querySelector('[value="ja"]'), + "The FullPageTranslationsPanel has no selection for Japanese in the to-menu-list." + ); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + const recordsForEnJa = createRecordsForLanguagePair("en", "ja"); + const recordsForJaEn = createRecordsForLanguagePair("ja", "en"); + + info("Publishing Japanese as a source language in Remote Settings."); + await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { + recordsToCreate: recordsForJaEn, + expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + ok( + fromMenuList.querySelector('[value="ja"]'), + "The FullPageTranslationsPanel now has an item for Japanese in the from-menu-list." + ); + ok( + !toMenuList.querySelector('[value="ja"]'), + "The FullPageTranslationsPanel still has no selection for Japanese in the to-menu-list." + ); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + info("Removing Japanese as a source language from Remote Settings."); + await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { + recordsToDelete: recordsForJaEn, + expectedDeletedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + ok( + !fromMenuList.querySelector('[value="ja"]'), + "The FullPageTranslationsPanel no longer has an item for Japanese in the from-menu-list." + ); + ok( + !toMenuList.querySelector('[value="ja"]'), + "The FullPageTranslationsPanel still has no selection for Japanese in the to-menu-list." + ); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + info("Publishing Japanese as a target language in Remote Settings."); + await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { + recordsToCreate: recordsForEnJa, + expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + ok( + !fromMenuList.querySelector('[value="ja"]'), + "The FullPageTranslationsPanel still has no selection for Japanese in the from-menu-list." + ); + ok( + toMenuList.querySelector('[value="ja"]'), + "The FullPageTranslationsPanel now has an item for Japanese in the to-menu-list." + ); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + info("Republishing Japanese as a source language in Remote Settings."); + await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { + recordsToCreate: recordsForJaEn, + expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + ok( + fromMenuList.querySelector('[value="ja"]'), + "The FullPageTranslationsPanel now has an item for Japanese in the from-menu-list." + ); + ok( + toMenuList.querySelector('[value="ja"]'), + "The FullPageTranslationsPanel still has an item for Japanese in the to-menu-list." + ); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "ja", + }); + await FullPageTranslationsTestUtils.clickTranslateButton(); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "ja", + runInPage, + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_language.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_language.js new file mode 100644 index 0000000000..7436317fbb --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_language.js @@ -0,0 +1,198 @@ +/* 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 not translated 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate("Reload the page", { url: SPANISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate("Navigate to a different Spanish page", { + url: SPANISH_PAGE_URL_DOT_ORG, + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate("Reload the page", { url: SPANISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: false, + }); + + await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate("Reload the page", { url: SPANISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site.js new file mode 100644 index 0000000000..87b0bbe5f7 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site.js @@ -0,0 +1,261 @@ +/* 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 not translated 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate("Navigate to a Spanish page with the same content principal", { + url: SPANISH_PAGE_URL_2, + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate( + "Navigate to a Spanish page with a different content principal", + { url: SPANISH_PAGE_URL_DOT_ORG } + ); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button should be visible, because this content principal " + + "has not been denied translations permissions" + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate("Reload the page", { url: SPANISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate( + "Navigate to a Spanish page with the same content principal", + { url: SPANISH_PAGE_URL_2 } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate( + "Navigate to a Spanish page with a different content principal", + { url: SPANISH_PAGE_URL_DOT_ORG } + ); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button should be visible, because this content principal " + + "has not been denied translations permissions" + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate("Reload the page", { url: SPANISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate( + "Navigate to a Spanish page with the same content principal", + { url: SPANISH_PAGE_URL_2 } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate( + "Navigate to a Spanish page with a different content principal", + { + url: SPANISH_PAGE_URL_DOT_ORG, + downloadHandler: resolveDownloads, + } + ); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_auto.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_auto.js new file mode 100644 index 0000000000..cfca060f31 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_auto.js @@ -0,0 +1,115 @@ +/* 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 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate("Reload the page", { url: SPANISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate( + "Navigate to a Spanish page with the same content principal", + { url: SPANISH_PAGE_URL_2 } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate( + "Navigate to a Spanish page with a different content principal", + { + url: SPANISH_PAGE_URL_DOT_ORG, + } + ); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_basic.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_basic.js new file mode 100644 index 0000000000..a20c585224 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_basic.js @@ -0,0 +1,64 @@ +/* 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 not translated 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate("Navigate to a Spanish page with the same content principal", { + url: SPANISH_PAGE_URL_2, + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate( + "Navigate to a Spanish page with a different content principal", + { url: SPANISH_PAGE_URL_DOT_ORG } + ); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button should be visible, because this content principal " + + "has not been denied translations permissions" + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_manual.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_manual.js new file mode 100644 index 0000000000..a1a4e43527 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_manual.js @@ -0,0 +1,89 @@ +/* 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 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: false } + ); + await FullPageTranslationsTestUtils.clickNeverTranslateSite(); + await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( + SPANISH_PAGE_URL, + { checked: true } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate("Reload the page", { url: SPANISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate( + "Navigate to a Spanish page with the same content principal", + { url: SPANISH_PAGE_URL_2 } + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await navigate( + "Navigate to a Spanish page with a different content principal", + { url: SPANISH_PAGE_URL_DOT_ORG } + ); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button should be visible, because this content principal " + + "has not been denied translations permissions" + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_retry.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_retry.js new file mode 100644 index 0000000000..69de13f999 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_retry.js @@ -0,0 +1,59 @@ +/* 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "fr", + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + pivotTranslation: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "fr", + runInPage, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_script_tags.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_script_tags.js new file mode 100644 index 0000000000..c4cf883f6b --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_script_tags.js @@ -0,0 +1,153 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of the FullPageTranslationsPanel when the source + * language has a script tag and the target language does not have a script tag. + */ +add_task(async function test_translations_panel_source_lang_has_script_tag() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "zh-Hans", toLang: "en" }, + ], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "zh-Hans", + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "es", + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + pivotTranslation: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "zh-Hans", + toLanguage: "es", + runInPage, + }); + + await cleanup(); +}); + +/** + * This test case verifies the behavior of the FullPageTranslationsPanel when the target + * language has a script tag and the source language does not have a script tag. + */ +add_task(async function test_translations_panel_target_lang_has_script_tag() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "en", toLang: "zh-Hant" }, + ], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "zh-Hant", + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + pivotTranslation: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "zh-Hant", + runInPage, + }); + + await cleanup(); +}); + +/** + * This test case verifies the behavior of the FullPageTranslationsPanel when both the source + * language and the target language have a script tag. + */ +add_task( + async function test_translations_panel_source_and_target_langs_have_script_tags() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "zh-Hans", toLang: "en" }, + { fromLang: "en", toLang: "zh-Hans" }, + { fromLang: "zh-Hant", toLang: "en" }, + { fromLang: "en", toLang: "zh-Hant" }, + ], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "zh-Hant", + }); + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "zh-Hans", + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + pivotTranslation: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "zh-Hant", + toLanguage: "zh-Hans", + runInPage, + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_settings_unsupported_lang.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_settings_unsupported_lang.js new file mode 100644 index 0000000000..38d29f30ab --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_settings_unsupported_lang.js @@ -0,0 +1,76 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This tests a specific defect where the language checkbox states were not being + * updated correctly when visiting a web page in an unsupported language after + * previously enabling always-translate-language or never-translate-language + * on a site with a supported language. + * + * See https://bugzilla.mozilla.org/show_bug.cgi?id=1845611 for more information. + */ +add_task(async function test_unsupported_language_settings_menu_checkboxes() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: [ + // Do not include French. + { fromLang: "en", toLang: "es" }, + { fromLang: "es", toLang: "en" }, + ], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await navigate("Navigate to a page in an unsupported language.", { + url: FRENCH_PAGE_URL, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The translations button should be unavailable." + ); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + onOpenPanel: + FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("fr", { + checked: false, + disabled: true, + }); + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("fr", { + checked: false, + disabled: true, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_languages.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_languages.js new file mode 100644 index 0000000000..4b6872aa58 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_languages.js @@ -0,0 +1,79 @@ +/* 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + const { translateButton } = FullPageTranslationsPanel.elements; + + ok(!translateButton.disabled, "The translate button starts as enabled"); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "en", + }); + + ok( + translateButton.disabled, + "The translate button is disabled when the languages are the same" + ); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "es", + }); + + ok( + !translateButton.disabled, + "When the languages are different it can be translated" + ); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "", + }); + + ok( + translateButton.disabled, + "The translate button is disabled nothing is selected." + ); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "en", + }); + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "fr", + }); + + ok(!translateButton.disabled, "The translate button can now be used"); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "en", + toLanguage: "fr", + runInPage, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_tabs_before_engine_ready.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_tabs_before_engine_ready.js new file mode 100644 index 0000000000..e974583c31 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_tabs_before_engine_ready.js @@ -0,0 +1,300 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the Translations URL-bar button does not become active in a tab + * where it is not currently present, when downloads complete and the TranslationsEngine + * becomes ready for translations that were requested in a different tab. + */ +add_task(async function test_button_does_not_update_when_button_is_not_shown() { + const { + tab: englishTab, + resolveDownloads, + cleanup, + } = await loadTestPage({ + page: ENGLISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The button should not be present since English is a known user language." + ); + + const { + tab: spanishTab, + runInPage: runInSpanishPage, + removeTab, + } = await addTab( + SPANISH_PAGE_URL, + "Creating a new tab for a page in Spanish." + ); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is present in the Spanish page." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInSpanishPage + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton(); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + + await switchTab(englishTab, "Switch to English tab"); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The button should still not be present on the English page before resolving downloads." + ); + + await resolveDownloads(1); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The button should still not be present on the English page after resolving downloads." + ); + + await switchTab(spanishTab, "Switch back to the Spanish tab"); + + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + "es", + "en" + ); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage: runInSpanishPage, + }); + + await removeTab(); + await cleanup(); +}); + +/** + * This test case ensures that the Translations URL-bar button does not become active in a tab + * where it is present but inactive, when downloads complete and the TranslationsEngine + * becomes ready for translations that were requested in a different tab. + */ +add_task( + async function test_button_does_not_update_when_button_is_shown_but_inactive() { + const { + tab: spanishTabDotCom, + runInPage: runInSpanishDotComPage, + resolveDownloads, + cleanup, + } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is present Spanish .com tab." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInSpanishDotComPage + ); + + const { + tab: spanishTabDotOrg, + runInPage: runInSpanishDotOrgPage, + removeTab, + } = await addTab( + SPANISH_PAGE_URL_DOT_ORG, + "Creating a new tab for a page in Spanish with a .org URL." + ); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is present Spanish .org tab." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInSpanishDotOrgPage + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "fr", + }); + await FullPageTranslationsTestUtils.clickTranslateButton(); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator on the Spanish .org tab." + ); + + await switchTab(spanishTabDotCom, "Switch to the Spanish .com tab."); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button should be present but inactive on the Spanish .com tab." + ); + + await resolveDownloads(2); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button should be present but inactive on the Spanish .com tab, even after resolving downloads." + ); + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInSpanishDotComPage + ); + + await switchTab(spanishTabDotOrg, "Switch back to the Spanish .org tab"); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage: runInSpanishDotOrgPage, + } + ); + + await removeTab(); + await cleanup(); + } +); + +/** + * This test case ensures that the Translations URL-bar button does not change its displayed + * locale in a tab where it is present and active, when downloads complete and the TranslationsEngine + * becomes ready for translations that were requested in a different tab for a different language. + */ +add_task( + async function test_button_does_not_update_when_button_is_shown_but_inactive() { + const { + tab: spanishTabDotCom, + runInPage: runInSpanishDotComPage, + resolveDownloads, + cleanup, + } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is present Spanish .com tab." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInSpanishDotComPage + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "fr", + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage: runInSpanishDotComPage, + } + ); + + const { + tab: spanishTabDotOrg, + runInPage: runInSpanishDotOrgPage, + removeTab, + } = await addTab( + SPANISH_PAGE_URL_DOT_ORG, + "Creating a new tab for a page in Spanish with a .org URL." + ); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is present but not active in the Spanish .org tab." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInSpanishDotOrgPage + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "fr", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "uk", + }); + await FullPageTranslationsTestUtils.clickTranslateButton(); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator on the Spanish .org tab." + ); + + await switchTab(spanishTabDotCom, "Switch to the Spanish .com tab."); + + info("The Spanish .com page should still be translated to French."); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage: runInSpanishDotComPage, + } + ); + + await resolveDownloads(2); + + info( + "The Spanish .com page should still be translated to French, even after resolving downloads." + ); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage: runInSpanishDotComPage, + } + ); + + await switchTab(spanishTabDotOrg, "Switch back to the Spanish .org tab"); + + info("The Spanish .org page should be translated to Ukrainian."); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "uk", + runInPage: runInSpanishDotOrgPage, + } + ); + + await removeTab(); + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_target_language_persists_on_reopen.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_target_language_persists_on_reopen.js new file mode 100644 index 0000000000..c0c2795f80 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_target_language_persists_on_reopen.js @@ -0,0 +1,46 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests the bug described in Bug 1838422, + * where the target language is reset if the user clicks + * outside the translations panel and reopens it. + * The user-selected target language should persist when + * the panel is reopened. + */ +add_task( + async function test_browser_translations_full_page_panel_target_language_persists_on_reopen() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "uk", + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + // Reopen the translations panel and check if the target language is still "fr". + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "uk", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_unsupported_lang.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_unsupported_lang.js new file mode 100644 index 0000000000..87982e36ed --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_unsupported_lang.js @@ -0,0 +1,33 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests how the unsupported language flow works. + */ +add_task(async function test_unsupported_lang() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + }); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + onOpenPanel: + FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await FullPageTranslationsTestUtils.clickChangeSourceLanguageButton({ + intro: true, + }); + FullPageTranslationsTestUtils.assertPanelViewIntro(); + FullPageTranslationsTestUtils.assertSelectedFromLanguage({ langTag: "" }); + FullPageTranslationsTestUtils.assertSelectedToLanguage({ langTag: "en" }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_weblanguage_differs_from_app.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_weblanguage_differs_from_app.js new file mode 100644 index 0000000000..506b93d692 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_weblanguage_differs_from_app.js @@ -0,0 +1,42 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests what happens when the web languages differ from the app language. + */ +add_task(async function test_weblanguage_differs_app_locale() { + const { cleanup } = await loadTestPage({ + page: ENGLISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + systemLocales: ["en"], + appLocales: ["en"], + webLanguages: ["fr"], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The translations button is available" + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "en", + expectedToLanguage: "fr", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("en", { + checked: false, + disabled: false, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("en", { + checked: false, + disabled: false, + }); + + await closeAllOpenPanelsAndMenus(); + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_reader_mode.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_reader_mode.js new file mode 100644 index 0000000000..c8bd0b8614 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_reader_mode.js @@ -0,0 +1,141 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that the translations button becomes hidden when entering reader mode. + */ +add_task(async function test_translations_button_hidden_in_reader_mode() { + const { cleanup, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await toggleReaderMode(); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The translations button is now hidden in reader mode." + ); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is now the reader-mode header", + getH1, + "Translations Test" + ); + }); + + await runInPage(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's final paragraph is in Spanish.", + getFinalParagraph, + "— Pues, aunque mováis más brazos que los del gigante Briareo, me lo habéis de pagar." + ); + }); + + await toggleReaderMode(); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible again outside of reader mode." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await cleanup(); +}); + +/** + * Tests that translations persist when entering reader mode after translating. + */ +add_task(async function test_translations_persist_in_reader_mode() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + contentEagerMode: true, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + message: + "The page's H1's title should be translated because it intersects with the viewport.", + }); + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + message: + "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", + } + ); + + await runInPage(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's final paragraph is translated from Spanish to English.", + getFinalParagraph, + "— PUES, AUNQUE MOVÁIS MÁS BRAZOS QUE LOS DEL GIGANTE BRIAREO, ME LO HABÉIS DE PAGAR. [es to en]" + ); + }); + + await toggleReaderMode(); + + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is now the translated reader-mode header", + getH1, + "TRANSLATIONS TEST [es to en]" + ); + }); + + await runInPage(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's final paragraph is translated from Spanish to English.", + getFinalParagraph, + "— PUES, AUNQUE MOVÁIS MÁS BRAZOS QUE LOS DEL GIGANTE BRIAREO, ME LO HABÉIS DE PAGAR. [es to en]" + ); + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The translations button is now hidden in reader mode." + ); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_auto_translate.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_auto_translate.js new file mode 100644 index 0000000000..24fd2497a4 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_auto_translate.js @@ -0,0 +1,127 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the entire flow of opening the translation settings menu and initiating + * an auto-translate requests. + */ +add_task(async function test_translations_telemetry_auto_translate() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.alwaysTranslateLanguage, + { + expectedEventCount: 1, + expectNewFlowId: false, + assertForMostRecentEvent: { + language: "es", + }, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 1, + expectNewFlowId: false, + }); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 1, + expectNewFlowId: false, + }); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 0], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + expectNewFlowId: false, + assertForMostRecentEvent: { + request_target: "full_page", + }, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.clickRestoreButton(); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 2, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "revisitView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.restorePageButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 2, + expectNewFlowId: false, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_basics.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_basics.js new file mode 100644 index 0000000000..6d3f2f13e5 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_basics.js @@ -0,0 +1,93 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests basic usage of the Translations panel, and that the telemetry events are logged accordingly + */ +add_task(async function test_translations_telemetry_basics() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 0, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.cancelButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 1, + expectNewFlowId: false, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 2, + expectNewFlowId: true, + assertForAllEvents: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.cancelButton, + { + expectedEventCount: 2, + expectNewFlowId: false, + } + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 2, + expectNewFlowId: false, + }); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_open_panel.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_open_panel.js new file mode 100644 index 0000000000..128e7e3065 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_open_panel.js @@ -0,0 +1,93 @@ +/* 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(Glean.translationsPanel.open, { + expectedEventCount: 0, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.cancelButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 1, + expectNewFlowId: false, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 2, + expectNewFlowId: true, + assertForAllEvents: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.cancelButton, + { + expectedEventCount: 2, + expectNewFlowId: false, + } + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 2, + expectNewFlowId: false, + }); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer.js new file mode 100644 index 0000000000..731029b9be --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer.js @@ -0,0 +1,87 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that the popup is automatically offered. + */ +add_task(async function test_translations_panel_auto_offer() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + autoOffer: true, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForAllEvents: { + auto_show: true, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.cancelButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 1, + expectNewFlowId: false, + }); + + await navigate("Navigate to another page on the same domain.", { + url: SPANISH_PAGE_URL_2, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is still shown." + ); + + await navigate("Navigate to a page on a different domain.", { + url: SPANISH_PAGE_URL_DOT_ORG, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 2, + expectNewFlowId: true, + assertForAllEvents: { + auto_show: true, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.cancelButton, + { + expectedEventCount: 2, + expectNewFlowId: false, + } + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 2, + expectNewFlowId: false, + }); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer_settings.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer_settings.js new file mode 100644 index 0000000000..58b47e1823 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer_settings.js @@ -0,0 +1,120 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests that the automatic offering of the popup can be disabled. + */ +add_task(async function test_translations_panel_auto_offer_settings() { + const { cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + // Use the auto offer mechanics, but default the pref to the off position. + autoOffer: true, + prefs: [["browser.translations.automaticallyPopup", false]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is shown." + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 0, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + await FullPageTranslationsTestUtils.assertIsAlwaysOfferTranslationsEnabled( + false + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForAllEvents: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await FullPageTranslationsTestUtils.clickAlwaysOfferTranslations(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.alwaysOfferTranslations, + { + expectedEventCount: 1, + expectNewFlowId: false, + assertForAllEvents: { + toggled_on: true, + }, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + await FullPageTranslationsTestUtils.assertIsAlwaysOfferTranslationsEnabled( + true + ); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 2, + expectNewFlowId: true, + assertForAllEvents: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.cancelButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 2, + expectNewFlowId: false, + }); + + await navigate( + "Wait for the popup to be shown when navigating to a different host.", + { + url: SPANISH_PAGE_URL_DOT_ORG, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + } + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 3, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: true, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_retranslate.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_retranslate.js new file mode 100644 index 0000000000..daf1c71a2b --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_retranslate.js @@ -0,0 +1,164 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the telemetry events for retranslating a page from the revisit view. + */ +add_task(async function test_translations_telemetry_retranslate() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "fr", + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "fr", + toLanguage: "en", + runInPage, + }); + + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 0], + ] + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectNewFlowId: true, + expectedEventCount: 1, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeFromLanguage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + language: "fr", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.translateButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 1, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + from_language: "fr", + to_language: "en", + auto_translate: false, + document_language: "es", + top_preferred_language: "en-US", + request_target: "full_page", + }, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "uk", + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "fr", + toLanguage: "uk", + runInPage, + }); + + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 2], + ["select", 0], + ] + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectNewFlowId: true, + expectedEventCount: 2, + assertForMostRecentEvent: { + auto_show: false, + view_name: "revisitView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeToLanguage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + language: "uk", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.translateButton, + { + expectedEventCount: 2, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 2, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + from_language: "fr", + to_language: "uk", + auto_translate: false, + document_language: "es", + top_preferred_language: "en", + request_target: "full_page", + }, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 2, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_switch_languages.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_switch_languages.js new file mode 100644 index 0000000000..cc4b6cd123 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_switch_languages.js @@ -0,0 +1,192 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the telemetry events for switching the from-language. + */ +add_task(async function test_translations_telemetry_switch_from_language() { + const { cleanup, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "en", + }); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeFromLanguage, + { + expectedEventCount: 1, + expectNewFlowId: false, + assertForMostRecentEvent: { + language: "en", + }, + } + ); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "es", + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeFromLanguage, + { + expectedEventCount: 2, + expectNewFlowId: false, + assertForMostRecentEvent: { + language: "es", + }, + } + ); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "", + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeFromLanguage, + { + expectedEventCount: 2, + } + ); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "en", + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeFromLanguage, + { + expectedEventCount: 3, + expectNewFlowId: false, + assertForMostRecentEvent: { + language: "en", + }, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); +}); + +/** + * Tests the telemetry events for switching the to-language. + */ +add_task(async function test_translations_telemetry_switch_to_language() { + const { cleanup, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "fr", + }); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeToLanguage, + { + expectedEventCount: 1, + expectNewFlowId: false, + assertForMostRecentEvent: { + language: "fr", + }, + } + ); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "en", + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeToLanguage, + { + expectedEventCount: 2, + expectNewFlowId: false, + assertForMostRecentEvent: { + language: "en", + }, + } + ); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ langTag: "" }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeToLanguage, + { + expectedEventCount: 2, + } + ); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "en", + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeToLanguage, + { + expectedEventCount: 3, + expectNewFlowId: false, + assertForMostRecentEvent: { + language: "en", + }, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_failure.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_failure.js new file mode 100644 index 0000000000..fcd809a0ec --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_failure.js @@ -0,0 +1,197 @@ +/* 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() { + const { cleanup, rejectDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 0, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: rejectDownloads, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewError, + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 2, + expectNewFlowId: false, + assertForMostRecentEvent: { + auto_show: true, + view_name: "errorView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.translateButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 1, + expectNewFlowId: false, + }); + await TestTranslationsTelemetry.assertEvent(Glean.translations.error, { + expectedEventCount: 1, + expectNewFlowId: false, + assertForMostRecentEvent: { + reason: "Error: Intentionally rejecting downloads.", + }, + }); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 0], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + expectNewFlowId: false, + assertForMostRecentEvent: { + from_language: "es", + to_language: "en", + auto_translate: false, + document_language: "es", + top_preferred_language: "en-US", + request_target: "full_page", + }, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); + } +); + +/** + * Tests the telemetry event for an automatic translation request failure. + */ +add_task(async function test_translations_telemetry_auto_translation_failure() { + const { cleanup, rejectDownloads, runInPage } = await loadTestPage({ + page: BLANK_PAGE, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.alwaysTranslateLanguages", "es"]], + }); + + await navigate("Navigate to a Spanish page", { + url: SPANISH_PAGE_URL, + downloadHandler: rejectDownloads, + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewError, + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: true, + view_name: "errorView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 0, + expectNewFlowId: false, + }); + await TestTranslationsTelemetry.assertEvent(Glean.translations.error, { + expectedEventCount: 1, + expectNewFlowId: false, + assertForMostRecentEvent: { + reason: "Error: Intentionally rejecting downloads.", + }, + }); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 0], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + expectNewFlowId: false, + assertForMostRecentEvent: { + from_language: "es", + to_language: "en", + auto_translate: true, + document_language: "es", + top_preferred_language: "en-US", + request_target: "full_page", + }, + } + ); + + await FullPageTranslationsTestUtils.clickCancelButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.cancelButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 1, + expectNewFlowId: false, + }); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_request.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_request.js new file mode 100644 index 0000000000..07a5939b08 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_request.js @@ -0,0 +1,157 @@ +/* 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, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 0, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.translateButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 1, + expectNewFlowId: false, + }); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 0], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + expectNewFlowId: false, + assertForMostRecentEvent: { + from_language: "es", + to_language: "en", + auto_translate: false, + document_language: "es", + top_preferred_language: "en-US", + request_target: "full_page", + }, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + 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: BLANK_PAGE, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.alwaysTranslateLanguages", "es"]], + }); + + await navigate("Navigate to a Spanish page", { + url: SPANISH_PAGE_URL, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "en", + runInPage, + }); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 0, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.translateButton, + { + expectedEventCount: 0, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 0, + }); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 0], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + from_language: "es", + to_language: "en", + auto_translate: true, + document_language: "es", + top_preferred_language: "en-US", + request_target: "full_page", + }, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_unsupported_lang.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_unsupported_lang.js new file mode 100644 index 0000000000..aa4622a85d --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_unsupported_lang.js @@ -0,0 +1,212 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * The FullPageTranslationsPanel telemetry when transitioning from the unsupported language view. + */ +add_task(async function test_translations_telemetry_unsupported_lang() { + const { runInPage, resolveDownloads, cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + }); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + onOpenPanel: + FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "appMenu", + document_language: "es", + }, + }); + + await FullPageTranslationsTestUtils.clickChangeSourceLanguageButton({ + intro: true, + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeSourceLanguageButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 1, + expectNewFlowId: false, + }); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 2, + expectNewFlowId: false, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "appMenu", + document_language: "es", + }, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.cancelButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 2, + expectNewFlowId: false, + }); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + onOpenPanel: + FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 3, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "appMenu", + document_language: "es", + }, + }); + + await FullPageTranslationsTestUtils.clickDismissErrorButton(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.dismissErrorButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 3, + expectNewFlowId: false, + }); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + onOpenPanel: + FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 4, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "appMenu", + document_language: "es", + }, + }); + + await FullPageTranslationsTestUtils.clickChangeSourceLanguageButton({ + intro: true, + }); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeSourceLanguageButton, + { + expectedEventCount: 2, + expectNewFlowId: false, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 4, + expectNewFlowId: false, + }); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 5, + expectNewFlowId: false, + assertForMostRecentEvent: { + auto_show: false, + view_name: "defaultView", + opened_from: "appMenu", + document_language: "es", + }, + }); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: "fr", + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "fr", + toLanguage: "en", + runInPage, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.changeFromLanguage, + { + expectNewFlowId: false, + expectedEventCount: 1, + assertForMostRecentEvent: { + language: "fr", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsPanel.translateButton, + { + expectedEventCount: 1, + expectNewFlowId: false, + } + ); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { + expectedEventCount: 5, + expectNewFlowId: false, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + expectNewFlowId: false, + assertForMostRecentEvent: { + from_language: "fr", + to_language: "en", + auto_translate: false, + document_language: "es", + top_preferred_language: "en-US", + request_target: "full_page", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 0], + ] + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_perf_es_en.js b/src/zen/tests/mochitests/translations/browser_translations_perf_es_en.js new file mode 100644 index 0000000000..d58904797b --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_perf_es_en.js @@ -0,0 +1,109 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This metadata schema is parsed by the perftest infrastructure. + * + * The perftest runner then scrapes the logs for a JSON results matching this schema, + * which are logged by the TranslationsBencher class. + * + * @see {TranslationsBencher.Journal} + */ +const perfMetadata = { + owner: "Translations Team", + name: "Full-Page Translation (Spanish to English)", + description: + "Tests the speed of Full Page Translations using the Spanish-to-English model.", + options: { + default: { + perfherder: true, + perfherder_metrics: [ + { + name: "engine-init-time", + unit: "ms", + shouldAlert: true, + lowerIsBetter: true, + }, + { + name: "words-per-second", + unit: "WPS", + shouldAlert: true, + lowerIsBetter: false, + }, + { + name: "tokens-per-second", + unit: "TPS", + shouldAlert: true, + lowerIsBetter: false, + }, + { + name: "peak-parent-process-memory-usage", + unit: "MiB", + shouldAlert: true, + lowerIsBetter: true, + }, + { + name: "stabilized-parent-process-memory-usage", + unit: "MiB", + shouldAlert: true, + lowerIsBetter: true, + }, + { + name: "post-gc-parent-process-memory-usage", + unit: "MiB", + shouldAlert: true, + lowerIsBetter: true, + }, + { + name: "peak-inference-process-memory-usage", + unit: "MiB", + shouldAlert: true, + lowerIsBetter: true, + }, + { + name: "stabilized-inference-process-memory-usage", + unit: "MiB", + shouldAlert: true, + lowerIsBetter: true, + }, + { + name: "post-gc-inference-process-memory-usage", + unit: "MiB", + shouldAlert: true, + lowerIsBetter: true, + }, + { + name: "total-translation-time", + unit: "s", + shouldAlert: true, + lowerIsBetter: true, + }, + ], + verbose: true, + manifest: "perftest.toml", + manifest_flavor: "browser-chrome", + try_platform: ["linux", "mac", "win"], + }, + }, +}; + +/** + * Request 4x longer timeout for this test. + */ +requestLongerTimeout(4); + +/** + * Runs the translations benchmark tests from Spanish to English. + */ +add_task(async function test_translations_performance_es_en() { + await TranslationsBencher.benchmarkTranslation({ + page: SPANISH_BENCHMARK_PAGE_URL, + sourceLanguage: "es", + targetLanguage: "en", + speedBenchCount: 5, + memoryBenchCount: 5, + memorySampleInterval: 10, + }); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_auto_translate.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_auto_translate.js new file mode 100644 index 0000000000..ba624ef7ed --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_auto_translate.js @@ -0,0 +1,82 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that recently translated target languages are stored, filtered, and retrieved + * properly when triggering multiple translations via auto translate. + */ +add_task(async function test_recent_language_memory_with_auto_translate() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [ + ["browser.translations.select.enable", true], + ["browser.translations.alwaysTranslateLanguages", "fr"], + ["browser.translations.mostRecentTargetLanguages", "uk"], + ], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectEnglishSection: true, + openAtEnglishSection: true, + expectedFromLanguage: "en", + expectedToLanguage: "uk", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickTranslateFullPageButton(); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "en", + toLanguage: "fr", + runInPage, + }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "es", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); + + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: false, + }); + await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage(); + await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { + checked: true, + }); + + await navigate("Navigate to a French page.", { url: FRENCH_PAGE_URL }); + await resolveDownloads(2); + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + "fr", + "es" + ); + + await navigate("Navigate to a Spanish page.", { url: SPANISH_PAGE_URL }); + await resolveDownloads(2); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ + fromLanguage: "es", + toLanguage: "fr", + runInPage, + }); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select.js new file mode 100644 index 0000000000..e72062d8a4 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select.js @@ -0,0 +1,103 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that recently translated target languages are stored, filtered, and retrieved + * properly when triggering multiple translations between the Full-Page Translations panel and the Select + * Translations Panel in various combinations. + */ +add_task( + async function test_recent_language_memory_with_full_page_and_select_translations() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "fr", + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.clickRestoreButton(); + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "fr", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickTranslateFullPageButton(); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage, + } + ); + + await navigate("Navigate to a French page.", { url: FRENCH_PAGE_URL }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectH1: true, + openAtH1: true, + expectedFromLanguage: "fr", + expectedToLanguage: "uk", + pivotTranslation: true, + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select_multi_window.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select_multi_window.js new file mode 100644 index 0000000000..bf69a34598 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select_multi_window.js @@ -0,0 +1,135 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that recently translated target languages are stored, filtered, and retrieved + * properly when triggering multiple translations from the Full-Page Translations panel and the Select + * Translations panel in different windows. + */ +add_task( + async function test_recent_language_memory_with_full_page_and_select_translations_multi_window() { + const window1 = window; + const { runInPage, resolveDownloads, cleanup } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + const window2 = await BrowserTestUtils.openNewBrowserWindow(); + + const testPage2 = await loadTestPage({ + win: window2, + page: FRENCH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await focusWindow(window1); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await focusWindow(window2); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "fr", + expectedToLanguage: "uk", + win: window2, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "es", + win: window2, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window2, + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + "fr", + "es", + window2 + ); + + await focusWindow(window1); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + expectedFromLanguage: "es", + expectedToLanguage: "fr", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "es", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["en"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await focusWindow(window2); + + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + "fr", + "es", + window2 + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + win: window2, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window2, + }); + + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + "fr", + "en", + window2 + ); + + await testPage2.cleanup(); + await BrowserTestUtils.closeWindow(window2); + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window.js new file mode 100644 index 0000000000..814fccddce --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window.js @@ -0,0 +1,127 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that recently translated target languages are stored, filtered, and retrieved + * properly when triggering multiple translations from the Full-Page Translations panel in different windows. + */ +add_task( + async function test_full_page_translations_panel_recent_language_memory_with_multiple_windows() { + const window1 = window; + const { runInPage, resolveDownloads, cleanup } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + const window2 = await BrowserTestUtils.openNewBrowserWindow(); + + const testPage2 = await loadTestPage({ + win: window2, + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await focusWindow(window1); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + win: window1, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "uk", + win: window1, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window1, + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "uk", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + win: window1, + expectedToLanguage: "en", + }); + + await focusWindow(window2); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + testPage2.runInPage + ); + + await FullPageTranslationsTestUtils.openPanel({ + win: window2, + expectedFromLanguage: "es", + expectedToLanguage: "uk", + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "fr", + win: window2, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window2, + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + "es", + "fr", + window2 + ); + + await focusWindow(window1); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "uk", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + win: window1, + expectedToLanguage: "fr", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window1, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage, + } + ); + + await testPage2.cleanup(); + await BrowserTestUtils.closeWindow(window2); + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window_multi_tab.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window_multi_tab.js new file mode 100644 index 0000000000..1928cf3956 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window_multi_tab.js @@ -0,0 +1,321 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [["test.wait300msAfterTabSwitch", true]], + }); +}); + +/** + * This test case open 5 tabs across 2 windows, requesting a translation to a different language in all 5 tabs before + * resolving all of the downloads at once. It then goes one by one through each open tab and ensures that they all show + * the correct locale code as well as translate the page content to the correct language. It also ensures that the language + * offered from the FullPageTranslationsPanel revisit view offers the correct language based on recent requests. + */ +add_task( + async function test_full_page_translations_panel_recent_language_memory_with_multiple_windows_and_multiple_tabs() { + const window1 = window; + const { + runInPage: runInEsEnPage, + cleanup: cleanupWindow1, + resolveBulkDownloads, + } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + }); + let expectedWasmDownloads = 0; + let expectedLanguagePairDownloads = 0; + + info("Opening a tab for es-en in window 1"); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is present and shows only the icon.", + window1 + ); + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInEsEnPage + ); + await FullPageTranslationsTestUtils.openPanel({ + win: window1, + expectedFromLanguage: "es", + expectedToLanguage: "en", + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window1, + }); + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The button presents the loading indicator", + window1 + ); + expectedWasmDownloads += 1; + expectedLanguagePairDownloads += 1; + + info("Opening a tab for es-fa in window 2"); + + const window2 = await BrowserTestUtils.openNewBrowserWindow(); + const { runInPage: runInEsFaPage, cleanup: cleanupWindow2 } = + await loadTestPage({ + win: window2, + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is present and shows only the icon.", + window2 + ); + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInEsFaPage + ); + await FullPageTranslationsTestUtils.openPanel({ + win: window2, + expectedFromLanguage: "es", + expectedToLanguage: "en", + }); + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "fa", + win: window2, + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window2, + }); + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The button presents the loading indicator", + window2 + ); + expectedWasmDownloads += 1; + expectedLanguagePairDownloads += 2; + + info("Opening a tab for es-sl in window 1"); + + await focusWindow(window1); + const { removeTab: removeEsSlTab, runInPage: runInEsSlPage } = await addTab( + SPANISH_PAGE_URL, + "Creating a new tab for es-sl", + window1 + ); + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is present and shows only the icon.", + window1 + ); + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInEsSlPage + ); + await FullPageTranslationsTestUtils.openPanel({ + win: window1, + expectedFromLanguage: "es", + expectedToLanguage: "fa", + }); + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "sl", + win: window1, + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window1, + }); + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The button presents the loading indicator", + window1 + ); + expectedWasmDownloads += 1; + expectedLanguagePairDownloads += 2; + + info("Opening a tab for es-uk in window 2"); + + await focusWindow(window2); + const { removeTab: removeEsUkTab, runInPage: runInEsUkPage } = await addTab( + SPANISH_PAGE_URL, + "Creating a new tab for es-uk", + window2 + ); + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is present and shows only the icon.", + window2 + ); + await FullPageTranslationsTestUtils.assertPageIsNotTranslated( + runInEsUkPage + ); + await FullPageTranslationsTestUtils.openPanel({ + win: window2, + expectedFromLanguage: "es", + expectedToLanguage: "sl", + }); + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "uk", + win: window2, + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window2, + }); + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The button presents the loading indicator", + window2 + ); + expectedWasmDownloads += 1; + expectedLanguagePairDownloads += 2; + + info("Opening a tab for fr-es in window 1"); + + await focusWindow(window1); + const { removeTab: removeFrEsTab, runInPage: runInFrEsPage } = await addTab( + FRENCH_PAGE_URL, + "Creating a new tab for fr-es", + window1 + ); + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is present and shows only the icon.", + window1 + ); + await runInFrEsPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The French page's H1 is translated from fr to es", + getH1, + "Cet élément d'en-tête HTML est écrit en français." + ); + }); + await FullPageTranslationsTestUtils.openPanel({ + win: window1, + expectedFromLanguage: "fr", + expectedToLanguage: "uk", + }); + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "es", + win: window1, + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + win: window1, + }); + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The button presents the loading indicator", + window1 + ); + expectedWasmDownloads += 1; + expectedLanguagePairDownloads += 2; + + info("Resolving all pending downloads for all open tabs"); + + await resolveBulkDownloads({ + expectedWasmDownloads, + expectedLanguagePairDownloads, + }); + + info("Ensuring that the fr-es tab is translated correctly"); + + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + "fr", + "es", + window1 + ); + await runInFrEsPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The French page's H1 is translated from fr to es", + getH1, + "CET ÉLÉMENT D'EN-TÊTE HTML EST ÉCRIT EN FRANÇAIS. [fr to es]" + ); + }); + await FullPageTranslationsTestUtils.openPanel({ + win: window1, + expectedToLanguage: "uk", + }); + await removeFrEsTab(); + + info("Ensuring that the es-uk tab is translated correctly"); + + await focusWindow(window2); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "uk", + runInPage: runInEsUkPage, + message: "The es-uk page should be translated to uk", + win: window2, + } + ); + await FullPageTranslationsTestUtils.openPanel({ + win: window2, + expectedToLanguage: "sl", + }); + await removeEsUkTab(); + + info("Ensuring that the es-sl tab is translated correctly"); + + await focusWindow(window1); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "sl", + runInPage: runInEsSlPage, + message: "The es-sl page should be translated to sl", + win: window1, + } + ); + await FullPageTranslationsTestUtils.openPanel({ + win: window1, + expectedToLanguage: "uk", + }); + await removeEsSlTab(); + + info("Ensuring that the es-fa tab is translated correctly"); + + await focusWindow(window2); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fa", + runInPage: runInEsFaPage, + message: "The es-fa page should be translated to fa", + win: window2, + } + ); + await FullPageTranslationsTestUtils.openPanel({ + win: window2, + expectedToLanguage: "uk", + }); + + info("Ensuring that the es-en tab is translated correctly"); + + await focusWindow(window1); + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage: runInEsEnPage, + message: "The es-en page should be translated to en", + win: window1, + } + ); + await FullPageTranslationsTestUtils.openPanel({ + win: window1, + expectedToLanguage: "uk", + }); + + await cleanupWindow2(); + await BrowserTestUtils.closeWindow(window2); + await cleanupWindow1(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_navigate.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_navigate.js new file mode 100644 index 0000000000..9c15b6b435 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_navigate.js @@ -0,0 +1,104 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that recently translated target languages are stored, filtered, and retrieved + * properly when triggering multiple translations from the Full-Page Translations panel when navigating + * between different pages in the same window. + */ +add_task( + async function test_full_page_translations_panel_recent_language_memory_when_navigating() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "fr", + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage, + } + ); + + await navigate("Navigate to a French page.", { url: FRENCH_PAGE_URL }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "fr", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "es", + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + "fr", + "es" + ); + + await navigate("Navigate to a Spanish page.", { url: SPANISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "fr", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + + await FullPageTranslationsTestUtils.clickCancelButton(); + + await navigate("Navigate to an English page.", { url: ENGLISH_PAGE_URL }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: false }, + "The button is not available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + openFromAppMenu: true, + expectedFromLanguage: "en", + expectedToLanguage: "es", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + "en", + "es" + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_retranslate.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_retranslate.js new file mode 100644 index 0000000000..03db62efd1 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_retranslate.js @@ -0,0 +1,85 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that recently translated target languages are stored, filtered, and retrieved + * properly when triggering multiple translations from the Full-Page Translations panel on the same page. + */ +add_task( + async function test_full_page_translations_panel_recent_language_memory_on_retranslate() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SPANISH_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "uk", + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "uk", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: "fr", + }); + await FullPageTranslationsTestUtils.clickTranslateButton({ + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "uk", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.clickRestoreButton(); + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "fr", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, + }); + await FullPageTranslationsTestUtils.clickCancelButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_engine_unsupported.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_engine_unsupported.js new file mode 100644 index 0000000000..b5fe9de0ef --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_engine_unsupported.js @@ -0,0 +1,35 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test checks the availability of the translate-selection menu item in the context menu, + * ensuring it is not visible when the hardware does not support Translations. In this case + * we simulate this scenario by setting "browser.translations.simulateUnsupportedEngine" to true. + */ +add_task( + async function test_translate_selection_menuitem_is_unavailable_when_engine_is_unsupported() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [ + ["browser.translations.enable", true], + ["browser.translations.select.enable", true], + ["browser.translations.simulateUnsupportedEngine", true], + ], + }); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectMenuItemVisible: false, + }, + "The translate-selection context menu item should be unavailable the translations engine is unsupported." + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_feature_disabled.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_feature_disabled.js new file mode 100644 index 0000000000..8d6e4772da --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_feature_disabled.js @@ -0,0 +1,114 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// This file ensures that the translate selection menu item is unavailable when the translation feature is disabled, +// This file will be removed when the feature is released, as the pref will no longer exist. +// +// https://bugzilla.mozilla.org/show_bug.cgi?id=1870366 +// +// However, for the time being, I like having these tests to ensure there is no regression when the pref +// is set to false. + +/** + * This test checks the availability of the translate-selection menu item in the context menu, + * ensuring it is not visible when the "browser.translations.select.enable" preference is set to false + * and no text is selected when the context menu is invoked. + */ +add_task( + async function test_translate_selection_menuitem_is_unavailable_with_feature_disabled_and_no_text_selected() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", false]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: false, + openAtSpanishSentence: true, + expectMenuItemVisible: false, + }, + "The translate-selection context menu item should be unavailable when the feature is disabled." + ); + + await cleanup(); + } +); + +/** + * This test case verifies the functionality of the translate-selection context menu item + * when the selected text is not in the user's preferred language. The menu item should be + * localized to translate to the target language matching the user's top preferred language + * when the selected text is detected to be in a different language. + */ +add_task( + async function test_translate_selection_menuitem_is_unavailable_with_feature_disabled_and_text_selected() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", false]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectMenuItemVisible: false, + }, + "The translate-selection context menu item should be unavailable when the feature is disabled." + ); + + await cleanup(); + } +); + +/** + * This test checks the availability of the translate-selection menu item in the context menu, + * ensuring it is not visible when the "browser.translations.select.enable" preference is set to false + * and the context menu is invoked on a hyperlink. This would result in the menu item being available + * if the pref were set to true. + */ +add_task( + async function test_translate_selection_menuitem_is_unavailable_with_feature_disabled_and_clicking_a_hyperlink() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", false]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: false, + openAtSpanishHyperlink: true, + expectMenuItemVisible: false, + }, + "The translate-selection context menu item should be unavailable when the feature is disabled." + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_app_locales.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_app_locales.js new file mode 100644 index 0000000000..60f9ec0dff --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_app_locales.js @@ -0,0 +1,106 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests various fallback edge cases regarding which language to + * offer for translations based on the user's application locale settings. + */ +add_task( + async function test_translate_selection_menuitem_preferred_app_locales() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "en", toLang: "es" }, + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "pl" }, + { fromLang: "pl", toLang: "en" }, + // Only supported as a source language + { fromLang: "fi", toLang: "en" }, + // Only supported as a target language + { fromLang: "en", toLang: "sl" }, + // Languages with script tags + { fromLang: "zh-Hans", toLang: "en" }, + { fromLang: "en", toLang: "zh-Hans" }, + { fromLang: "zh-Hant", toLang: "en" }, + { fromLang: "en", toLang: "zh-Hant" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["es", "fr", "fi", "ja", "sl"], + // The page language tag is "es", so expect the next language in the list. + expectedTargetLanguage: "fr", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["fr", "fi", "ja", "sl", "es"], + expectedTargetLanguage: "fr", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["fi", "ja", "sl", "es", "fr"], + // "fi" is not supported as a target language, so fall back + expectedTargetLanguage: "sl", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["ja", "sl", "es", "fr", "fi"], + expectedTargetLanguage: "sl", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["sl", "es", "fr", "fi", "ja"], + expectedTargetLanguage: "sl", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["zh-CN", "zh", "es", "fr", "fi", "ja"], + expectedTargetLanguage: "zh-Hans", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["zh-SG", "zh", "es", "fr", "fi", "ja"], + expectedTargetLanguage: "zh-Hans", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["zh-MY", "zh", "es", "fr", "fi", "ja"], + expectedTargetLanguage: "zh-Hans", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["zh-HK", "zh", "es", "fr", "fi", "ja"], + expectedTargetLanguage: "zh-Hant", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["zh-MO", "zh", "es", "fr", "fi", "ja"], + expectedTargetLanguage: "zh-Hant", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["zh-TW", "zh", "es", "fr", "fi", "ja"], + expectedTargetLanguage: "zh-Hant", + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_language_edge_cases.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_language_edge_cases.js new file mode 100644 index 0000000000..1bee976a06 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_language_edge_cases.js @@ -0,0 +1,74 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests various fallback edge cases regarding which language to + * offer for translations based on user settings and supported translations languages. + */ +add_task( + async function test_translate_selection_menuitem_preferred_language_edge_cases() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "en", toLang: "es" }, + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "pl" }, + { fromLang: "pl", toLang: "en" }, + // Only supported as a source language + { fromLang: "fi", toLang: "en" }, + // Only supported as a target language + { fromLang: "en", toLang: "sl" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + systemLocales: [], + appLocales: [], + webLanguages: [], + // No locales are specified, so fall back to "en". + expectedTargetLanguage: "en", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["fi", "fr", "en-US"], + webLanguages: ["zh"], + expectedTargetLanguage: "fr", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["zh", "uk", "fr", "en-US"], + webLanguages: ["fi"], + // Fall back to the first to-language compatible tag. + expectedTargetLanguage: "fr", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + appLocales: ["zh", "fi", "sl", "fr", "en-US"], + webLanguages: ["fi", "zh"], + // Fall back to the first to-language compatible tag. + expectedTargetLanguage: "sl", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + systemLocales: ["zh-TW", "zh-CN", "de"], + appLocales: ["pt-BR", "ja"], + webLanguages: ["cs", "hu"], + // None of these locales are supported, so default to "en". + expectedTargetLanguage: "en", + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_web_languages.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_web_languages.js new file mode 100644 index 0000000000..41eb4acd38 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_web_languages.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests various fallback edge cases regarding which language to + * offer for translations based on the user's web content language settings. + */ +add_task( + async function test_translate_selection_menuitem_preferred_web_languages() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "en", toLang: "es" }, + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "pl" }, + { fromLang: "pl", toLang: "en" }, + // Only supported as a source language + { fromLang: "fi", toLang: "en" }, + // Only supported as a target language + { fromLang: "en", toLang: "sl" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + webLanguages: ["es", "fr", "fi", "zh", "sl"], + // The page language tag is "es", so expect the next language in the list. + expectedTargetLanguage: "fr", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + webLanguages: ["fr", "fi", "zh", "sl", "es"], + expectedTargetLanguage: "fr", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + webLanguages: ["fi", "zh", "sl", "es", "fr"], + // "fi" is not supported as a target language, so fall back + expectedTargetLanguage: "sl", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + webLanguages: ["zh", "sl", "es", "fr", "fi"], + expectedTargetLanguage: "sl", + }); + + await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ + runInPage, + webLanguages: ["sl", "es", "fr", "fi", "zh"], + expectedTargetLanguage: "sl", + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_full_page_translations_active.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_full_page_translations_active.js new file mode 100644 index 0000000000..e47180c733 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_full_page_translations_active.js @@ -0,0 +1,174 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case checks the behavior of the translate-selection menu item in the context menu + * when full-page translations is active or inactive. The menu item should be available under + * the correct selected-text conditions while full-page translations is inactive, and it should + * never be available while full-page translations is active. + */ +add_task( + async function test_translate_selection_menuitem_with_text_selected_and_full_page_translations_active() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should be available while full-page translations is inactive." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should be available even while full-page translations is active." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.clickRestoreButton(); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should be available while full-page translations is inactive." + ); + + await cleanup(); + } +); + +/** + * This test case checks the behavior of the translate-selection menu item in the context menu + * when full-page translations is active or inactive. The menu item should be available under + * the correct link-clicked conditions while full-page translations is inactive, and it should + * never be available while full-page translations is active. + */ +add_task( + async function test_translate_selection_menuitem_with_link_clicked_and_full_page_translations_active() { + const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: false, + openAtSpanishHyperlink: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should be available while full-page translations is inactive." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + }); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: false, + openAtSpanishHyperlink: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should be available even while full-page translations is active." + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + + await FullPageTranslationsTestUtils.clickRestoreButton(); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: false, + openAtSpanishHyperlink: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should be available while full-page translations is inactive." + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_hyperlink.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_hyperlink.js new file mode 100644 index 0000000000..acd1960051 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_hyperlink.js @@ -0,0 +1,139 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the functionality of the translate-selection context menu item + * when a hyperlink is right-clicked. The menu item should offer to translate the link text + * to a target language when the detected language of the link text does not match the preferred + * language. + */ +add_task( + async function test_translate_selection_menuitem_translate_link_text_to_target_language() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: false, + openAtSpanishHyperlink: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should be localized to translate the link text" + + "to the target language." + ); + + await cleanup(); + } +); + +/** + * This test case verifies the functionality of the translate-selection context menu item + * when a hyperlink is right-clicked, and the link text is in the top preferred language. + * The menu item should still offer to translate the link text to the top preferred language, + * since the Select Translations Panel should pass through the text for same-language translation. + */ +add_task( + async function test_translate_selection_menuitem_translate_link_text_in_preferred_language() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: false, + openAtEnglishHyperlink: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should be localized to translate the link text" + + "to the target language." + ); + + await cleanup(); + } +); + +/** + * This test case ensures that the translate-selection context menu item functions correctly + * when text is actively selected but the context menu is invoked on an unselected hyperlink. + * The selected text content should take precedence over the link text, and the menu item should + * be localized to translate the selected text to the target language, rather than the hyperlink text. + */ +add_task( + async function test_translate_selection_menuitem_selected_text_takes_precedence_over_link_text() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: true, + openAtEnglishHyperlink: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should be localized to translate the selection" + + "even though the hyperlink is the element on which the context menu was invoked." + ); + + await cleanup(); + } +); + +/** + * This test case verifies that the translate-selection context menu item is unavailable + * when the underlying hyperlink text is a URL, rather than plain text. + */ +add_task( + async function test_translate_selection_menuitem_with_raw_url_hyperlink() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + openAtURLHyperlink: true, + expectMenuItemVisible: false, + }, + "The translate-selection context menu item should be unavailable when the hyperlink text is a URL." + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_no_text_selected.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_no_text_selected.js new file mode 100644 index 0000000000..71fd372e7d --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_no_text_selected.js @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies that the translate-selection context menu item is unavailable + * when no text is selected. + */ +add_task( + async function test_translate_selection_menuitem_is_unavailable_when_no_text_is_selected() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: false, + openAtSpanishSentence: true, + expectMenuItemVisible: false, + }, + "The translate-selection context menu item should be unavailable when no text is selected." + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_text_selected.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_text_selected.js new file mode 100644 index 0000000000..ce29a33795 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_text_selected.js @@ -0,0 +1,76 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the functionality of the translate-selection context menu item + * when the selected text is not in the user's preferred language. The menu item should be + * localized to translate to the target language matching the user's top preferred language + * when the selected text is detected to be in a different language. + */ +add_task( + async function test_translate_selection_menuitem_when_selected_text_is_not_preferred_language() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should display a target language " + + "when the selected text is not the preferred language." + ); + + await cleanup(); + } +); + +/** + * This test case verifies the functionality of the translate-selection context menu item + * when the selected text is detected to be in the user's preferred language. The menu item + * still be localized to the user's preferred language as a target, since the Select Translations + * Panel allows passing through the text for same-language translation. + */ +add_task( + async function test_translate_selection_menuitem_when_selected_text_is_preferred_language() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectEnglishSentence: true, + openAtEnglishSentence: true, + expectMenuItemVisible: true, + expectedTargetLanguage: "en", + }, + "The translate-selection context menu item should still display a target language " + + "when the selected text is in the preferred language." + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_a11y_utils.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_a11y_utils.js new file mode 100644 index 0000000000..4e50faa783 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_a11y_utils.js @@ -0,0 +1,87 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that A11yUtils.announce is called to announce to assistive technology + * whenever the translation completes, and that no call is made if the translation fails, + * since that is handled by aria-describedby when the error message occurs. + */ +add_task( + async function test_select_translations_panel_a11y_announce_translation_complete() { + const { cleanup, runInPage, resolveDownloads, rejectDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + is( + MockedA11yUtils.announceCalls.length, + 0, + "There should be no A11yUtils announce calls." + ); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + MockedA11yUtils.assertMostRecentAnnounceCall({ + expectedCallNumber: 1, + expectedArgs: { + id: "select-translations-panel-translation-complete-announcement", + }, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + MockedA11yUtils.assertMostRecentAnnounceCall({ + expectedCallNumber: 2, + expectedArgs: { + id: "select-translations-panel-translation-complete-announcement", + }, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + pivotTranslation: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + MockedA11yUtils.assertMostRecentAnnounceCall({ + expectedCallNumber: 3, + expectedArgs: { + id: "select-translations-panel-translation-complete-announcement", + }, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { + openDropdownMenu: false, + downloadHandler: rejectDownloads, + pivotTranslation: true, + onChangeLanguage: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + is( + MockedA11yUtils.announceCalls.length, + 3, + "A failed translation should not announce that the translation is complete." + ); + + await SelectTranslationsTestUtils.clickCancelButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_change_app_locale.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_change_app_locale.js new file mode 100644 index 0000000000..12f336803e --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_change_app_locale.js @@ -0,0 +1,74 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the language display names within the SelectTranslationsPanel + * dropdown menu lists update immediately upon the next panel open when the user's application + * locale changes. + */ +add_task( + async function test_select_translations_panel_change_application_locale() { + const { runInPage, resolveDownloads, cleanup } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + const { fromMenuList, toMenuList } = SelectTranslationsPanel.elements; + + is( + fromMenuList.label, + "French", + "The SelectTranslationsPanel from-menu-list languages should be localized to English display names." + ); + + is( + toMenuList.label, + "English", + "The SelectTranslationsPanel to-menu-list languages should be localized to English display names." + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + + info("Changing the application locale from English to Spanish"); + const cleanupLocales = await mockLocales({ + appLocales: ["es"], + webLanguages: ["en"], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + is( + fromMenuList.label, + "francés", + "The SelectTranslationsPanel from-menu-list languages should be localized to Spanish display names." + ); + + is( + toMenuList.label, + "inglés", + "The SelectTranslationsPanel to-menu-list languages should be localized to Spanish display names." + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanupLocales(); + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_close_on_new_tab.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_close_on_new_tab.js new file mode 100644 index 0000000000..86e563b157 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_close_on_new_tab.js @@ -0,0 +1,46 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests the scenario where the SelectTranslationsPanel is open + * and the user opens a new tab while the panel is still open. The panel should + * close appropriately, as the content relevant to the selection is no longer + * in the active tab. + */ +add_task( + async function test_select_translations_panel_translate_sentence_on_open() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + let tab; + + await SelectTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + async () => { + tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + SPANISH_PAGE_URL, + true // waitForLoad + ); + } + ); + + BrowserTestUtils.removeTab(tab); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_copy_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_copy_button.js new file mode 100644 index 0000000000..29eafb980d --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_copy_button.js @@ -0,0 +1,95 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests functionality of the SelectTranslationsPanel copy button + * when retranslating by closing the panel and re-opening the panel to new links + * or selections of text. + */ +add_task(async function test_select_translations_panel_copy_button_on_reopen() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtSpanishHyperlink: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickCopyButton(); + await SelectTranslationsTestUtils.clickDoneButton(); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectEnglishSection: true, + openAtEnglishSection: true, + expectedFromLanguage: "en", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickCopyButton(); + await SelectTranslationsTestUtils.clickDoneButton(); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickCopyButton(); + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); +}); + +/** + * This test case tests functionality of the SelectTranslationsPanel copy button + * when retranslating by changing the from-language and to-language values for + * the same selection of source text. + */ +add_task( + async function test_select_translations_panel_copy_button_on_retranslate() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickCopyButton(); + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickCopyButton(); + await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { + openDropdownMenu: false, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickCopyButton(); + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_engine_cache.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_engine_cache.js new file mode 100644 index 0000000000..a0ef58c694 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_engine_cache.js @@ -0,0 +1,59 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests that the SelectTranslationsPanel successfully + * caches the engine within the Translator for the given language pair, + * and if that engine is destroyed, the Translator will correctly reinitialize + * the engine, even for the same language pair. + */ +add_task( + async function test_select_translations_panel_translate_sentence_on_open() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + expectedDownloads: 1, + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + // No downloads because the engine is cached for this language pair. + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + info("Explicitly destroying the Translations Engine."); + await destroyTranslationsEngine(); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtFrenchHyperlink: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + // Expect downloads again since the engine was destroyed. + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_fallback_to_doc_language.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_fallback_to_doc_language.js new file mode 100644 index 0000000000..9cf9e5d2f4 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_fallback_to_doc_language.js @@ -0,0 +1,89 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests the case of opening the SelectTranslationsPanel when the + * detected language is unsupported, but the page language is known to be a supported + * language. The panel should automatically fall back to the page language in an + * effort to combat falsely identified selections. + */ +add_task( + async function test_select_translations_panel_translate_sentence_on_open() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include French. + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + // French is not supported, but the page is in Spanish, so expect Spanish. + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * Bug 1899354 + * + * This test case tests a specific defect in which the languageInfo cache within the + * SelectTranslationsPanel was not properly cleared between panel opens on different + * pages, causing the panel to think that the page's document language tag is that of + * the previously opened page, rather than the currently opened page. + */ +add_task( + async function test_select_translations_panel_translate_sentence_on_open() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: FRENCH_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectH1: true, + openAtH1: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await navigate("Navigate to the Select Translations test page.", { + url: SELECT_TEST_PAGE_URL, + }); + + // With the defect described by Bug 1899354 this would incorrectly translate to French, + // because it would fall back to the previously loaded page's language tag. + // + // However, since the SELECT_TEST_PAGE_URL is in Spanish, and the detected text is Spanish, + // we should have nothing to fall back to, and it should show the unsupported language view. + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_flip_lexical_shortlist.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_flip_lexical_shortlist.js new file mode 100644 index 0000000000..020049442d --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_flip_lexical_shortlist.js @@ -0,0 +1,104 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests translations in the SelectTranslationsPanel with the + * useLexicalShortlist pref initially set to false. It then toggles it to true, + * and then back to false, ensuring that the correct models are downloaded, and + * that the translations succeed with each flip of the pref. + */ +add_task( + async function test_select_translations_panel_lexical_shortlist_starting_false() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [ + ["browser.translations.select.enable", true], + ["browser.translations.useLexicalShortlist", false], + ], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await waitForTranslationModelRecordsChanged(() => { + Services.prefs.setBoolPref( + "browser.translations.useLexicalShortlist", + true + ); + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case tests translations in the SelectTranslationsPanel with the + * useLexicalShortlist pref initially set to true. It then toggles it to false, + * and then back to true, ensuring that the correct models are downloaded, and + * that the translations succeed with each flip of the pref. + */ +add_task( + async function test_select_translations_panel_lexical_shortlist_starting_true() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [ + ["browser.translations.select.enable", true], + ["browser.translations.useLexicalShortlist", true], + ], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await waitForTranslationModelRecordsChanged(() => { + Services.prefs.setBoolPref( + "browser.translations.useLexicalShortlist", + false + ); + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_init_failure.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_init_failure.js new file mode 100644 index 0000000000..9e17b0705f --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_init_failure.js @@ -0,0 +1,119 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the scenario of clicking the cancel button to close + * the SelectTranslationsPanel after the language lists fail to initialize upon + * opening the panel, and the proper error message is displayed. + */ +add_task(async function test_select_translations_panel_init_failure_cancel() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, + }); + + await SelectTranslationsTestUtils.clickCancelButton(); + + await cleanup(); +}); + +/** + * This test case verifies the scenario of opening the SelectTranslationsPanel to a valid + * language pair, but having the language lists fail to initialize, then clicking the try-again + * button multiple times until both initialization and translation succeed. + */ +add_task( + async function test_select_translations_panel_init_failure_try_again_into_translation() { + const { cleanup, runInPage, resolveDownloads, rejectDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + SelectTranslationsTestUtils.clickTryAgainButton, + SelectTranslationsTestUtils.assertPanelViewInitFailure + ); + + await SelectTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + async () => + SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: rejectDownloads, + }), + SelectTranslationsTestUtils.assertPanelViewTranslationFailure + ); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: resolveDownloads, + viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case verifies the scenario of opening the SelectTranslationsPanel to an unsupported + * language, but having the language lists fail to initialize, then clicking the try-again + * button multiple times until the unsupported-language view is shown. + */ +add_task( + async function test_select_translations_panel_init_failure_try_again_into_unsupported() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + SelectTranslationsTestUtils.clickTryAgainButton, + SelectTranslationsTestUtils.assertPanelViewInitFailure + ); + + await SelectTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + SelectTranslationsTestUtils.clickTryAgainButton, + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_modify_available_language_models.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_modify_available_language_models.js new file mode 100644 index 0000000000..d9121f6aad --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_modify_available_language_models.js @@ -0,0 +1,163 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test verifies that when language models are added or removed from Remote Settings, + * then the list of available languages is immediately reflected in the SelectTranslationsPanel's + * dropdown menu lists upon the panel's next open. + */ +add_task( + async function test_select_translations_panel_modify_available_language_models() { + const { runInPage, remoteClients, resolveDownloads, cleanup } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + }); + + const { fromMenuList, toMenuList } = SelectTranslationsPanel.elements; + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + ok( + !fromMenuList.querySelector('[value="ja"]'), + "The SelectTranslationsPanel has no selection for Japanese in the from-menu-list." + ); + ok( + !toMenuList.querySelector('[value="ja"]'), + "The SelectTranslationsPanel has no selection for Japanese in the to-menu-list." + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + + const recordsForEnJa = createRecordsForLanguagePair("en", "ja"); + const recordsForJaEn = createRecordsForLanguagePair("ja", "en"); + + info("Publishing Japanese as a source language in Remote Settings."); + await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { + recordsToCreate: recordsForJaEn, + expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + ok( + fromMenuList.querySelector('[value="ja"]'), + "The SelectTranslationsPanel now has a selection for Japanese in the from-menu-list." + ); + ok( + !toMenuList.querySelector('[value="ja"]'), + "The SelectTranslationsPanel still has no selection for Japanese in the to-menu-list." + ); + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["ja"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + info("Removing Japanese as a source language from Remote Settings."); + await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { + recordsToDelete: recordsForJaEn, + expectedDeletedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + ok( + !fromMenuList.querySelector('[value="ja"]'), + "The SelectTranslationsPanel no longer has a selection for Japanese in the from-menu-list." + ); + ok( + !toMenuList.querySelector('[value="ja"]'), + "The SelectTranslationsPanel still has no selection for Japanese in the to-menu-list." + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + + info("Publishing Japanese as a target language in Remote Settings."); + await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { + recordsToCreate: recordsForEnJa, + expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + ok( + !fromMenuList.querySelector('[value="ja"]'), + "The SelectTranslationsPanel still has no selection for Japanese in the from-menu-list." + ); + ok( + toMenuList.querySelector('[value="ja"]'), + "The SelectTranslationsPanel now has a selection for Japanese in the to-menu-list." + ); + await SelectTranslationsTestUtils.changeSelectedToLanguage(["ja"], { + openDropdownMenu: false, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + info("Republishing Japanese as a source language in Remote Settings."); + await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { + recordsToCreate: recordsForJaEn, + expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "ja", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + ok( + fromMenuList.querySelector('[value="ja"]'), + "The SelectTranslationsPanel now has a selection for Japanese in the from-menu-list." + ); + ok( + toMenuList.querySelector('[value="ja"]'), + "The SelectTranslationsPanel still has a selection for Japanese in the to-menu-list." + ); + await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["ja"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_pdf.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_pdf.js new file mode 100644 index 0000000000..fd675e9cea --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_pdf.js @@ -0,0 +1,42 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies that the Select Translations Panel functionality + * is available and works within PDF files. + */ +add_task(async function test_the_select_translations_panel_in_pdf_files() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: PDF_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectPdfSpan: true, + openAtPdfSpan: true, + expectedFromLanguage: "en", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { + openDropdownMenu: true, + pivotTranslation: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: false, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_reader_mode.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_reader_mode.js new file mode 100644 index 0000000000..5f05b1a878 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_reader_mode.js @@ -0,0 +1,44 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies that the Select Translations Panel functionality + * is available and works within reader mode. + */ +add_task(async function test_the_select_translations_panel_in_reader_mode() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await toggleReaderMode(); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectH1: true, + openAtH1: true, + expectedFromLanguage: "en", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { + openDropdownMenu: true, + pivotTranslation: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: false, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); +}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_directly.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_directly.js new file mode 100644 index 0000000000..fff0326f75 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_directly.js @@ -0,0 +1,70 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of triggering a translation by directly switching + * the from-language when the panel is already in the "translated" state from a previous + * language pair. + */ +add_task( + async function test_select_translations_panel_retranslate_on_change_from_language_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { + openDropdownMenu: false, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of triggering a translation by directly switching + * the to-language when the panel is already in the "translated" state from a previous + * language pair. + */ +add_task( + async function test_select_translations_panel_retranslate_on_change_to_language_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { + openDropdownMenu: false, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js new file mode 100644 index 0000000000..16f2cb39f7 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js @@ -0,0 +1,68 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of triggering a translation by switching the + * from-language by opening the language dropdown menu when the panel is already in + * the "translated" state from a previous language pair. + */ +add_task( + async function test_select_translations_panel_retranslate_on_change_from_language_via_popup() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtSpanishHyperlink: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of triggering a translation by switching the + * to-language by opening the language dropdown menu when the panel is already in + * the "translated" state from a previous language pair. + */ +add_task( + async function test_select_translations_panel_retranslate_on_change_to_language_via_popup() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtSpanishHyperlink: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_script_tags.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_script_tags.js new file mode 100644 index 0000000000..1a2e229626 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_script_tags.js @@ -0,0 +1,126 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of the SelectTranslationsPanel when the source + * language has a script tag and the target language does not have a script tag. + */ +add_task( + async function test_select_translations_panel_source_lang_has_script_tag() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "zh-Hant", toLang: "en" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["zh-Hant"], { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of the SelectTranslationsPanel when the target + * language has a script tag and the source language does not have a script tag. + */ +add_task( + async function test_select_translations_panel_target_lang_has_script_tag() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "en", toLang: "zh-Hans" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["zh-Hans"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + pivotTranslation: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of the SelectTranslationsPanel when both the source + * language and the target language have a script tag. + */ +add_task( + async function test_select_translations_panel_source_and_target_langs_have_script_tags() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "zh-Hans", toLang: "en" }, + { fromLang: "en", toLang: "zh-Hans" }, + { fromLang: "zh-Hant", toLang: "en" }, + { fromLang: "en", toLang: "zh-Hant" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["zh-Hant"], { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["zh-Hans"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + pivotTranslation: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_directly.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_directly.js new file mode 100644 index 0000000000..f45326800f --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_directly.js @@ -0,0 +1,71 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of directly switching the from-language to the same + * from-language that is already selected, ensuring no change occurs to the translation state, + * and that no re-translation is triggered. + */ +add_task( + async function test_select_translations_panel_select_current_from_language_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { + openDropdownMenu: false, + // No downloads are resolved, because no re-translation is triggered. + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of directly switching the to-language to the same + * to-language that is already selected, ensuring no change occurs to the translation state, + * and that no re-translation is triggered. + */ +add_task( + async function test_select_translations_panel_select_current_from_language_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtFrenchHyperlink: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["en"], { + openDropdownMenu: false, + // No downloads are resolved, because no re-translation is triggered. + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_from_dropdown_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_from_dropdown_menu.js new file mode 100644 index 0000000000..04aa731cf2 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_from_dropdown_menu.js @@ -0,0 +1,71 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of directly switching the from-language to the same + * from-language that is already selected by opening the language dropdown menu, + * ensuring no change occurs to the translation state, and that no re-translation is triggered. + */ +add_task( + async function test_select_translations_panel_select_current_from_language_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { + openDropdownMenu: true, + // No downloads are resolved, because no re-translation is triggered. + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of directly switching the to-language to the same + * to-language that is already selected by opening the language dropdown menu, + * ensuring no change occurs to the translation state, and that no re-translation is triggered. + */ +add_task( + async function test_select_translations_panel_select_current_from_language_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtFrenchHyperlink: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["en"], { + openDropdownMenu: true, + // No downloads are resolved, because no re-translation is triggered. + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_directly.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_directly.js new file mode 100644 index 0000000000..673faee796 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_directly.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of switching the from-language to the same value + * that is currently selected in the to-language, effectively stealing the to-language's + * value, leaving it unselected and focused. + */ +add_task( + async function test_select_translations_panel_select_same_from_language_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["en"], { + openDropdownMenu: false, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of switching the to-language to the same value + * that is currently selected in the from-language, creating a passthrough translation + * of the source text directly into the text area. + */ +add_task( + async function test_select_translations_panel_select_same_to_language_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: false, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_from_dropdown_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_from_dropdown_menu.js new file mode 100644 index 0000000000..eea7a76bf2 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_from_dropdown_menu.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of switching the from-language to the same value + * that is currently selected in the to-language by opening the language dropdown menu, + * effectively stealing the to-language's value, leaving it unselected and focused. + */ +add_task( + async function test_select_translations_panel_select_same_from_language_via_popup() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["en"], { + openDropdownMenu: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of switching the to-language to the same value + * that is currently selected in the from-language by opening the language dropdown menu, + * creating a passthrough translation of the source text directly into the text area. + */ +add_task( + async function test_select_translations_panel_select_same_to_language_via_popup() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_settings_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_settings_menu.js new file mode 100644 index 0000000000..b6263325d5 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_settings_menu.js @@ -0,0 +1,70 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests the scenario of clicking the settings menu item + * that leads to the translations section of the about:preferences settings + * page in Firefox. + */ +add_task(async function test_select_translations_panel_open_settings_page() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.openPanelSettingsMenu(); + SelectTranslationsTestUtils.clickTranslationsSettingsPageMenuItem(); + + await waitForCondition( + () => gBrowser.currentURI.spec === "about:preferences#general", + "Waiting for about:preferences to be opened." + ); + + info("Remove the about:preferences tab"); + gBrowser.removeCurrentTab(); + + await cleanup(); +}); + +/** + * This test case tests the scenario of opening the SelectTranslationsPanel + * settings menu from the unsupported-language panel state. + */ +add_task( + async function test_select_translations_panel_open_settings_menu_from_unsupported_language() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await SelectTranslationsTestUtils.openPanelSettingsMenu(); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_full_page_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_full_page_button.js new file mode 100644 index 0000000000..0d4fa1090c --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_full_page_button.js @@ -0,0 +1,87 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Simulates clicking the translate-full-page button with a from-language that + * matches the language of the given document. + */ +add_task( + async function test_select_translations_panel_translat_full_page_button_matching_doc_lang() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtSpanishHyperlink: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickTranslateFullPageButton(); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await cleanup(); + } +); + +/** + * Simulates clicking the translate-full-page button after changing the from-language + * and to-language values to values that don't match the document language or the + * user's app locale, ensuring that the current selection is respected. + */ +add_task( + async function test_select_translations_panel_translat_full_page_button_matching_doc_lang() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["fr"], { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + pivotTranslation: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickTranslateFullPageButton(); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "fr", + toLanguage: "uk", + runInPage, + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_directly.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_directly.js new file mode 100644 index 0000000000..7ea721fb0f --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_directly.js @@ -0,0 +1,67 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of triggering a translation by directly switching + * the from-language to a valid selection when the panel is in the "idle" state without + * valid language pair. + */ +add_task( + async function test_select_translations_panel_translate_on_change_from_language_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["fr"], { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of triggering a translation by directly switching + * the to-language to a valid selection when the panel is in the "idle" state without + * valid language pair. + */ +add_task( + async function test_select_translations_panel_translate_on_change_to_language_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectEnglishSection: true, + openAtEnglishSection: true, + expectedFromLanguage: "en", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_from_dropdown_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_from_dropdown_menu.js new file mode 100644 index 0000000000..c0ba02f6db --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_from_dropdown_menu.js @@ -0,0 +1,67 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of triggering a translation by switching the + * from-language to a valid selection by opening the language dropdown when the panel + * is in the "idle" state without valid language pair. + */ +add_task( + async function test_select_translations_panel_translate_on_change_from_language() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["fr"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of triggering a translation by switching the + * to-language to a valid selection by opening the language dropdown when the panel + * is in the "idle" state without valid language pair. + */ +add_task( + async function test_select_translations_panel_translate_on_change_to_language() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectEnglishSection: true, + openAtEnglishSection: true, + expectedFromLanguage: "en", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_directly.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_directly.js new file mode 100644 index 0000000000..cd60f73e6c --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_directly.js @@ -0,0 +1,98 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of directly changing the from-language in rapid succession, + * ensuring that any triggered translations are resolved/dropped in order, and that the final translated + * state matches the final selected language. + */ +add_task( + async function test_select_translations_panel_translate_on_change_from_language_multiple_times_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "fi", toLang: "en" }, + { fromLang: "en", toLang: "fi" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage( + ["fa", "fi", "fr", "sl", "uk"], + { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + } + ); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of directly changing the to-language in rapid succession, + * ensuring that any triggered translations are resolved/dropped in order, and that the final translated + * state matches the final selected language. + */ +add_task( + async function test_select_translations_panel_translate_on_change_to_language_multiple_times_directly() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "fi", toLang: "en" }, + { fromLang: "en", toLang: "fi" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtEnglishHyperlink: true, + expectedFromLanguage: "en", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage( + ["es", "fa", "fi", "fr", "sl", "uk", "fa"], + { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_from_dropdown_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_from_dropdown_menu.js new file mode 100644 index 0000000000..1b2044ef97 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_from_dropdown_menu.js @@ -0,0 +1,99 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of directly changing the from-language in rapid succession + * by opening the language dropdown menu, ensuring that any triggered translations are resolved/dropped + * in order, and that the final translated state matches the final selected language. + */ +add_task( + async function test_select_translations_panel_translate_on_change_from_language_multiple_times_via_popup() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "fi", toLang: "en" }, + { fromLang: "en", toLang: "fi" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage( + ["fa", "fi", "fr", "sl", "uk"], + { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + } + ); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of directly changing the to-language in rapid succession + * by opening the language dropdown menu, ensuring that any triggered translations are resolved/dropped + * in order, and that the final translated state matches the final selected language. + */ +add_task( + async function test_select_translations_panel_translate_on_change_to_language_multiple_times_via_popup() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "fi", toLang: "en" }, + { fromLang: "en", toLang: "fi" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectEnglishSentence: true, + openAtEnglishSentence: true, + expectedFromLanguage: "en", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage( + ["es", "fa", "fi", "fr", "sl", "uk"], + { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + } + ); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_open.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_open.js new file mode 100644 index 0000000000..7c7d6d88c9 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_open.js @@ -0,0 +1,86 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests the case of opening the SelectTranslationsPanel to a valid + * language pair from a short selection of text, which should trigger a translation + * on panel open. + */ +add_task( + async function test_select_translations_panel_translate_sentence_on_open() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case tests the case of opening the SelectTranslationsPanel to a valid + * language pair from hyperlink text, which should trigger a translation on panel open. + */ +add_task( + async function test_select_translations_panel_translate_link_text_on_open() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtSpanishHyperlink: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case tests the case of opening the SelectTranslationsPanel to a valid + * language pair from a long selection of text, which should trigger a translation + * on panel open. + */ +add_task( + async function test_select_translations_panel_translate_long_text_on_open() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_after_unsupported_language.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_after_unsupported_language.js new file mode 100644 index 0000000000..79ce46b7dc --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_after_unsupported_language.js @@ -0,0 +1,55 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests the scenario of encountering the translation failure message + * as a result of changing the source language from the unsupported-language state. + */ +add_task( + async function test_select_translations_panel_failure_after_unsupported_language() { + const { cleanup, runInPage, resolveDownloads, rejectDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( + "fr" + ); + + await SelectTranslationsTestUtils.clickTranslateButton({ + downloadHandler: rejectDownloads, + viewAssertion: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: rejectDownloads, + viewAssertion: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: resolveDownloads, + viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_open.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_open.js new file mode 100644 index 0000000000..0fc133f269 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_open.js @@ -0,0 +1,92 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests the scenario of opening the SelectTranslationsPanel to a translation + * attempt that fails, followed by closing the panel via the cancel button, and then re-attempting + * the translation by re-opening the panel and having it succeed. + */ +add_task( + async function test_select_translations_panel_translation_failure_on_open_then_cancel_and_reopen() { + const { cleanup, runInPage, rejectDownloads, resolveDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: rejectDownloads, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.clickCancelButton(); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case tests the scenario of opening the SelectTranslationsPanel to a translation + * attempt that fails, followed by clicking the try-again button multiple times to retry the + * translation until it finally succeeds. + */ +add_task( + async function test_select_translations_panel_translation_failure_on_open_then_try_again() { + const { cleanup, runInPage, rejectDownloads, resolveDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: rejectDownloads, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: rejectDownloads, + viewAssertion: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: rejectDownloads, + viewAssertion: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: resolveDownloads, + viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_retranslate.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_retranslate.js new file mode 100644 index 0000000000..d19439c6a4 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_retranslate.js @@ -0,0 +1,128 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests the scenario of encountering the translation failure message + * as a result of changing the selected from-language, along with moving from the failure + * state to a successful translation also by changing the selected from-language. + */ +add_task( + async function test_select_translations_panel_translation_failure_on_change_from_language() { + const { cleanup, runInPage, rejectDownloads, resolveDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { + openDropdownMenu: false, + downloadHandler: rejectDownloads, + onChangeLanguage: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk"], { + openDropdownMenu: true, + downloadHandler: rejectDownloads, + onChangeLanguage: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk"], { + openDropdownMenu: false, + downloadHandler: rejectDownloads, + onChangeLanguage: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: resolveDownloads, + viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case tests the scenario of encountering the translation failure message + * as a result of changing the selected to-language, along with moving from the failure + * state to a successful translation also by changing the selected to-language. + */ +add_task( + async function test_select_translations_panel_translation_failure_on_change_to_language() { + const { cleanup, runInPage, rejectDownloads, resolveDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { + openDropdownMenu: false, + downloadHandler: rejectDownloads, + onChangeLanguage: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { + openDropdownMenu: true, + downloadHandler: rejectDownloads, + onChangeLanguage: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + pivotTranslation: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { + openDropdownMenu: false, + downloadHandler: rejectDownloads, + onChangeLanguage: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: resolveDownloads, + pivotTranslation: true, + viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_unsupported_language.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_unsupported_language.js new file mode 100644 index 0000000000..0898bd125b --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_panel_unsupported_language.js @@ -0,0 +1,163 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the behavior of opening the SelectTranslationsPanel to an unsupported language + * and then clicking the done button to close the panel. + */ +add_task( + async function test_select_translations_panel_unsupported_click_done_button() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of opening the SelectTranslationsPanel to an unsupported language + * then changing the source language to the same language as the app locale, triggering a same-language + * translation, then changing the from-language and to-language multiple times. + */ +add_task( + async function test_select_translations_panel_unsupported_then_to_same_language_translation() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "fi", toLang: "en" }, + { fromLang: "en", toLang: "fi" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( + "en" + ); + + await SelectTranslationsTestUtils.clickTranslateButton({ + viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk", "fi"], { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["sl", "fr"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + pivotTranslation: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); + +/** + * This test case verifies the behavior of opening the SelectTranslationsPanel to an unsupported language + * then changing the source language to a valid language, followed by changing the from-language and to-language + * multiple times. + */ +add_task( + async function test_select_translations_panel_unsupported_into_different_language_translation() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "fi", toLang: "en" }, + { fromLang: "en", toLang: "fi" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( + "fr" + ); + + await SelectTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk", "fi"], { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + pivotTranslation: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["sl", "uk"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + pivotTranslation: true, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk"], { + openDropdownMenu: false, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + await SelectTranslationsTestUtils.clickDoneButton(); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_both_languages_together.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_both_languages_together.js new file mode 100644 index 0000000000..0b72f93f71 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_both_languages_together.js @@ -0,0 +1,333 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case tests the edge-case scenario where, through keyboard navigation, a user is technically + * able to change both the from-language and the to-language value before triggering a re-translation. + * We want to make sure in this situation that both telemetry events for a changed from-language and + * for a changed to-language fire. + * + * The test covers all three methods of triggering the translation: + * - Pressing the Enter key with the from-menulist focused. + * - Pressing the Enter key with the to-menulist focused. + * - Tabbing to focus the textarea after a language has been changed. + */ +add_task( + async function test_select_translations_panel_change_from_and_to_languages_before_retranslation() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "fi", toLang: "en" }, + { fromLang: "en", toLang: "fi" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 165, + source_text_word_count: 28, + }, + } + ); + + const { fromMenuList, toMenuList } = SelectTranslationsPanel.elements; + + info( + "Changing both the from-language and to-language before triggering translation." + ); + fromMenuList.value = "fr"; + toMenuList.value = "uk"; + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 0, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 0, + } + ); + + { + info( + "Triggering a single translation with both updated languages via Enter key on from-menulist." + ); + const translatablePhasePromise = + SelectTranslationsTestUtils.waitForPanelState("translatable"); + focusElementAndSynthesizeKey(fromMenuList, "KEY_Enter"); + await translatablePhasePromise; + + await SelectTranslationsTestUtils.handleDownloads({ + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + await SelectTranslationsTestUtils.assertPanelViewTranslated(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + language: "fr", + previous_language: "es", + document_language: "es", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + language: "uk", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fr", + to_language: "uk", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + }, + } + ); + } + + { + info( + "Changing both the from-language and to-language before triggering translation." + ); + fromMenuList.value = "fa"; + toMenuList.value = "en"; + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 1, + } + ); + + info( + "Triggering a single translation with both updated languages via Enter key on to-menulist." + ); + const translatablePhasePromise = + SelectTranslationsTestUtils.waitForPanelState("translatable"); + focusElementAndSynthesizeKey(toMenuList, "KEY_Enter"); + await translatablePhasePromise; + + await SelectTranslationsTestUtils.handleDownloads({ + downloadHandler: resolveDownloads, + }); + await SelectTranslationsTestUtils.assertPanelViewTranslated(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + language: "fa", + previous_language: "fr", + document_language: "es", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + language: "en", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 3], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 3, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fa", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + }, + } + ); + } + + { + info( + "Changing both the from-language and to-language before triggering translation." + ); + fromMenuList.value = "sl"; + toMenuList.value = "fi"; + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 2, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 2, + } + ); + + info( + "Triggering a single translation with both updated languages via Tab key on to-menulist." + ); + const translatablePhasePromise = + SelectTranslationsTestUtils.waitForPanelState("translatable"); + focusElementAndSynthesizeKey(toMenuList, "KEY_Tab"); + await translatablePhasePromise; + + await SelectTranslationsTestUtils.handleDownloads({ + pivotTranslation: true, + downloadHandler: resolveDownloads, + }); + await SelectTranslationsTestUtils.assertPanelViewTranslated(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 3, + assertForMostRecentEvent: { + language: "sl", + previous_language: "fa", + document_language: "es", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 3, + assertForMostRecentEvent: { + language: "fi", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 4], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 4, + assertForMostRecentEvent: { + document_language: "es", + from_language: "sl", + to_language: "fi", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + }, + } + ); + } + + await SelectTranslationsTestUtils.clickDoneButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 4, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_languages_multiple_times.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_languages_multiple_times.js new file mode 100644 index 0000000000..942c828ed5 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_languages_multiple_times.js @@ -0,0 +1,374 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the data associated the change-from-language and change-to-language + * telemetry events when changing selected the from-language menu item multiple times in different ways. + */ +add_task( + async function test_select_translations_panel_change_from_language_multiple_times() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "fi", toLang: "en" }, + { fromLang: "en", toLang: "fi" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 165, + source_text_word_count: 28, + }, + } + ); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage( + ["fi", "fr", "sl"], + { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + language: "sl", + previous_language: "es", + document_language: "es", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 0, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + document_language: "es", + from_language: "sl", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + }, + } + ); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk", "fa"], { + openDropdownMenu: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 3, + assertForMostRecentEvent: { + language: "fa", + previous_language: "uk", + document_language: "es", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 0, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 4], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 4, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fa", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + }, + } + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 4, + }); + + await cleanup(); + } +); + +/** + * This test case verifies the data associated the change-from-language and change-to-language + * telemetry events when changing the selected to-language menu item multiple times in different ways. + */ +add_task( + async function test_select_translations_panel_change_to_language_multiple_times() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "fi", toLang: "en" }, + { fromLang: "en", toLang: "fi" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 165, + source_text_word_count: 28, + }, + } + ); + + await SelectTranslationsTestUtils.changeSelectedToLanguage( + ["sl", "fi", "fa"], + { + openDropdownMenu: false, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 0, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + language: "fa", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "fa", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 165, + source_text_word_count: 28, + }, + } + ); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr", "uk"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 0, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 3, + assertForMostRecentEvent: { + language: "uk", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 4], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 4, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "uk", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 165, + source_text_word_count: 28, + }, + } + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 4, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_cancel.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_cancel.js new file mode 100644 index 0000000000..7503f11074 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_cancel.js @@ -0,0 +1,102 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the counts and extra data sent from telemetry events when interacting + * with the SelectTranslationsPanel's initialization-failure UI and the user cancels after retrying. + */ +add_task( + async function test_select_translations_panel_telemetry_init_failure_then_cancel() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.initializationFailureMessage, + { + expectedEventCount: 1, + } + ); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.clickTryAgainButton({ + viewAssertion: SelectTranslationsTestUtils.assertPanelViewInitFailure, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.tryAgainButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 2, + expectNewFlowId: false, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.initializationFailureMessage, + { + expectedEventCount: 2, + } + ); + + await SelectTranslationsTestUtils.clickCancelButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.cancelButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 2, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_succeed.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_succeed.js new file mode 100644 index 0000000000..f6d4797725 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_succeed.js @@ -0,0 +1,122 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the counts and extra data sent from telemetry events when interacting + * with the SelectTranslationsPanel's initialization-failure UI and retrying is successful. + */ +add_task( + async function test_select_translations_panel_telemetry_init_failure_then_succeed() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.initializationFailureMessage, + { + expectedEventCount: 1, + } + ); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: resolveDownloads, + viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.tryAgainButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 2, + expectNewFlowId: false, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: + AppConstants.platform === "win" + ? 2064 // With carriage returns + : 2041, // No carriage returns + source_text_word_count: 358, + }, + } + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 2, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_cancel_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_cancel_button.js new file mode 100644 index 0000000000..5ad1c4a816 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_cancel_button.js @@ -0,0 +1,174 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the SelectTranslationsPanel cancel button can be invoked with the Enter key + * from the initialization-failure panel view. + */ +add_task( + async function test_select_translations_panel_invoke_init_failure_cancel_button_with_enter_key() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.cancelButton, + "KEY_Enter" + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.cancelButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel cancel button can be invoked with the space bar + * from the initialization-failure panel view. + */ +add_task( + async function test_select_translations_panel_invoke_init_failure_cancel_button_with_space_bar() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.cancelButton, + " " + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.cancelButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel cancel button can be invoked with the Enter key + * from the translation-failure panel view. + */ +add_task( + async function test_select_translations_panel_invoke_translation_failure_cancel_button_with_enter_key() { + const { cleanup, runInPage, rejectDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: rejectDownloads, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.cancelButton, + "KEY_Enter" + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.cancelButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel cancel button can be invoked with the space bar + * from the translation-failure panel view. + */ +add_task( + async function test_select_translations_panel_invoke_translation_failure_cancel_button_with_space_bar() { + const { cleanup, runInPage, rejectDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: rejectDownloads, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.cancelButton, + " " + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.cancelButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_copy_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_copy_button.js new file mode 100644 index 0000000000..7536befdfd --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_copy_button.js @@ -0,0 +1,88 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the SelectTranslationsPanel copy button can be invoked with the Enter key. + */ +add_task( + async function test_select_translations_panel_invoke_copy_button_with_enter_key() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.copyButton, + "KEY_Enter" + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.copyButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel copy button can be invoked with the space bar. + */ +add_task( + async function test_select_translations_panel_invoke_copy_button_with_space_bar() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.copyButton, + " " + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.copyButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_done_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_done_button.js new file mode 100644 index 0000000000..945742b045 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_done_button.js @@ -0,0 +1,180 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the SelectTranslationsPanel done button can be invoked with the Enter key + * from the primary-UI panel view. + */ +add_task( + async function test_select_translations_panel_invoke_primary_done_button_with_enter_key() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.doneButtonPrimary, + "KEY_Enter" + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel done button can be invoked with the space bar + * from the primary-UI panel view. + */ +add_task( + async function test_select_translations_panel_invoke_primary_done_button_with_space_bar() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.doneButtonPrimary, + " " + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel done button can be invoked with the Enter key + * from the unsupported-language panel view. + */ +add_task( + async function test_select_translations_panel_invoke_secondary_done_button_with_enter_key() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include French. + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.doneButtonSecondary, + "KEY_Enter" + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel done button can be invoked with the space bar + * from the unsupported-language panel view. + */ +add_task( + async function test_select_translations_panel_invoke_secondary_done_button_with_space_bar() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.doneButtonSecondary, + " " + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_settings_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_settings_button.js new file mode 100644 index 0000000000..8377ed2c7c --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_settings_button.js @@ -0,0 +1,87 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the SelectTranslationsPanel settings button can be invoked with the Enter key. + */ +add_task( + async function test_select_translations_panel_open_settings_menu_with_enter_key() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.settingsButton, + "KEY_Enter" + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.openSettingsMenu, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel settings button can be invoked with the space bar. + */ +add_task( + async function test_select_translations_panel_open_settings_menu_with_space_bar() { + const { cleanup, runInPage } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectEnglishSection: true, + openAtEnglishSection: true, + expectedFromLanguage: "en", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.settingsButton, + " " + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.openSettingsMenu, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_button.js new file mode 100644 index 0000000000..0a095297e6 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_button.js @@ -0,0 +1,121 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the SelectTranslationsPanel translate button can be invoked with the Enter key. + */ +add_task( + async function test_select_translations_panel_invoke_translate_button_with_enter_key() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include French. + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( + "uk" + ); + + const translatablePhasePromise = + SelectTranslationsTestUtils.waitForPanelState("translatable"); + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.translateButton, + "KEY_Enter" + ); + await translatablePhasePromise; + + await SelectTranslationsTestUtils.handleDownloads({ + downloadHandler: resolveDownloads, + }); + await SelectTranslationsTestUtils.assertPanelViewTranslated(); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translateButton, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + detected_language: "fr", + from_language: "uk", + to_language: "en", + }, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel translate button can be invoked with the space bar. + */ +add_task( + async function test_select_translations_panel_invoke_translate_button_with_space_bar() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + + await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( + "fr" + ); + + const translatablePhasePromise = + SelectTranslationsTestUtils.waitForPanelState("translatable"); + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.translateButton, + " " + ); + await translatablePhasePromise; + + await SelectTranslationsTestUtils.handleDownloads({ + downloadHandler: resolveDownloads, + }); + await SelectTranslationsTestUtils.assertPanelViewTranslated(); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translateButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_full_page_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_full_page_button.js new file mode 100644 index 0000000000..712ae1db47 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_full_page_button.js @@ -0,0 +1,118 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the SelectTranslationsPanel translate-full-page button can be invoked with the Enter key. + */ +add_task( + async function test_select_translations_panel_invoke_translate_full_page_button_with_enter_key() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + const fullPageTranslationCompletePromise = + FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.translateFullPageButton, + "KEY_Enter" + ); + + await fullPageTranslationCompletePromise; + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "en", + runInPage, + } + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translateFullPageButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel translate-full-page button can be invoked with the space bar. + */ +add_task( + async function test_select_translations_panel_invoke_translate_full_page_button_with_space_bar() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSentence: true, + openAtFrenchSentence: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + + const fullPageTranslationCompletePromise = + FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale." + ); + + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.translateFullPageButton, + " " + ); + + await fullPageTranslationCompletePromise; + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "fr", + toLanguage: "en", + runInPage, + } + ); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translateFullPageButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_init_failure.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_init_failure.js new file mode 100644 index 0000000000..02727fe220 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_init_failure.js @@ -0,0 +1,106 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the SelectTranslationsPanel try-again button can be invoked with the Enter key. + * from the initialization-failure panel view. + */ +add_task( + async function test_select_translations_panel_invoke_init_failure_try_again_button_with_enter_key() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, + }); + + const translatablePhasePromise = + SelectTranslationsTestUtils.waitForPanelState("translatable"); + await SelectTranslationsTestUtils.waitForPanelPopupEvent("popupshown", () => + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.tryAgainButton, + "KEY_Enter" + ) + ); + await translatablePhasePromise; + + await SelectTranslationsTestUtils.handleDownloads({ + downloadHandler: resolveDownloads, + }); + await SelectTranslationsTestUtils.assertPanelViewTranslated(); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.tryAgainButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel try-again button can be invoked with the space bar. + * from the initialization-failure panel view. + */ +add_task( + async function test_select_translations_panel_invoke_init_failure_try_again_button_with_space_bar() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + TranslationsPanelShared.simulateLangListError(); + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, + }); + + const translatablePhasePromise = + SelectTranslationsTestUtils.waitForPanelState("translatable"); + await SelectTranslationsTestUtils.waitForPanelPopupEvent("popupshown", () => + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.tryAgainButton, + "KEY_Enter" + ) + ); + await translatablePhasePromise; + + await SelectTranslationsTestUtils.handleDownloads({ + downloadHandler: resolveDownloads, + }); + await SelectTranslationsTestUtils.assertPanelViewTranslated(); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.tryAgainButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_translation_failure.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_translation_failure.js new file mode 100644 index 0000000000..4509cbdb7e --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_translation_failure.js @@ -0,0 +1,110 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that the SelectTranslationsPanel try-again button can be invoked with the Enter key. + * from the translation-failure panel view. + */ +add_task( + async function test_select_translations_panel_invoke_translation_failure_try_again_button_with_enter_key() { + const { cleanup, runInPage, resolveDownloads, rejectDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: rejectDownloads, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + const translatablePhasePromise = + SelectTranslationsTestUtils.waitForPanelState("translatable"); + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.tryAgainButton, + "KEY_Enter" + ); + await translatablePhasePromise; + + await SelectTranslationsTestUtils.handleDownloads({ + downloadHandler: resolveDownloads, + }); + await SelectTranslationsTestUtils.assertPanelViewTranslated(); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.tryAgainButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); + +/** + * This test case ensures that the SelectTranslationsPanel try-again button can be invoked with the space bar. + * from the translation-failure panel view. + */ +add_task( + async function test_select_translations_panel_invoke_translation_failure_try_again_button_with_space_bar() { + const { cleanup, runInPage, resolveDownloads, rejectDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: rejectDownloads, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + + const translatablePhasePromise = + SelectTranslationsTestUtils.waitForPanelState("translatable"); + focusElementAndSynthesizeKey( + SelectTranslationsPanel.elements.tryAgainButton, + " " + ); + await translatablePhasePromise; + + await SelectTranslationsTestUtils.handleDownloads({ + downloadHandler: resolveDownloads, + }); + await SelectTranslationsTestUtils.assertPanelViewTranslated(); + + await closeAllOpenPanelsAndMenus(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.tryAgainButton, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_multi_page.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_multi_page.js new file mode 100644 index 0000000000..7e253d7a72 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_multi_page.js @@ -0,0 +1,138 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case ensures that all of the telemetry metadata is correct + * when translating multiple pages from different languages, ensuring that + * any cached information about the page's language etc. is properly updated. + */ +add_task( + async function test_select_translations_panel_telemetry_multiple_pages() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtSpanishHyperlink: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "hyperlink", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 23, + source_text_word_count: 4, + }, + } + ); + + await navigate("Navigate to a French page.", { url: FRENCH_PAGE_URL }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectH1: true, + openAtH1: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 2, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "fr", + from_language: "fr", + to_language: "en", + top_preferred_language: "en", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + document_language: "fr", + from_language: "fr", + to_language: "en", + top_preferred_language: "en", + request_target: "select", + auto_translate: false, + source_text_code_units: 49, + source_text_word_count: 9, + }, + } + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 2, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 2, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_primary_ui.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_primary_ui.js new file mode 100644 index 0000000000..2d972d385f --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_primary_ui.js @@ -0,0 +1,306 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the counts and extra data sent from telemetry events when interacting + * with the SelectTranslationsPanel's primary happy-path UI states. + */ +add_task( + async function test_select_translations_panel_telemetry_primary_ui_components() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + { fromLang: "es", toLang: "en" }, + { fromLang: "en", toLang: "es" }, + { fromLang: "fa", toLang: "en" }, + { fromLang: "en", toLang: "fa" }, + { fromLang: "fi", toLang: "en" }, + { fromLang: "en", toLang: "fi" }, + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + { fromLang: "sl", toLang: "en" }, + { fromLang: "en", toLang: "sl" }, + { fromLang: "uk", toLang: "en" }, + { fromLang: "en", toLang: "uk" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 165, + source_text_word_count: 28, + }, + } + ); + + await SelectTranslationsTestUtils.clickCopyButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.copyButton, + { + expectedEventCount: 1, + } + ); + + await SelectTranslationsTestUtils.changeSelectedFromLanguage(["fi"], { + openDropdownMenu: false, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + language: "fi", + previous_language: "es", + document_language: "es", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 0, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fi", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 165, + source_text_word_count: 28, + }, + } + ); + + await SelectTranslationsTestUtils.clickCopyButton(); + await SelectTranslationsTestUtils.clickCopyButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.copyButton, + { + expectedEventCount: 3, + } + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 2, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 3], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 3, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en", + request_target: "select", + auto_translate: false, + source_text_code_units: 165, + source_text_word_count: 28, + }, + } + ); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fa"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeFromLanguage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + language: "fi", + previous_language: "es", + document_language: "es", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + language: "fa", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 4], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 4, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "fa", + top_preferred_language: "en", + request_target: "select", + auto_translate: false, + source_text_code_units: 165, + source_text_word_count: 28, + }, + } + ); + + await SelectTranslationsTestUtils.clickCopyButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.copyButton, + { + expectedEventCount: 4, + } + ); + + await SelectTranslationsTestUtils.clickTranslateFullPageButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translateFullPageButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 2, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 4], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 5, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "fa", + top_preferred_language: "fa", + request_target: "full_page", + auto_translate: false, + }, + } + ); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fa", + runInPage, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 3, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_settings_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_settings_menu.js new file mode 100644 index 0000000000..8229d6017b --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_settings_menu.js @@ -0,0 +1,98 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the counts and extra data sent from telemetry events when interacting + * with the SelectTranslationsPanel's settings menu. + */ +add_task( + async function test_select_translations_panel_telemetry_settings_menu() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtFrenchHyperlink: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fr", + to_language: "en", + top_preferred_language: "en-US", + text_source: "hyperlink", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fr", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 27, + source_text_word_count: 5, + }, + } + ); + + await SelectTranslationsTestUtils.openPanelSettingsMenu(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.openSettingsMenu, + { + expectedEventCount: 1, + } + ); + + SelectTranslationsTestUtils.clickTranslationsSettingsPageMenuItem(); + await waitForCondition( + () => gBrowser.currentURI.spec === "about:preferences#general", + "Waiting for about:preferences to be opened." + ); + info("Remove the about:preferences tab"); + gBrowser.removeCurrentTab(); + + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translationSettings, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_cancel.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_cancel.js new file mode 100644 index 0000000000..e12720c1e9 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_cancel.js @@ -0,0 +1,146 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the counts and extra data sent from telemetry events when interacting + * with the SelectTranslationsPanel's translation-failure UI and the user cancels after retrying. + */ +add_task( + async function test_select_translations_panel_telemetry_translation_failure_then_cancel() { + const { cleanup, runInPage, rejectDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: rejectDownloads, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fr", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fr", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: + AppConstants.platform === "win" + ? 1616 // With carriage returns + : 1607, // No carriage returns + source_text_word_count: 257, + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translationFailureMessage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + from_language: "fr", + to_language: "en", + }, + } + ); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: rejectDownloads, + viewAssertion: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.tryAgainButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fr", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: + AppConstants.platform === "win" + ? 1616 // With carriage returns + : 1607, // No carriage returns + source_text_word_count: 257, + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translationFailureMessage, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + from_language: "fr", + to_language: "en", + }, + } + ); + + await SelectTranslationsTestUtils.clickCancelButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.cancelButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 0, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_succeed.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_succeed.js new file mode 100644 index 0000000000..35c9250b63 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_succeed.js @@ -0,0 +1,136 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the counts and extra data sent from telemetry events when interacting + * with the SelectTranslationsPanel's translation-failure UI and retrying is successful. + */ +add_task( + async function test_select_translations_panel_telemetry_translation_failure_then_succeed() { + const { cleanup, runInPage, rejectDownloads, resolveDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: rejectDownloads, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fr", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fr", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: + AppConstants.platform === "win" + ? 1616 // With carriage returns + : 1607, // No carriage returns + source_text_word_count: 257, + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translationFailureMessage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + from_language: "fr", + to_language: "en", + }, + } + ); + + await SelectTranslationsTestUtils.clickTryAgainButton({ + downloadHandler: resolveDownloads, + viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.tryAgainButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fr", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: + AppConstants.platform === "win" + ? 1616 // With carriage returns + : 1607, // No carriage returns + source_text_word_count: 257, + }, + } + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_with_full_page_translations_active.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_with_full_page_translations_active.js new file mode 100644 index 0000000000..f36d5e6b91 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_with_full_page_translations_active.js @@ -0,0 +1,212 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task( + async function test_select_translations_panel_translation_failure_with_full_page_translations_active() { + const { cleanup, runInPage, resolveDownloads, rejectDownloads } = + await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtSpanishHyperlink: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "hyperlink", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 23, + source_text_word_count: 4, + }, + } + ); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "fr", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 23, + source_text_word_count: 4, + }, + } + ); + + await SelectTranslationsTestUtils.clickTranslateFullPageButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translateFullPageButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 3, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "fr", + top_preferred_language: "fr", + request_target: "full_page", + auto_translate: false, + }, + } + ); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage, + } + ); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: rejectDownloads, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewTranslationFailure, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 2, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "fr", + from_language: "fr", + to_language: "en", + top_preferred_language: "fr", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 3], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 4, + assertForMostRecentEvent: { + document_language: "fr", + from_language: "fr", + to_language: "en", + top_preferred_language: "fr", + request_target: "select", + auto_translate: false, + source_text_code_units: + AppConstants.platform === "win" + ? 1616 // With carriage returns + : 1607, // No carriage returns + source_text_word_count: 257, + }, + } + ); + + await SelectTranslationsTestUtils.clickCancelButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.cancelButton, + { + expectedEventCount: 1, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "en", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "revisitView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 2, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_success_with_full_page_translations_active.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_success_with_full_page_translations_active.js new file mode 100644 index 0000000000..7069a855e8 --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_success_with_full_page_translations_active.js @@ -0,0 +1,249 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task( + async function test_select_translations_panel_translation_success_with_full_page_translations_active() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: LANGUAGE_PAIRS, + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtSpanishHyperlink: true, + expectedFromLanguage: "es", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "hyperlink", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 23, + source_text_word_count: 4, + }, + } + ); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { + openDropdownMenu: true, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "fr", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: 23, + source_text_word_count: 4, + }, + } + ); + + await SelectTranslationsTestUtils.clickTranslateFullPageButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translateFullPageButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 2], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 3, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "fr", + top_preferred_language: "fr", + request_target: "full_page", + auto_translate: false, + }, + } + ); + + await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( + { + fromLanguage: "es", + toLanguage: "fr", + runInPage, + } + ); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectFrenchSection: true, + openAtFrenchSection: true, + expectedFromLanguage: "fr", + expectedToLanguage: "en", + downloadHandler: resolveDownloads, + onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 2, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "fr", + from_language: "fr", + to_language: "en", + top_preferred_language: "fr", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 3], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 4, + assertForMostRecentEvent: { + document_language: "fr", + from_language: "fr", + to_language: "en", + top_preferred_language: "fr", + request_target: "select", + auto_translate: false, + source_text_code_units: + AppConstants.platform === "win" + ? 1616 // With carriage returns + : 1607, // No carriage returns + source_text_word_count: 257, + }, + } + ); + + await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { + openDropdownMenu: false, + pivotTranslation: true, + downloadHandler: resolveDownloads, + onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.changeToLanguage, + { + expectedEventCount: 2, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 1], + ["select", 4], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 5, + assertForMostRecentEvent: { + document_language: "fr", + from_language: "fr", + to_language: "uk", + top_preferred_language: "fr", + request_target: "select", + auto_translate: false, + source_text_code_units: + AppConstants.platform === "win" + ? 1616 // With carriage returns + : 1607, // No carriage returns + source_text_word_count: 257, + }, + } + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + + await FullPageTranslationsTestUtils.openPanel({ + expectedToLanguage: "uk", + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, + }); + await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + auto_show: false, + view_name: "revisitView", + opened_from: "translationsButton", + document_language: "es", + }, + }); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 4, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_unsupported_language_ui.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_unsupported_language_ui.js new file mode 100644 index 0000000000..b68f23eacc --- /dev/null +++ b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_unsupported_language_ui.js @@ -0,0 +1,162 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * This test case verifies the counts and extra data sent from telemetry events when interacting + * with the SelectTranslationsPanel's unsupported-language UI states. + */ +add_task( + async function test_select_translations_panel_telemetry_unsupported_language_ui() { + const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ + page: SELECT_TEST_PAGE_URL, + languagePairs: [ + // Do not include Spanish. + { fromLang: "fr", toLang: "en" }, + { fromLang: "en", toLang: "fr" }, + ], + prefs: [["browser.translations.select.enable", true]], + }); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + selectSpanishSection: true, + openAtSpanishSection: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 1, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.unsupportedLanguageMessage, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + detected_language: "es", + }, + } + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 1, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 1, + } + ); + + await SelectTranslationsTestUtils.openPanel(runInPage, { + openAtFrenchHyperlink: true, + onOpenPanel: + SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.open, + { + expectedEventCount: 2, + expectNewFlowId: true, + assertForMostRecentEvent: { + document_language: "es", + from_language: "es", + to_language: "en", + top_preferred_language: "en-US", + text_source: "selection", + }, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.unsupportedLanguageMessage, + { + expectedEventCount: 2, + assertForMostRecentEvent: { + document_language: "es", + detected_language: "es", + }, + } + ); + + await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( + "fr" + ); + await SelectTranslationsTestUtils.clickTranslateButton({ + downloadHandler: resolveDownloads, + viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, + }); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.translateButton, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + detected_language: "es", + from_language: "fr", + to_language: "en", + }, + } + ); + await TestTranslationsTelemetry.assertLabeledCounter( + Glean.translations.requestCount, + [ + ["full_page", 0], + ["select", 1], + ] + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translations.translationRequest, + { + expectedEventCount: 1, + assertForMostRecentEvent: { + document_language: "es", + from_language: "fr", + to_language: "en", + top_preferred_language: "en-US", + request_target: "select", + auto_translate: false, + source_text_code_units: + AppConstants.platform === "win" + ? 2064 // With carriage returns + : 2041, // No carriage returns + source_text_word_count: 358, + }, + } + ); + + await SelectTranslationsTestUtils.clickDoneButton(); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.doneButton, + { + expectedEventCount: 2, + } + ); + await TestTranslationsTelemetry.assertEvent( + Glean.translationsSelectTranslationsPanel.close, + { + expectedEventCount: 2, + } + ); + + await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ + expectedEventCount: 1, + }); + + await cleanup(); + } +); diff --git a/src/zen/tests/mochitests/translations/head.js b/src/zen/tests/mochitests/translations/head.js new file mode 100644 index 0000000000..80456375c1 --- /dev/null +++ b/src/zen/tests/mochitests/translations/head.js @@ -0,0 +1,4291 @@ +/* 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 +); + +/** + * Converts milliseconds to seconds. + * + * @param {number} ms - The duration in milliseconds. + * @returns {number} The duration in seconds. + */ +function millisecondsToSeconds(ms) { + return ms / 1000; +} + +/** + * Converts bytes to mebibytes. + * + * @param {number} bytes - The size in bytes. + * @returns {number} The size in mebibytes. + */ +function bytesToMebibytes(bytes) { + return bytes / (1024 * 1024); +} + +/** + * Calculates the median of a list of numbers. + * + * @param {number[]} numbers - An array of numbers to find the median of. + * @returns {number} The median of the provided numbers. + */ +function median(numbers) { + numbers = numbers.sort((lhs, rhs) => lhs - rhs); + const midIndex = Math.floor(numbers.length / 2); + + if (numbers.length & 1) { + return numbers[midIndex]; + } + + return (numbers[midIndex - 1] + numbers[midIndex]) / 2; +} + +/** + * Opens a new tab in the foreground. + * + * @param {string} url + */ +async function addTab(url, message, win = window) { + logAction(url); + info(message); + const tab = await BrowserTestUtils.openNewForegroundTab( + win.gBrowser, + url, + true // Wait for load + ); + return { + tab, + removeTab() { + BrowserTestUtils.removeTab(tab); + }, + /** + * Runs a callback in the content page. The function's contents are serialized as + * a string, and run in the page. The `translations-test.mjs` module is made + * available to the page. + * + * @param {(TranslationsTest: import("./translations-test.mjs")) => any} callback + * @returns {Promise} + */ + runInPage(callback, data = {}) { + return ContentTask.spawn( + tab.linkedBrowser, + { contentData: data, callbackSource: callback.toString() }, // Data to inject. + function ({ contentData, callbackSource }) { + const TranslationsTest = ChromeUtils.importESModule( + "chrome://mochitests/content/browser/toolkit/components/translations/tests/browser/translations-test.mjs" + ); + + // Pass in the values that get injected by the task runner. + TranslationsTest.setup({ Assert, ContentTaskUtils, content }); + + // eslint-disable-next-line no-eval + let contentCallback = eval(`(${callbackSource})`); + return contentCallback(TranslationsTest, contentData); + } + ); + }, + }; +} + +/** + * Simulates clicking an element with the mouse. + * + * @param {element} element - The element to click. + * @param {string} [message] - A message to log to info. + */ +function click(element, message) { + logAction(message); + return new Promise(resolve => { + element.addEventListener( + "click", + function () { + resolve(); + }, + { once: true } + ); + + EventUtils.synthesizeMouseAtCenter(element, { + type: "mousedown", + isSynthesized: false, + }); + EventUtils.synthesizeMouseAtCenter(element, { + type: "mouseup", + isSynthesized: false, + }); + }); +} + +function focusElementAndSynthesizeKey(element, key) { + assertVisibility({ visible: { element } }); + element.focus(); + EventUtils.synthesizeKey(key); +} + +/** + * Focuses the given window object, moving it to the top of all open windows. + * + * @param {Window} win + */ +async function focusWindow(win) { + const windowFocusPromise = BrowserTestUtils.waitForEvent(win, "focus"); + win.focus(); + await windowFocusPromise; +} + +/** + * 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; +} + +/** + * Retrieves an element by its Id. + * + * @param {string} id + * @param {Document} [doc] + * @returns {Element} + * @throws Throws if the element is not visible in the DOM. + */ +function getById(id, doc = document) { + const element = maybeGetById(id, /* ensureIsVisible */ true, doc); + if (!element) { + throw new Error("The element is not visible in the DOM: #" + id); + } + return element; +} + +/** + * 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 (BrowserTestUtils.isVisible(element)) { + return element; + } + } + throw new Error("The element is not visible in the DOM: " + l10nId); +} + +/** + * Returns the intl display name of a given language tag. + * + * @param {string} langTag - A BCP-47 language tag. + */ +const getIntlDisplayName = (() => { + let languageDisplayNames = null; + + return langTag => { + if (!languageDisplayNames) { + languageDisplayNames = TranslationsParent.createLanguageDisplayNames({ + fallback: "none", + }); + } + return languageDisplayNames.of(langTag); + }; +})(); + +/** + * Attempts to retrieve an element by its Id. + * + * @param {string} id - The Id of the element to retrieve. + * @param {boolean} [ensureIsVisible=true] - If set to true, the function will return null when the element is not visible. + * @param {Document} [doc=document] - The document from which to retrieve the element. + * @returns {Element | null} - The retrieved element. + * @throws Throws if no element was found by the given Id. + */ +function maybeGetById(id, ensureIsVisible = true, doc = document) { + const element = doc.getElementById(id); + if (!element) { + throw new Error("Could not find the element by id: #" + id); + } + + if (!ensureIsVisible) { + return element; + } + + if (BrowserTestUtils.isVisible(element)) { + return element; + } + + return null; +} + +/** + * 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 (BrowserTestUtils.isVisible(element)) { + return element; + } + } + return null; +} + +/** + * Provide a uniform way to log actions. This abuses the Error stack to get the callers + * of the action. This should help in test debugging. + */ +function logAction(...params) { + const error = new Error(); + const stackLines = error.stack.split("\n"); + const actionName = stackLines[1]?.split("@")[0] ?? ""; + const taskFileLocation = stackLines[2]?.split("@")[1] ?? ""; + if (taskFileLocation.includes("head.js")) { + // Only log actions that were done at the test level. + return; + } + + info(`Action: ${actionName}(${params.join(", ")})`); + info( + `Source: ${taskFileLocation.replace( + "chrome://mochitests/content/browser/", + "" + )}` + ); +} + +/** + * Returns true if Full-Page Translations is currently active, otherwise false. + * + * @returns {boolean} + */ +function isFullPageTranslationsActive() { + try { + const { requestedLanguagePair } = TranslationsParent.getTranslationsActor( + gBrowser.selectedBrowser + ).languageState; + return !!requestedLanguagePair; + } catch { + // Translations actor unavailable, continue on. + } + return false; +} + +/** + * Navigate to a URL and indicate a message as to why. + */ +async function navigate( + message, + { url, onOpenPanel = null, downloadHandler = null, pivotTranslation = false } +) { + logAction(); + // When the translations panel is open from the app menu, + // it doesn't close on navigate the way that it does when it's + // open from the translations button, so ensure that we always + // close it when we navigate to a new page. + await closeAllOpenPanelsAndMenus(); + + info(message + " - " + url); + + // 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. + await loadBlankPage(); + const loadTargetPage = async () => { + await loadNewPage(gBrowser.selectedBrowser, url); + + if (downloadHandler) { + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + await downloadHandler(pivotTranslation ? 2 : 1); + } + }; + + info(`Loading url: "${url}"`); + if (onOpenPanel) { + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + loadTargetPage, + onOpenPanel + ); + } else { + await loadTargetPage(); + } +} + +/** + * Switches to a given tab. + * + * @param {object} tab - The tab to switch to + * @param {string} name + */ +async function switchTab(tab, name) { + logAction("tab", name); + gBrowser.selectedTab = tab; + await new Promise(resolve => setTimeout(resolve, 0)); +} + +/** + * Click the reader-mode button if the reader-mode button is available. + * Fails if the reader-mode button is hidden. + */ +async function toggleReaderMode() { + logAction(); + const readerButton = document.getElementById("reader-mode-button"); + await waitForCondition(() => readerButton.hidden === false); + + readerButton.getAttribute("readeractive") + ? info("Exiting reader mode") + : info("Entering reader mode"); + + const readyPromise = readerButton.getAttribute("readeractive") + ? waitForCondition(() => !readerButton.getAttribute("readeractive")) + : BrowserTestUtils.waitForContentEvent( + gBrowser.selectedBrowser, + "AboutReaderContentReady" + ); + + click(readerButton, "Clicking the reader-mode button"); + await readyPromise; +} + +/** + * Scrolls to the top of the content page. + * + * @param {Function} runInPage - Runs a closure within the content context of the content page. + * + * @returns {Promise} Resolves once the scroll position has been updated and a paint has occurred. + */ +async function scrollToTopOfPage(runInPage) { + logAction(); + await runInPage(async ({ waitForCondition }) => { + content.scrollTo({ top: 0, behavior: "smooth" }); + + await waitForCondition( + () => content.scrollY <= 10, + "Waiting for scroll animation to complete." + ); + + // Wait for the new position to be painted. + await new Promise(resolve => { + content.requestAnimationFrame(() => + content.requestAnimationFrame(resolve) + ); + }); + }); +} + +/** + * Scrolls the content page to the very bottom. + * + * @param {Function} runInPage - Runs a closure within the content context of the content page. + * + * @returns {Promise} Resolves once the scroll position has been updated and a paint has occurred. + */ +async function scrollToBottomOfPage(runInPage) { + logAction(); + await runInPage(async ({ waitForCondition }) => { + const scrollHeight = content.document.documentElement.scrollHeight; + content.scrollTo({ top: scrollHeight, behavior: "smooth" }); + + await waitForCondition(() => { + return content.scrollY >= scrollHeight - content.innerHeight - 10; + }, "Waiting for scroll animation to complete."); + + // Wait for the new position to be painted. + await new Promise(resolve => { + content.requestAnimationFrame(() => + content.requestAnimationFrame(resolve) + ); + }); + }); +} + +/** + * A class for benchmarking translation performance and reporting + * metrics to our perftest infrastructure. + */ +class TranslationsBencher { + /** + * The metric base name for the engine initialization time. + * + * @type {string} + */ + static METRIC_ENGINE_INIT_TIME = "engine-init-time"; + + /** + * The metric base name for words translated per second. + * + * @type {string} + */ + static METRIC_WORDS_PER_SECOND = "words-per-second"; + + /** + * The metric base name for tokens translated per second. + * + * @type {string} + */ + static METRIC_TOKENS_PER_SECOND = "tokens-per-second"; + + /** + * The metric base name for peak memory usage in the parent process. + * The TranslationsBencher records this at a sampled interval reporting + * the maximum recorded memory recorded during the benchmark. + * + * @type {string} + */ + static METRIC_PEAK_PARENT_PROCESS_MEMORY_USAGE = + "peak-parent-process-memory-usage"; + + /** + * The metric base name for stabilized memory usage in the parent process. + * The TranslationsBencher records this just after finishing the final translation, + * but before destroying the engine and running GC. + * + * @type {string} + */ + static METRIC_STABILIZED_PARENT_PROCESS_MEMORY_USAGE = + "stabilized-parent-process-memory-usage"; + + /** + * The metric base name for the memory usage in the parent process after + * translation has completed, and after running cycle collection and + * garbage collection. + * + * @type {string} + */ + static METRIC_POST_GC_PARENT_PROCESS_MEMORY_USAGE = + "post-gc-parent-process-memory-usage"; + + /** + * The metric base name for peak memory usage in the inference process. + * The TranslationsBencher records this at a sampled interval reporting + * the maximum recorded memory recorded during the benchmark. + * + * @type {string} + */ + static METRIC_PEAK_INFERENCE_PROCESS_MEMORY_USAGE = + "peak-inference-process-memory-usage"; + + /** + * The metric base name for stabilized memory usage in the inference process, + * The TranslationsBencher records this just after finishing the final translation, + * but before running GC. + * + * @type {string} + */ + static METRIC_STABILIZED_INFERENCE_PROCESS_MEMORY_USAGE = + "stabilized-inference-process-memory-usage"; + + /** + * The metric base name for the memory usage in the inference process after + * translation has completed, and after running cycle collection and garbage + * garbage collection. + * + * @type {string} + */ + static METRIC_POST_GC_INFERENCE_PROCESS_MEMORY_USAGE = + "post-gc-inference-process-memory-usage"; + + /** + * The metric base name for total translation time. + * + * @type {string} + */ + static METRIC_TOTAL_TRANSLATION_TIME = "total-translation-time"; + + /** + * Data required to ensure that peftest metrics are validated and calculated correctly for the + * given test file. This data can be generated for a test file by running the script located at: + * + * toolkit/components/translations/tests/scripts/translations-perf-data.py + * + * @type {Record} + */ + static #PAGE_DATA = { + [SPANISH_BENCHMARK_PAGE_URL]: { + pageLanguage: "es", + tokenCount: 10966, + wordCount: 6944, + }, + }; + + /** + * A class that gathers and reports metrics to perftest. + */ + static Journal = class { + /** + * A map of collected metrics, where the key is the metric name + * and the value is an array of all recorded values. + * + * @type {Record} + */ + #metrics = {}; + + /** + * Pushes a metric value into the journal. + * + * @param {string} metricName - The metric name. + * @param {number} value - The metric value to record. + */ + pushMetric(metricName, value) { + if (!this.#metrics[metricName]) { + this.#metrics[metricName] = []; + } + + this.#metrics[metricName].push(Number(value.toFixed(3))); + } + + /** + * Pushes multiple metric values into the journal. + * + * @param {Array<[string, number]>} metrics - An array of [metricName, value] pairs. + */ + pushMetrics(metrics) { + for (const [metricName, value] of metrics) { + this.pushMetric(metricName, value); + } + } + + /** + * Logs the median value along with the individual values from all + * test runs for each collected metric to the console. + * The log is then picked up by the perftest infrastructure. + * The logged data must match the schema defined in the test file. + */ + reportMetrics() { + const reportedMetrics = []; + for (const [name, values] of Object.entries(this.#metrics)) { + reportedMetrics.push({ + name, + values, + value: median(values), + }); + } + info(`perfMetrics | ${JSON.stringify(reportedMetrics)}`); + } + }; + + /** + * A class to track peak memory usage during translation via sampled intervals. + */ + static PeakMemorySampler = class { + /** + * The peak recorded memory in mebibytes (MiB) for the parent process. + * + * @type {number} + */ + #peakParentMemoryMiB = 0; + + /** + * The peak recorded memory in mebibytes (MiB) for the inference process. + * + * @type {number} + */ + #peakInferenceMemoryMiB = 0; + + /** + * The interval id for the memory sample timer. + * + * @type {number|null} + */ + #intervalId = null; + + /** + * The interval at which memory usage is sampled in milliseconds. + * + * @type {number} + */ + #interval; + + /** + * Constructs a PeakMemorySampler. + * + * @param {number} interval - The interval in milliseconds between memory samples. + */ + constructor(interval) { + this.#interval = interval; + } + + /** + * Collects the current memory usage for both the parent and inference processes + * and updates the peak memory measurements if the current usage exceeds the + * previously recorded peaks. + * + * @returns {Promise} + */ + async #collectMemorySample() { + const { parentMemoryMiB, inferenceMemoryMiB } = + await TranslationsBencher.#getTotalMemoryUsageByProcess(); + + if (parentMemoryMiB > this.#peakParentMemoryMiB) { + this.#peakParentMemoryMiB = parentMemoryMiB; + } + if (inferenceMemoryMiB > this.#peakInferenceMemoryMiB) { + this.#peakInferenceMemoryMiB = inferenceMemoryMiB; + } + } + + /** + * Starts the interval timer to begin sampling new peak memory usage values. + */ + start() { + if (this.#intervalId !== null) { + throw new Error( + "Attempt to start a PeakMemorySampler that was already running." + ); + } + + this.#peakParentMemoryMiB = 0; + this.#peakInferenceMemoryMiB = 0; + this.#intervalId = setInterval(() => { + this.#collectMemorySample().catch(console.error); + }, this.#interval); + } + + /** + * Stops the interval timer from continuing to sample peak memory usage. + */ + stop() { + if (this.#intervalId === null) { + throw new Error( + "Attempt to stop a PeakMemorySampler that was not running." + ); + } + + clearInterval(this.#intervalId); + this.#intervalId = null; + this.#collectMemorySample(); + } + + /** + * Returns the peak recorded memory usage in mebibytes (MiB). + * + * @returns {{ peakParentMemoryMiB: number, peakInferenceMemoryMiB: number }} + */ + getPeakRecordedMemoryUsage() { + if (this.#intervalId) { + throw new Error( + "Attempt to retrieve peak recorded memory usage while the memory sampler is running." + ); + } + + return { + peakParentMemoryMiB: this.#peakParentMemoryMiB, + peakInferenceMemoryMiB: this.#peakInferenceMemoryMiB, + }; + } + }; + + /** + * Benchmarks the translation process (both memory usage and speed) + * and reports metrics to perftest. It runs one full translation for + * each memory sample, and then one full translation for each speed sample. + * + * @param {object} options - The benchmark options. + * @param {string} options.page - The URL of the page to test. + * @param {string} options.sourceLanguage - The BCP-47 language tag for the source language. + * @param {string} options.targetLanguage - The BCP-47 language tag for the target language. + * @param {number} options.speedBenchCount - The number of speed-sampling runs to perform. + * @param {number} options.memoryBenchCount - The number of memory-sampling runs to perform. + * @param {number} [options.memorySampleInterval] - The interval in milliseconds between memory usage samples. + * + * @returns {Promise} Resolves when benchmarking is complete. + */ + static async benchmarkTranslation({ + page, + sourceLanguage, + targetLanguage, + speedBenchCount, + memoryBenchCount, + memorySampleInterval = 10, + }) { + const { wordCount, tokenCount, pageLanguage } = + TranslationsBencher.#PAGE_DATA[page] ?? {}; + + if (!wordCount || !tokenCount || !pageLanguage) { + const testPageName = page.match(/[^\\/]+$/)[0]; + const testPagePath = page.substring( + "https://example.com/browser/".length + ); + const sourceLangName = getIntlDisplayName(sourceLanguage); + throw new Error(` + + 🚨 Perf test data is not properly defined for ${testPageName} 🚨 + + To enable ${testPageName} for Translations perf tests, please follow these steps: + + 1) Ensure ${testPageName} has a proper HTML lang attribute in the markup: + + + + 2) Download the ${sourceLanguage}-${PIVOT_LANGUAGE}.vocab.spm model from a ${sourceLangName} row on the following site: + + https://gregtatum.github.io/taskcluster-tools/src/models/ + + 3) Run the following command to extract the perf metadata from ${testPageName}: + + ❯ python3 toolkit/components/translations/tests/scripts/translations-perf-data.py \\ + --page_path="${testPagePath}" \\ + --model_path="..." + + 4) Include the resulting metadata for ${testPageName} in the TranslationsBencher.#PAGE_DATA object. + `); + } + + if (sourceLanguage !== pageLanguage) { + throw new Error( + `Perf test source language '${sourceLanguage}' did not match the expected page language '${pageLanguage}'.` + ); + } + + const journal = new TranslationsBencher.Journal(); + + await TranslationsBencher.#benchmarkTranslationMemory({ + page, + journal, + sourceLanguage, + targetLanguage, + memoryBenchCount, + memorySampleInterval, + }); + + await TranslationsBencher.#benchmarkTranslationSpeed({ + page, + journal, + sourceLanguage, + targetLanguage, + wordCount, + tokenCount, + speedBenchCount, + }); + + journal.reportMetrics(); + } + + /** + * Benchmarks memory usage by measuring peak and stabilized memory usage + * across multiple runs of the translation process. + * + * @param {object} options - The benchmark options. + * @param {string} options.page - The URL of the page to test. + * @param {TranslationsBencher.Journal} options.journal - The shared metrics journal. + * @param {string} options.sourceLanguage - The BCP-47 language tag for the source language. + * @param {string} options.targetLanguage - The BCP-47 language tag for the target language. + * @param {number} options.memoryBenchCount - The number of runs to perform for memory sampling. + * @param {number} options.memorySampleInterval - The interval in milliseconds between memory samples. + * + * @returns {Promise} Resolves when memory benchmarking is complete. + */ + static async #benchmarkTranslationMemory({ + page, + journal, + sourceLanguage, + targetLanguage, + memoryBenchCount, + memorySampleInterval, + }) { + for (let runNumber = 0; runNumber < memoryBenchCount; ++runNumber) { + const { cleanup, runInPage } = await loadTestPage({ + page, + endToEndTest: true, + languagePairs: [ + { fromLang: sourceLanguage, toLang: "en" }, + { fromLang: "en", toLang: targetLanguage }, + ], + prefs: [["browser.translations.logLevel", "Error"]], + contentEagerMode: true, + }); + + // Create a new PeakMemorySampler using the provided interval. + const peakMemorySampler = new TranslationsBencher.PeakMemorySampler( + memorySampleInterval + ); + + await TranslationsBencher.#injectFinalParagraphTranslatedObserver( + runInPage + ); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: sourceLanguage, + }); + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: targetLanguage, + }); + + const translationCompleteTimestampPromise = + TranslationsBencher.#getTranslationCompleteTimestampPromise(runInPage); + + peakMemorySampler.start(); + + await FullPageTranslationsTestUtils.clickTranslateButton(); + await translationCompleteTimestampPromise; + + peakMemorySampler.stop(); + + const { peakParentMemoryMiB, peakInferenceMemoryMiB } = + peakMemorySampler.getPeakRecordedMemoryUsage(); + + const { parentMemoryMiB, inferenceMemoryMiB } = + await TranslationsBencher.#getTotalMemoryUsageByProcess(); + + // Force cycle collection and garbage collection. + Services.obs.notifyObservers(null, "child-cc-request"); + Services.obs.notifyObservers(null, "child-gc-request"); + window.windowUtils.cycleCollect(); + Cu.forceGC(); + + const { inferenceMemoryMiB: postGCInferenceMiB } = + await TranslationsBencher.#getTotalMemoryUsageByProcess(); + + // Destroy the TranslationsEngine, then force cycle collection and garbage collection again. + await EngineProcess.destroyTranslationsEngine(); + Services.obs.notifyObservers(null, "child-cc-request"); + Services.obs.notifyObservers(null, "child-gc-request"); + window.windowUtils.cycleCollect(); + Cu.forceGC(); + + const { parentMemoryMiB: postGCParentMiB } = + await TranslationsBencher.#getTotalMemoryUsageByProcess(); + + journal.pushMetrics([ + [ + TranslationsBencher.METRIC_PEAK_PARENT_PROCESS_MEMORY_USAGE, + peakParentMemoryMiB, + ], + [ + TranslationsBencher.METRIC_STABILIZED_PARENT_PROCESS_MEMORY_USAGE, + parentMemoryMiB, + ], + [ + TranslationsBencher.METRIC_POST_GC_PARENT_PROCESS_MEMORY_USAGE, + postGCParentMiB, + ], + [ + TranslationsBencher.METRIC_PEAK_INFERENCE_PROCESS_MEMORY_USAGE, + peakInferenceMemoryMiB, + ], + [ + TranslationsBencher.METRIC_STABILIZED_INFERENCE_PROCESS_MEMORY_USAGE, + inferenceMemoryMiB, + ], + [ + TranslationsBencher.METRIC_POST_GC_INFERENCE_PROCESS_MEMORY_USAGE, + postGCInferenceMiB, + ], + ]); + + await cleanup(); + } + } + + /** + * Benchmarks speed by measuring engine init time, words per second, tokens per second, + * and total translation time across multiple runs. + * + * @param {object} options - The benchmark options. + * @param {string} options.page - The URL of the page to test. + * @param {TranslationsBencher.Journal} options.journal - The shared metrics journal. + * @param {string} options.sourceLanguage - The BCP-47 language tag for the source language. + * @param {string} options.targetLanguage - The BCP-47 language tag for the target language. + * @param {number} options.wordCount - The total word count of the page. + * @param {number} options.tokenCount - The total token count of the page. + * @param {number} options.speedBenchCount - The number of runs to perform for speed sampling. + * + * @returns {Promise} Resolves when speed benchmarking is complete. + */ + static async #benchmarkTranslationSpeed({ + page, + journal, + sourceLanguage, + targetLanguage, + wordCount, + tokenCount, + speedBenchCount, + }) { + for (let runNumber = 0; runNumber < speedBenchCount; ++runNumber) { + const { tab, cleanup, runInPage } = await loadTestPage({ + page, + endToEndTest: true, + languagePairs: [ + { fromLang: sourceLanguage, toLang: "en" }, + { fromLang: "en", toLang: targetLanguage }, + ], + prefs: [["browser.translations.logLevel", "Error"]], + contentEagerMode: true, + }); + + await TranslationsBencher.#injectFinalParagraphTranslatedObserver( + runInPage + ); + + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: false, icon: true }, + "The button is available." + ); + + await FullPageTranslationsTestUtils.openPanel({ + onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, + }); + + await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ + langTag: sourceLanguage, + }); + await FullPageTranslationsTestUtils.changeSelectedToLanguage({ + langTag: targetLanguage, + }); + + const engineReadyTimestampPromise = + TranslationsBencher.#getEngineReadyTimestampPromise(tab.linkedBrowser); + const translationCompleteTimestampPromise = + TranslationsBencher.#getTranslationCompleteTimestampPromise(runInPage); + + const translateButtonClickedTime = performance.now(); + await FullPageTranslationsTestUtils.clickTranslateButton(); + + const [engineReadyTime, translationCompleteTime] = await Promise.all([ + engineReadyTimestampPromise, + translationCompleteTimestampPromise, + ]); + + const initTimeMilliseconds = engineReadyTime - translateButtonClickedTime; + const translationTimeSeconds = millisecondsToSeconds( + translationCompleteTime - engineReadyTime + ); + const wordsPerSecond = wordCount / translationTimeSeconds; + const tokensPerSecond = tokenCount / translationTimeSeconds; + + journal.pushMetrics([ + [TranslationsBencher.METRIC_ENGINE_INIT_TIME, initTimeMilliseconds], + [TranslationsBencher.METRIC_WORDS_PER_SECOND, wordsPerSecond], + [TranslationsBencher.METRIC_TOKENS_PER_SECOND, tokensPerSecond], + [ + TranslationsBencher.METRIC_TOTAL_TRANSLATION_TIME, + translationTimeSeconds, + ], + ]); + + await cleanup(); + } + } + + /** + * Injects a mutation observer into the test page to detect when the final paragraph + * has been translated, and dispatch an event when that happens. This is a signal that + * we are nearing the end of translating, at which point we can wait for the pending + * request count to reduce to zero. + * + * @param {Function} runInPage - Runs a closure within the content context of the page. + * @returns {Promise} Resolves when the observer is injected. + */ + static async #injectFinalParagraphTranslatedObserver(runInPage) { + await runInPage(TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + const lastParagraph = getFinalParagraph(); + + if (!lastParagraph) { + throw new Error("Unable to find the final paragraph for observation."); + } + + const observer = new content.MutationObserver( + (_mutationsList, _observer) => { + content.document.dispatchEvent( + new CustomEvent("FinalParagraphTranslated") + ); + } + ); + + observer.observe(lastParagraph, { + childList: true, + }); + }); + } + + /** + * Returns a Promise that resolves with the timestamp when the Translations engine becomes ready. + * + * @param {Browser} browser - The browser hosting the translation. + * @returns {Promise} The timestamp when the engine is ready. + */ + static async #getEngineReadyTimestampPromise(browser) { + const { promise, resolve } = Promise.withResolvers(); + + function maybeGetTranslationStartTime(event) { + if ( + event.detail.reason === "isEngineReady" && + event.detail.actor.languageState.isEngineReady + ) { + browser.removeEventListener( + "TranslationsParent:LanguageState", + maybeGetTranslationStartTime + ); + resolve(performance.now()); + } + } + + browser.addEventListener( + "TranslationsParent:LanguageState", + maybeGetTranslationStartTime + ); + + return promise; + } + + /** + * Returns a Promise that resolves with the timestamp after the translation is complete. + * + * @param {Function} runInPage - A helper to run code on the test page. + * @returns {Promise} The timestamp when the translation is complete. + */ + static async #getTranslationCompleteTimestampPromise(runInPage) { + await runInPage(async ({ waitForCondition }) => { + // First, wait for the final paragraph to be translated. + await new Promise(resolve => { + content.document.addEventListener("FinalParagraphTranslated", resolve, { + once: true, + }); + }); + + const translationsChild = + content.windowGlobalChild.getActor("Translations"); + + if ( + translationsChild.translatedDoc?.hasPendingCallbackOnEventLoop() || + translationsChild.translatedDoc?.hasPendingTranslationRequests() || + translationsChild.translatedDoc?.isObservingAnyElementForContentIntersection() + ) { + // The final paragraph was translated, but it wasn't the final request, + // so we must still wait for every translation request to complete. + await waitForCondition( + () => + !translationsChild.translatedDoc?.hasPendingCallbackOnEventLoop() && + !translationsChild.translatedDoc?.hasPendingTranslationRequests() && + !translationsChild.translatedDoc?.isObservingAnyElementForContentIntersection(), + "Waiting for all pending translation requests to complete." + ); + } + }); + + return performance.now(); + } + + /** + * Returns the total memory used by both the parent process and the inference + * process in mebibytes (MiB). + * + * @returns {Promise<{ parentMemoryMiB: number, inferenceMemoryMiB: number }>} + * The total memory usage for each process in mebibytes. + */ + static async #getTotalMemoryUsageByProcess() { + const { parentInfo, inferenceInfo } = + await TranslationsBencher.#fetchProcessesInfo(); + return { + parentMemoryMiB: bytesToMebibytes(parentInfo.memory), + inferenceMemoryMiB: bytesToMebibytes(inferenceInfo.memory), + }; + } + + /** + * Returns the process info for both the parent process and inference process. + * + * @returns {Promise<{ parentInfo: { pid: number, memory: number, cpuTime: number, cpuCycleCount: number }, + * inferenceInfo: { pid: number, memory: number, cpuTime: number, cpuCycleCount: number } }>} + */ + static async #fetchProcessesInfo() { + let info = await ChromeUtils.requestProcInfo(); + + const parentInfo = { + pid: info.pid, + memory: info.memory, + cpuTime: info.cpuTime, + cpuCycleCount: info.cpuCycleCount, + }; + + let inferenceInfo = {}; + for (const child of info.children) { + // At the time of writing, there is only a single inference process. + // If we one day spawn multiple inference processes, this code will + // need to be revised. + if (child.type === "inference") { + inferenceInfo = { + pid: child.pid, + memory: child.memory, + cpuTime: child.cpuTime, + cpuCycleCount: child.cpuCycleCount, + }; + break; + } + } + + return { + parentInfo, + inferenceInfo, + }; + } +} + +/** + * A collection of shared functionality utilized by + * FullPageTranslationsTestUtils and SelectTranslationsTestUtils. + * + * Using functions from the aforementioned classes is preferred over + * using functions from this class directly. + */ +class SharedTranslationsTestUtils { + /** + * Asserts that the specified element currently has focus. + * + * @param {Element} element - The element to check for focus. + */ + static _assertHasFocus(element) { + is( + document.activeElement, + element, + `The element '${element.id}' should have focus.` + ); + } + + /** + * 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 + * @param {string} expectedId - The expected id that mainViewId is set to. + */ + static _assertPanelMainViewId(panel, expectedId) { + const mainViewId = panel.elements.multiview.getAttribute("mainViewId"); + is( + mainViewId, + expectedId, + "The mainViewId should match its expected value" + ); + } + + /** + * Asserts that the selected language in the menu matches the langTag or l10nId. + * + * @param {Element} menuList - The menu list element to check. + * @param {object} options - Options containing 'langTag' and 'l10nId' to assert against. + * @param {string} [options.langTag] - The BCP-47 language tag to match. + * @param {string} [options.l10nId] - The localization Id to match. + */ + static _assertSelectedLanguage(menuList, { langTag, l10nId }) { + ok( + menuList.label, + `The label for the menulist ${menuList.id} should not be empty.` + ); + if (langTag !== undefined) { + is( + menuList.value, + langTag, + `Expected ${menuList.id} selection to match '${langTag}'` + ); + } + if (l10nId !== undefined) { + is( + menuList.getAttribute("data-l10n-id"), + l10nId, + `Expected ${menuList.id} l10nId to match '${l10nId}'` + ); + } + } + + /** + * Asserts the visibility of the given elements based on the given expectations. + * + * @param {object} elements - An object containing the elements to be checked for visibility. + * @param {object} expectations - An object where each property corresponds to a property in elements, + * and its value is a boolean indicating whether the element should + * be visible (true) or hidden (false). + * @throws Throws if elements does not contain a property for each property in expectations. + */ + static _assertPanelElementVisibility(elements, expectations) { + const hidden = {}; + const visible = {}; + + for (const propertyName in expectations) { + ok( + elements.hasOwnProperty(propertyName), + `Expected panel elements to have property ${propertyName}` + ); + if (expectations[propertyName]) { + visible[propertyName] = elements[propertyName]; + } else { + hidden[propertyName] = elements[propertyName]; + } + } + + assertVisibility({ hidden, visible }); + } + + /** + * 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. + * + * Optionally executes a postEventAssertion function once the event occurs. + * + * @param {string} elementId - The Id of the element to wait for the event on. + * @param {string} eventName - The name of the event to wait for. + * @param {Function} callback - A callback function to execute immediately before waiting for the event. + * This is often used to trigger the event on the expected element. + * @param {Function|null} [postEventAssertion=null] - An optional callback function to execute after + * the event has occurred. + * @param {ChromeWindow} [win] + * @throws Throws if the element with the specified `elementId` does not exist. + * @returns {Promise} + */ + static async _waitForPopupEvent( + elementId, + eventName, + callback, + postEventAssertion = null, + win = window + ) { + const element = win.document.getElementById(elementId); + if (!element) { + throw new Error( + `Unable to find the ${elementId} element in the document.` + ); + } + const promise = BrowserTestUtils.waitForEvent(element, eventName); + await callback(); + info(`Waiting for the ${elementId} ${eventName} event`); + await promise; + if (postEventAssertion) { + await postEventAssertion(); + } + // Wait a single tick on the event loop. + await new Promise(resolve => setTimeout(resolve, 0)); + } +} + +/** + * A class containing test utility functions specific to testing full-page translations. + */ +class FullPageTranslationsTestUtils { + /** + * A collection of element visibility expectations for the default panel view. + */ + static #defaultViewVisibilityExpectations = { + cancelButton: true, + fromMenuList: true, + fromLabel: true, + header: true, + langSelection: true, + toMenuList: true, + toLabel: true, + translateButton: true, + }; + + /** + * 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 {object} expectations + * @param {string} expectations.langTag - A BCP-47 language tag. + * @param {boolean} expectations.checked - Whether the checkbox is expected to be checked. + * @param {boolean} expectations.disabled - Whether the menuitem is expected to be disabled. + */ + static async #assertCheckboxState( + dataL10nId, + { langTag = null, checked = true, disabled = false } + ) { + const menuItems = getAllByL10nId(dataL10nId); + for (const menuItem of menuItems) { + if (langTag) { + const { + args: { language }, + } = document.l10n.getAttributes(menuItem); + is( + language, + getIntlDisplayName(langTag), + `Should match expected language display name for ${dataL10nId}` + ); + } + is( + menuItem.disabled, + disabled, + `Should match expected disabled state for ${dataL10nId}` + ); + await waitForCondition( + () => menuItem.getAttribute("checked") === (checked ? "true" : "false"), + "Waiting for checkbox state" + ); + is( + menuItem.getAttribute("checked"), + checked ? "true" : "false", + `Should match expected checkbox state for ${dataL10nId}` + ); + } + } + + /** + * Asserts that the always-offer-translations checkbox matches the expected checked state. + * + * @param {boolean} checked + */ + static async assertIsAlwaysOfferTranslationsEnabled(checked) { + info( + `Checking that always-offer-translations is ${ + checked ? "enabled" : "disabled" + }` + ); + await FullPageTranslationsTestUtils.#assertCheckboxState( + "translations-panel-settings-always-offer-translation", + { checked } + ); + } + + /** + * Asserts that the always-translate-language checkbox matches the expected checked state. + * + * @param {string} langTag - A BCP-47 language tag + * @param {object} expectations + * @param {boolean} expectations.checked - Whether the checkbox is expected to be checked. + * @param {boolean} expectations.disabled - Whether the menuitem is expected to be disabled. + */ + static async assertIsAlwaysTranslateLanguage( + langTag, + { checked = true, disabled = false } + ) { + info( + `Checking that always-translate is ${ + checked ? "enabled" : "disabled" + } for "${langTag}"` + ); + await FullPageTranslationsTestUtils.#assertCheckboxState( + "translations-panel-settings-always-translate-language", + { langTag, checked, disabled } + ); + } + + /** + * Asserts that the never-translate-language checkbox matches the expected checked state. + * + * @param {string} langTag - A BCP-47 language tag + * @param {object} expectations + * @param {boolean} expectations.checked - Whether the checkbox is expected to be checked. + * @param {boolean} expectations.disabled - Whether the menuitem is expected to be disabled. + */ + static async assertIsNeverTranslateLanguage( + langTag, + { checked = true, disabled = false } + ) { + info( + `Checking that never-translate is ${ + checked ? "enabled" : "disabled" + } for "${langTag}"` + ); + await FullPageTranslationsTestUtils.#assertCheckboxState( + "translations-panel-settings-never-translate-language", + { langTag, checked, disabled } + ); + } + + /** + * Asserts that the never-translate-site checkbox matches the expected checked state. + * + * @param {string} url - The url of a website + * @param {object} expectations + * @param {boolean} expectations.checked - Whether the checkbox is expected to be checked. + * @param {boolean} expectations.disabled - Whether the menuitem is expected to be disabled. + */ + static async assertIsNeverTranslateSite( + url, + { checked = true, disabled = false } + ) { + info( + `Checking that never-translate is ${ + checked ? "enabled" : "disabled" + } for "${url}"` + ); + await FullPageTranslationsTestUtils.#assertCheckboxState( + "translations-panel-settings-never-translate-site", + { checked, disabled } + ); + } + + /** + * Asserts that the proper language tags are shown on the translations button. + * + * @param {string} fromLanguage - The BCP-47 language tag being translated from. + * @param {string} toLanguage - The BCP-47 language tag being translated into. + * @param {ChromeWindow} win + */ + static async assertLangTagIsShownOnTranslationsButton( + fromLanguage, + toLanguage, + win = window + ) { + info( + `Ensuring that the translations button displays the language tag "${toLanguage}"` + ); + const { button, locale } = + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: false, locale: true, icon: true }, + "The icon presents the locale.", + win + ); + is( + locale.innerText, + toLanguage.split("-")[0], + `The expected language tag "${toLanguage}" is shown.` + ); + is( + button.getAttribute("data-l10n-id"), + "urlbar-translations-button-translated" + ); + const fromLangDisplay = getIntlDisplayName(fromLanguage); + const toLangDisplay = getIntlDisplayName(toLanguage); + is( + button.getAttribute("data-l10n-args"), + `{"fromLanguage":"${fromLangDisplay}","toLanguage":"${toLangDisplay}"}` + ); + } + + /** + * Waits for all pending translation requests in the TranslationsDocument to complete. + * + * @param {Function} runInPage - A function run a closure in the content page. + */ + static async waitForAllPendingTranslationsToComplete(runInPage) { + await runInPage(async ({ waitForCondition }) => { + const translationsChild = + content.windowGlobalChild.getActor("Translations"); + + while ( + translationsChild.translatedDoc?.hasPendingTranslationRequests() || + translationsChild.translatedDoc?.hasPendingCallbackOnEventLoop() + ) { + await waitForCondition( + () => + !translationsChild.translatedDoc?.hasPendingTranslationRequests(), + "Waiting for all pending translation requests to complete." + ); + + await waitForCondition( + () => + !translationsChild.translatedDoc?.hasPendingCallbackOnEventLoop(), + "Waiting for pending event-loop callbacks to resolve in the TranslationsDocument." + ); + } + }); + } + + /** + * Waits until no elements are being observed for content intersection, + * indicating that every content-translation request has completed + * (barring future DOM mutations). + * + * @param {Function} runInPage – Executes an async closure in the content page. + */ + static async assertNoElementsAreObservedForContentIntersection(runInPage) { + await runInPage(async ({ waitForCondition }) => { + const translationsChild = + content.windowGlobalChild.getActor("Translations"); + + await waitForCondition( + () => + !translationsChild.translatedDoc?.isObservingAnyElementForContentIntersection(), + "Waiting until no elements are observed for content intersection." + ); + }); + } + + /** + * Waits until no elements are being observed for attribute intersection, + * indicating that every attribute-translation request has completed + * (barring future DOM mutations). + * + * @param {Function} runInPage – Executes an async closure in the content page. + */ + static async assertNoElementsAreObservedForAttributeIntersection(runInPage) { + await runInPage(async ({ waitForCondition }) => { + const translationsChild = + content.windowGlobalChild.getActor("Translations"); + + await waitForCondition( + () => + !translationsChild.translatedDoc?.isObservingAnyElementForAttributeIntersection(), + "Waiting until no elements are observed for attribute intersection." + ); + }); + } + + /** + * Waits until at least one element is being observed for content + * intersection. + * + * @param {Function} runInPage – Executes an async closure in the content page. + */ + static async assertAnyElementIsObservedForContentIntersection(runInPage) { + await runInPage(async ({ waitForCondition }) => { + const translationsChild = + content.windowGlobalChild.getActor("Translations"); + + await waitForCondition( + () => + translationsChild.translatedDoc?.isObservingAnyElementForContentIntersection(), + "Waiting until an element is observed for content intersection." + ); + }); + } + + /** + * Waits until at least one element is being observed for attribute + * intersection. + * + * @param {Function} runInPage – Executes an async closure in the content page. + */ + static async assertAnyElementIsObservedForAttributeIntersection(runInPage) { + await runInPage(async ({ waitForCondition }) => { + const translationsChild = + content.windowGlobalChild.getActor("Translations"); + + await waitForCondition( + () => + translationsChild.translatedDoc?.isObservingAnyElementForAttributeIntersection(), + "Waiting until an element is observed for attribute intersection." + ); + }); + } + + /** + * Waits for any translation request to initialize and become pending within the TranslationsDocument. + * + * @param {Function} runInPage - A function run a closure in the content page. + */ + static async waitForAnyRequestToInitialize(runInPage) { + await runInPage(async ({ waitForCondition }) => { + const translationsChild = + content.windowGlobalChild.getActor("Translations"); + + await waitForCondition( + () => translationsChild.translatedDoc?.hasPendingTranslationRequests(), + "Waiting for any translation request to initialize." + ); + }); + } + + /** + * Asserts that the Spanish test page H1 element's content has been translated into the target language. + * + * @param {object} options - The options for the assertion. + * + * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. + * @param {string} options.toLanguage - The BCP-47 language tag being translated into. + * @param {Function} options.runInPage - Allows running a closure in the content page. + * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. + * @param {string} [options.message] - An optional message to log to info. + */ + static async assertPageH1ContentIsTranslated({ + fromLanguage, + toLanguage, + runInPage, + endToEndTest = false, + message = null, + }) { + if (message) { + info(message); + } + info("Checking that the page header is translated"); + let callback; + if (endToEndTest) { + callback = async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is translated.", + getH1, + "Don Quixote de La Mancha" + ); + }; + } else { + callback = async (TranslationsTest, { fromLang, toLang }) => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is translated.", + getH1, + `DON QUIJOTE DE LA MANCHA [${fromLang} to ${toLang}]` + ); + }; + } + + await runInPage(callback, { fromLang: fromLanguage, toLang: toLanguage }); + } + + /** + * Asserts that the Spanish test page H1 element's content is not translated into the target language. + * + * @param {object} options - The options for the assertion. + * + * @param {Function} options.runInPage - Allows running a closure in the content page. + * @param {string} [options.message] - An optional message to log to info. + */ + static async assertPageH1ContentIsNotTranslated({ + runInPage, + message = null, + }) { + if (message) { + info(message); + } + + info("Checking that the page header is not translated"); + await runInPage(async TranslationsTest => { + const { getH1 } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1 is not translated and is in the original Spanish.", + getH1, + "Don Quijote de La Mancha" + ); + }); + } + + /** + * Asserts that the Spanish test page H1 element's title has been translated into the target language. + * + * @param {object} options - The options for the assertion. + * + * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. + * @param {string} options.toLanguage - The BCP-47 language tag being translated into. + * @param {Function} options.runInPage - Allows running a closure in the content page. + * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. + * @param {string} [options.message] - An optional message to log to info. + */ + static async assertPageH1TitleIsTranslated({ + fromLanguage, + toLanguage, + runInPage, + endToEndTest = false, + message = null, + }) { + if (message) { + info(message); + } + info("Checking that the page header's title attribute is translated"); + let callback; + if (endToEndTest) { + callback = async TranslationsTest => { + const { getH1Title } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1's title attribute is translated.", + getH1Title, + "This is the title of the page header" + ); + }; + } else { + callback = async (TranslationsTest, { fromLang, toLang }) => { + const { getH1Title } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1's title attribute is translated.", + getH1Title, + `ESTE ES EL TÍTULO DEL ENCABEZADO DE PÁGINA [${fromLang} to ${toLang}]` + ); + }; + } + + await runInPage(callback, { fromLang: fromLanguage, toLang: toLanguage }); + } + + /** + * Asserts that the Spanish test page H1 element's title attribute is not translated into the target language. + * + * @param {object} options - The options for the assertion. + * + * @param {Function} options.runInPage - Allows running a closure in the content page. + * @param {string} [options.message] - An optional message to log to info. + */ + static async assertPageH1TitleIsNotTranslated({ runInPage, message = null }) { + if (message) { + info(message); + } + + info("Checking that the page header's title is not translated"); + await runInPage(async TranslationsTest => { + const { getH1Title } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's H1's title is not translated and is in the original Spanish.", + getH1Title, + "Este es el título del encabezado de página" + ); + }); + } + + /** + * Asserts that the Spanish test page final

element has been translated into the target language. + * + * @param {object} options - The options for the assertion. + * + * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. + * @param {string} options.toLanguage - The BCP-47 language tag being translated into. + * @param {Function} options.runInPage - Allows running a closure in the content page. + * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. + * @param {string} [options.message] - An optional message to log to info. + */ + static async assertPageFinalParagraphContentIsTranslated({ + fromLanguage, + toLanguage, + runInPage, + endToEndTest = false, + message = null, + }) { + if (message) { + info(message); + } + info("Checking that the page's final paragraph is translated"); + let callback; + if (endToEndTest) { + callback = async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's final paragraph is translated.", + getFinalParagraph, + [ + // TODO (Bug 1967764) We need to investigate why some machines may produce + // a different translated output, given the same models and the same WASM binary. + "Well, even if you're more arms than those of the giant Briareo, you'll pay me.", + "For, though you're more arms than those of the giant Briareo, you'll pay me.", + ] + ); + }; + } else { + callback = async (TranslationsTest, { fromLang, toLang }) => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's final paragraph is translated.", + getFinalParagraph, + `— PUES, AUNQUE MOVÁIS MÁS BRAZOS QUE LOS DEL GIGANTE BRIAREO, ME LO HABÉIS DE PAGAR. [${fromLang} to ${toLang}]` + ); + }; + } + + await runInPage(callback, { fromLang: fromLanguage, toLang: toLanguage }); + } + + /** + * Asserts that the Spanish test page final

element is still in its original form. + * + * @param {object} options - The options for the assertion. + * + * @param {Function} options.runInPage - Allows running a closure in the content page. + * @param {string} [options.message] - An optional message to log to info. + */ + static async assertPageFinalParagraphContentIsNotTranslated({ + runInPage, + message = null, + }) { + if (message) { + info(message); + } + + info("Checking that the page's final paragraph is not translated"); + await runInPage(async TranslationsTest => { + const { getFinalParagraph } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The page's final paragraph is not translated and is in the original Spanish.", + getFinalParagraph, + "— Pues, aunque mováis más brazos que los del gigante Briareo, me lo habéis de pagar." + ); + }); + } + + /** + * Asserts that the Spanish test page final

element's title attribute has been translated into the target language. + * + * @param {object} options - The options for the assertion. + * + * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. + * @param {string} options.toLanguage - The BCP-47 language tag being translated into. + * @param {Function} options.runInPage - Allows running a closure in the content page. + * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. + * @param {string} [options.message] - An optional message to log to info. + */ + static async assertPageFinalParagraphTitleIsTranslated({ + fromLanguage, + toLanguage, + runInPage, + endToEndTest = false, + message = null, + }) { + if (message) { + info(message); + } + info("Checking that the final paragraph's title attribute is translated"); + let callback; + if (endToEndTest) { + callback = async TranslationsTest => { + const { getFinalParagraphTitle } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The final paragraph's title attribute is translated.", + getFinalParagraphTitle, + "This is the title of the final paragraph" + ); + }; + } else { + callback = async (TranslationsTest, { fromLang, toLang }) => { + const { getFinalParagraphTitle } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The final paragraph's title attribute is translated.", + getFinalParagraphTitle, + `ESTE ES EL TÍTULO DEL ÚLTIMO PÁRRAFO [${fromLang} to ${toLang}]` + ); + }; + } + + await runInPage(callback, { fromLang: fromLanguage, toLang: toLanguage }); + } + + /** + * Asserts that the Spanish test page final

element's title attribute is not translated into the target language. + * + * @param {object} options - The options for the assertion. + * + * @param {Function} options.runInPage - Allows running a closure in the content page. + * @param {string} [options.message] - An optional message to log to info. + */ + static async assertPageFinalParagraphTitleIsNotTranslated({ + runInPage, + message = null, + }) { + if (message) { + info(message); + } + + info( + "Checking that the final paragraph's title attribute is not translated" + ); + await runInPage(async TranslationsTest => { + const { getFinalParagraphTitle } = TranslationsTest.getSelectors(); + await TranslationsTest.assertTranslationResult( + "The final paragraph's title attribute is not translated and is in the original Spanish.", + getFinalParagraphTitle, + "Este es el título del último párrafo" + ); + }); + } + + /** + * + * @param {object} options - The options for the assertion. + * + * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. + * @param {string} options.toLanguage - The BCP-47 language tag being translated into. + * @param {Function} options.runInPage - Allows running a closure in the content page. + * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. + * @param {string} [options.message] - An optional message to log to info. + * @param {ChromeWindow} [options.win=window] - The window in which to perform the check (defaults to the current window). + */ + static async assertAllPageContentIsTranslated(options) { + await FullPageTranslationsTestUtils.assertPageH1ContentIsTranslated( + options + ); + await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsTranslated( + options + ); + + const { win, fromLanguage, toLanguage, runInPage } = options; + + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + fromLanguage, + toLanguage, + win + ); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + await FullPageTranslationsTestUtils.assertNoElementsAreObservedForContentIntersection( + runInPage + ); + } + + /** + * + * @param {object} options - The options for the assertion. + * + * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. + * @param {string} options.toLanguage - The BCP-47 language tag being translated into. + * @param {Function} options.runInPage - Allows running a closure in the content page. + * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. + * @param {string} [options.message] - An optional message to log to info. + * @param {ChromeWindow} [options.win=window] - The window in which to perform the check (defaults to the current window). + */ + static async assertOnlyIntersectingNodesAreTranslated(options) { + await FullPageTranslationsTestUtils.assertPageH1ContentIsTranslated( + options + ); + await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated(options); + + const { win, fromLanguage, toLanguage, runInPage } = options; + + await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( + fromLanguage, + toLanguage, + win + ); + + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsNotTranslated( + options + ); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + options + ); + + await FullPageTranslationsTestUtils.assertAnyElementIsObservedForContentIntersection( + runInPage + ); + + await FullPageTranslationsTestUtils.assertAnyElementIsObservedForAttributeIntersection( + runInPage + ); + } + + /** + * Asserts that the Spanish test page is not translated by checking + * that the H1 element is still in its original Spanish form. + * + * @param {Function} runInPage - Allows running a closure in the content page. + * @param {string} message - An optional message to log to info. + */ + static async assertPageIsNotTranslated(runInPage, message = null) { + if (message) { + info(message); + } + + info("Ensuring that no translation requests are pending."); + await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( + runInPage + ); + + info("Checking that the page is not translated"); + + await FullPageTranslationsTestUtils.assertPageH1ContentIsNotTranslated({ + runInPage, + message, + }); + + await FullPageTranslationsTestUtils.assertPageH1TitleIsNotTranslated({ + runInPage, + message, + }); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsNotTranslated( + { + runInPage, + message, + } + ); + + await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( + { + runInPage, + message, + } + ); + } + + /** + * Asserts that for each provided expectation, the visible state of the corresponding + * element in FullPageTranslationsPanel.elements both exists and matches the visibility expectation. + * + * @param {object} expectations + * A list of expectations for the visibility of any subset of FullPageTranslationsPanel.elements + */ + static #assertPanelElementVisibility(expectations = {}) { + SharedTranslationsTestUtils._assertPanelElementVisibility( + FullPageTranslationsPanel.elements, + { + cancelButton: false, + changeSourceLanguageButton: false, + dismissErrorButton: false, + error: false, + errorMessage: false, + errorMessageHint: false, + errorHintAction: false, + fromLabel: false, + fromMenuList: false, + fromMenuPopup: false, + header: false, + intro: false, + introLearnMoreLink: false, + langSelection: false, + restoreButton: false, + toLabel: false, + toMenuList: false, + toMenuPopup: false, + translateButton: false, + unsupportedHeader: false, + unsupportedHint: false, + unsupportedLearnMoreLink: false, + // Overwrite any of the above defaults with the passed in expectations. + ...expectations, + } + ); + } + + /** + * Asserts that the FullPageTranslationsPanel header has the expected l10nId. + * + * @param {string} l10nId - The expected data-l10n-id of the header. + */ + static #assertPanelHeaderL10nId(l10nId) { + const { header } = FullPageTranslationsPanel.elements; + SharedTranslationsTestUtils._assertL10nId(header, l10nId); + } + + /** + * Asserts that the FullPageTranslationsPanel error has the expected l10nId. + * + * @param {string} l10nId - The expected data-l10n-id of the error. + */ + static #assertPanelErrorL10nId(l10nId) { + const { errorMessage } = FullPageTranslationsPanel.elements; + SharedTranslationsTestUtils._assertL10nId(errorMessage, l10nId); + } + + /** + * Asserts that the mainViewId of the panel matches the given string. + * + * @param {string} expectedId + */ + static #assertPanelMainViewId(expectedId) { + SharedTranslationsTestUtils._assertPanelMainViewId( + FullPageTranslationsPanel, + expectedId + ); + + const panelView = document.getElementById(expectedId); + const label = document.getElementById( + panelView.getAttribute("aria-labelledby") + ); + ok(label, "The a11y label for the panel view can be found."); + assertVisibility({ visible: { label } }); + } + + /** + * Asserts that panel element visibility matches the default panel view. + */ + static assertPanelViewDefault() { + info("Checking that the panel shows the default view"); + FullPageTranslationsTestUtils.#assertPanelMainViewId( + "full-page-translations-panel-view-default" + ); + FullPageTranslationsTestUtils.#assertPanelElementVisibility({ + ...FullPageTranslationsTestUtils.#defaultViewVisibilityExpectations, + }); + FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( + "translations-panel-header" + ); + } + + /** + * Asserts that panel element visibility matches the initialization-failure view. + */ + static assertPanelViewInitFailure() { + info("Checking that the panel shows the default view"); + const { translateButton } = FullPageTranslationsPanel.elements; + FullPageTranslationsTestUtils.#assertPanelMainViewId( + "full-page-translations-panel-view-default" + ); + FullPageTranslationsTestUtils.#assertPanelElementVisibility({ + cancelButton: true, + error: true, + errorMessage: true, + errorMessageHint: true, + errorHintAction: true, + header: true, + translateButton: true, + }); + is( + translateButton.disabled, + true, + "The translate button should be disabled." + ); + FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( + "translations-panel-header" + ); + } + + /** + * Asserts that panel element visibility matches the panel error view. + */ + static assertPanelViewError() { + info("Checking that the panel shows the error view"); + FullPageTranslationsTestUtils.#assertPanelMainViewId( + "full-page-translations-panel-view-default" + ); + FullPageTranslationsTestUtils.#assertPanelElementVisibility({ + error: true, + errorMessage: true, + ...FullPageTranslationsTestUtils.#defaultViewVisibilityExpectations, + }); + FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( + "translations-panel-header" + ); + FullPageTranslationsTestUtils.#assertPanelErrorL10nId( + "translations-panel-error-translating" + ); + } + + /** + * Asserts that the panel element visibility matches the panel loading view. + */ + static assertPanelViewLoading() { + info("Checking that the panel shows the loading view"); + FullPageTranslationsTestUtils.assertPanelViewDefault(); + const loadingButton = getByL10nId( + "translations-panel-translate-button-loading" + ); + ok(loadingButton, "The loading button is present"); + ok(loadingButton.disabled, "The loading button is disabled"); + } + + /** + * Asserts that panel element visibility matches the panel intro view. + */ + static assertPanelViewIntro() { + info("Checking that the panel shows the intro view"); + FullPageTranslationsTestUtils.#assertPanelMainViewId( + "full-page-translations-panel-view-default" + ); + FullPageTranslationsTestUtils.#assertPanelElementVisibility({ + intro: true, + introLearnMoreLink: true, + ...FullPageTranslationsTestUtils.#defaultViewVisibilityExpectations, + }); + FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( + "translations-panel-intro-header" + ); + } + + /** + * Asserts that panel element visibility matches the panel intro error view. + */ + static assertPanelViewIntroError() { + info("Checking that the panel shows the intro error view"); + FullPageTranslationsTestUtils.#assertPanelMainViewId( + "full-page-translations-panel-view-default" + ); + FullPageTranslationsTestUtils.#assertPanelElementVisibility({ + error: true, + intro: true, + introLearnMoreLink: true, + ...FullPageTranslationsTestUtils.#defaultViewVisibilityExpectations, + }); + FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( + "translations-panel-intro-header" + ); + } + + /** + * Asserts that panel element visibility matches the panel revisit view. + */ + static assertPanelViewRevisit() { + info("Checking that the panel shows the revisit view"); + FullPageTranslationsTestUtils.#assertPanelMainViewId( + "full-page-translations-panel-view-default" + ); + FullPageTranslationsTestUtils.#assertPanelElementVisibility({ + header: true, + langSelection: true, + restoreButton: true, + toLabel: true, + toMenuList: true, + translateButton: true, + }); + FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( + "translations-panel-revisit-header" + ); + } + + /** + * Asserts that panel element visibility matches the panel unsupported language view. + */ + static assertPanelViewUnsupportedLanguage() { + info("Checking that the panel shows the unsupported-language view"); + FullPageTranslationsTestUtils.#assertPanelMainViewId( + "full-page-translations-panel-view-unsupported-language" + ); + FullPageTranslationsTestUtils.#assertPanelElementVisibility({ + changeSourceLanguageButton: true, + dismissErrorButton: true, + unsupportedHeader: true, + unsupportedHint: true, + unsupportedLearnMoreLink: true, + }); + } + + /** + * Asserts that the selected from-language matches the provided language tag. + * + * @param {object} options - Options containing 'langTag' and 'l10nId' to assert against. + * @param {string} [options.langTag] - The BCP-47 language tag to match. + * @param {string} [options.l10nId] - The localization Id to match. + * @param {ChromeWindow} [options.win] + * - An optional ChromeWindow, for multi-window tests. + */ + static assertSelectedFromLanguage({ langTag, l10nId, win = window }) { + const { fromMenuList } = win.FullPageTranslationsPanel.elements; + SharedTranslationsTestUtils._assertSelectedLanguage(fromMenuList, { + langTag, + l10nId, + }); + } + + /** + * Asserts that the selected to-language matches the provided language tag. + * + * @param {object} options - Options containing 'langTag' and 'l10nId' to assert against. + * @param {string} [options.langTag] - The BCP-47 language tag to match. + * @param {string} [options.l10nId] - The localization Id to match. + * @param {ChromeWindow} [options.win] + * - An optional ChromeWindow, for multi-window tests. + */ + static assertSelectedToLanguage({ langTag, l10nId, win = window }) { + const { toMenuList } = win.FullPageTranslationsPanel.elements; + SharedTranslationsTestUtils._assertSelectedLanguage(toMenuList, { + langTag, + l10nId, + }); + } + + /** + * Assert some property about the translations button. + * + * @param {Record} visibleAssertions + * @param {string} message The message for the assertion. + * @param {ChromeWindow} [win] + * @returns {HTMLElement} + */ + static async assertTranslationsButton( + visibleAssertions, + message, + win = window + ) { + const elements = { + button: win.document.getElementById("translations-button"), + icon: win.document.getElementById("translations-button-icon"), + circleArrows: win.document.getElementById( + "translations-button-circle-arrows" + ), + locale: win.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 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; + } + + /** + * Simulates the effect of clicking the always-offer-translations menuitem. + * Requires that the settings menu of the translations panel is open, + * otherwise the test will fail. + */ + static async clickAlwaysOfferTranslations() { + logAction(); + await FullPageTranslationsTestUtils.#clickSettingsMenuItemByL10nId( + "translations-panel-settings-always-offer-translation" + ); + } + + /** + * 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. + */ + static async clickAlwaysTranslateLanguage({ + downloadHandler = null, + pivotTranslation = false, + } = {}) { + logAction(); + await FullPageTranslationsTestUtils.#clickSettingsMenuItemByL10nId( + "translations-panel-settings-always-translate-language" + ); + if (downloadHandler) { + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator." + ); + await downloadHandler(pivotTranslation ? 2 : 1); + } + } + + /** + * Simulates clicking the cancel button. + */ + static async clickCancelButton() { + logAction(); + const { cancelButton } = FullPageTranslationsPanel.elements; + assertVisibility({ visible: { cancelButton } }); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + () => { + click(cancelButton, "Clicking the cancel button"); + } + ); + } + + /** + * Simulates clicking the change-source-language button. + * + * @param {object} config + * @param {boolean} config.intro + * - True if the intro view should be expected + * False if the default view should be expected + */ + static async clickChangeSourceLanguageButton({ intro = false } = {}) { + logAction(); + const { changeSourceLanguageButton } = FullPageTranslationsPanel.elements; + assertVisibility({ visible: { changeSourceLanguageButton } }); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + () => { + click( + changeSourceLanguageButton, + "Click the change-source-language button" + ); + }, + intro + ? FullPageTranslationsTestUtils.assertPanelViewIntro + : FullPageTranslationsTestUtils.assertPanelViewDefault + ); + } + + /** + * Simulates clicking the dismiss-error button. + */ + static async clickDismissErrorButton() { + logAction(); + const { dismissErrorButton } = FullPageTranslationsPanel.elements; + assertVisibility({ visible: { dismissErrorButton } }); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + () => { + click(dismissErrorButton, "Click the dismiss-error button"); + } + ); + } + + /** + * Simulates the effect of clicking the manage-languages menuitem. + * Requires that the settings menu of the translations panel is open, + * otherwise the test will fail. + */ + static async clickManageLanguages() { + logAction(); + await FullPageTranslationsTestUtils.#clickSettingsMenuItemByL10nId( + "translations-panel-settings-manage-languages" + ); + } + + /** + * 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. + */ + static async clickNeverTranslateLanguage() { + logAction(); + await FullPageTranslationsTestUtils.#clickSettingsMenuItemByL10nId( + "translations-panel-settings-never-translate-language" + ); + } + + /** + * 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. + */ + static async clickNeverTranslateSite() { + logAction(); + await FullPageTranslationsTestUtils.#clickSettingsMenuItemByL10nId( + "translations-panel-settings-never-translate-site" + ); + } + + /** + * Simulates clicking the restore-page button. + * + * @param {ChromeWindow} [win] + * - An optional ChromeWindow, for multi-window tests. + */ + static async clickRestoreButton(win = window) { + logAction(); + const { restoreButton } = win.FullPageTranslationsPanel.elements; + assertVisibility({ visible: { restoreButton } }); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + () => { + click(restoreButton, "Click the restore-page button"); + } + ); + } + + /* + * Simulates the effect of toggling a menu item in the translations panel + * settings menu. Requires that the settings menu is currently open, + * otherwise the test will fail. + */ + static async #clickSettingsMenuItemByL10nId(l10nId) { + info(`Toggling the "${l10nId}" settings menu item.`); + click(getByL10nId(l10nId), `Clicking the "${l10nId}" settings menu item.`); + await closeFullPagePanelSettingsMenuIfOpen(); + } + + /** + * Simulates clicking the translate 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.onOpenPanel + * - A function to run as soon as the panel opens. + * @param {ChromeWindow} [config.win] + * - An optional ChromeWindow, for multi-window tests. + */ + static async clickTranslateButton({ + downloadHandler = null, + pivotTranslation = false, + onOpenPanel = null, + win = window, + } = {}) { + logAction(); + const { translateButton } = win.FullPageTranslationsPanel.elements; + assertVisibility({ visible: { translateButton } }); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + () => { + click(translateButton); + }, + null /* postEventAssertion */, + win + ); + + let panelOpenCallbackPromise; + if (onOpenPanel) { + panelOpenCallbackPromise = + FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + () => {}, + onOpenPanel + ); + } + + if (downloadHandler) { + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true, circleArrows: true, locale: false, icon: true }, + "The icon presents the loading indicator.", + win + ); + await downloadHandler(pivotTranslation ? 2 : 1); + } + + await panelOpenCallbackPromise; + } + + /** + * Opens the translations panel. + * + * @param {object} config + * @param {Function} config.onOpenPanel + * - A function to run as soon as the panel opens. + * @param {boolean} config.openFromAppMenu + * - Open the panel from the app menu. If false, uses the translations button. + * @param {boolean} config.openWithKeyboard + * - Open the panel by synthesizing the keyboard. If false, synthesizes the mouse. + * @param {string} [config.expectedFromLanguage] - The expected from-language tag. + * @param {string} [config.expectedToLanguage] - The expected to-language tag. + * @param {ChromeWindow} [config.win] + * - An optional window for multi-window tests. + */ + static async openPanel({ + onOpenPanel = null, + openFromAppMenu = false, + openWithKeyboard = false, + expectedFromLanguage = undefined, + expectedToLanguage = undefined, + win = window, + }) { + logAction(); + await closeAllOpenPanelsAndMenus(win); + if (openFromAppMenu) { + await FullPageTranslationsTestUtils.#openPanelViaAppMenu({ + win, + onOpenPanel, + openWithKeyboard, + }); + } else { + await FullPageTranslationsTestUtils.#openPanelViaTranslationsButton({ + win, + onOpenPanel, + openWithKeyboard, + }); + } + if (expectedFromLanguage !== undefined) { + FullPageTranslationsTestUtils.assertSelectedFromLanguage({ + win, + langTag: expectedFromLanguage, + }); + } + if (expectedToLanguage !== undefined) { + FullPageTranslationsTestUtils.assertSelectedToLanguage({ + win, + langTag: expectedToLanguage, + }); + } + } + + /** + * Opens the translations panel via the app menu. + * + * @param {object} config + * @param {Function} config.onOpenPanel + * - A function to run as soon as the panel opens. + * @param {boolean} config.openWithKeyboard + * - Open the panel by synthesizing the keyboard. If false, synthesizes the mouse. + * @param {ChromeWindow} [config.win] + */ + static async #openPanelViaAppMenu({ + onOpenPanel = null, + openWithKeyboard = false, + win = window, + }) { + logAction(); + const appMenuButton = getById("PanelUI-menu-button", win.document); + if (openWithKeyboard) { + hitEnterKey(appMenuButton, "Opening the app-menu button with keyboard"); + } else { + click(appMenuButton, "Opening the app-menu button"); + } + await BrowserTestUtils.waitForEvent(win.PanelUI.mainView, "ViewShown"); + + const translateSiteButton = getById( + "appMenu-translate-button", + win.document + ); + + is( + translateSiteButton.disabled, + false, + "The app-menu translate button should be enabled" + ); + + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + () => { + if (openWithKeyboard) { + hitEnterKey(translateSiteButton, "Opening the popup with keyboard"); + } else { + click(translateSiteButton, "Opening the popup"); + } + }, + onOpenPanel + ); + } + + /** + * Opens the translations panel via the translations button. + * + * @param {object} config + * @param {Function} config.onOpenPanel + * - A function to run as soon as the panel opens. + * @param {boolean} config.openWithKeyboard + * - Open the panel by synthesizing the keyboard. If false, synthesizes the mouse. + * @param {ChromeWindow} [config.win] + */ + static async #openPanelViaTranslationsButton({ + onOpenPanel = null, + openWithKeyboard = false, + win = window, + }) { + logAction(); + const { button } = + await FullPageTranslationsTestUtils.assertTranslationsButton( + { button: true }, + "The translations button is visible.", + win + ); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + () => { + if (openWithKeyboard) { + hitEnterKey(button, "Opening the popup with keyboard"); + } else { + click(button, "Opening the popup"); + } + }, + onOpenPanel, + win + ); + } + + /** + * Opens the translations panel settings menu. + * Requires that the translations panel is already open. + */ + static async openTranslationsSettingsMenu() { + logAction(); + const gearIcons = getAllByL10nId("translations-panel-settings-button"); + for (const gearIcon of gearIcons) { + if (BrowserTestUtils.isHidden(gearIcon)) { + continue; + } + click(gearIcon, "Open the settings menu"); + info("Waiting for settings menu to open."); + const manageLanguages = await waitForCondition(() => + maybeGetByL10nId("translations-panel-settings-manage-languages") + ); + ok( + manageLanguages, + "The manage languages item should be visible in the settings menu." + ); + return; + } + } + + /** + * Changes the selected language by opening the dropdown menu for each provided language tag. + * + * @param {string} langTag - The BCP-47 language tag to select from the dropdown menu. + * @param {object} elements - Elements involved in the dropdown language selection process. + * @param {Element} elements.menuList - The element that triggers the dropdown menu. + * @param {Element} elements.menuPopup - The dropdown menu element containing selectable languages. + * @param {ChromeWindow} [win] + * - An optional ChromeWindow, for multi-window tests. + * + * @returns {Promise} + */ + static async #changeSelectedLanguage(langTag, elements, win = window) { + const { menuList, menuPopup } = elements; + + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + () => click(menuList), + null /* postEventAssertion */, + win + ); + + const menuItem = menuPopup.querySelector(`[value="${langTag}"]`); + await FullPageTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + () => { + click(menuItem); + // Synthesizing a click on the menuitem isn't closing the popup + // as a click normally would, so this tab keypress is added to + // ensure the popup closes. + EventUtils.synthesizeKey("KEY_Tab", {}, win); + }, + null /* postEventAssertion */, + win + ); + } + + /** + * Switches the selected from-language to the provided language tag. + * + * @param {object} options + * @param {string} options.langTag - A BCP-47 language tag. + * @param {ChromeWindow} [options.win] + * - An optional ChromeWindow, for multi-window tests. + */ + static async changeSelectedFromLanguage({ langTag, win = window }) { + logAction(langTag); + const { fromMenuList: menuList, fromMenuPopup: menuPopup } = + win.FullPageTranslationsPanel.elements; + await FullPageTranslationsTestUtils.#changeSelectedLanguage( + langTag, + { + menuList, + menuPopup, + }, + win + ); + } + + /** + * Switches the selected to-language to the provided language tag. + * + * @param {object} options + * @param {string} options.langTag - A BCP-47 language tag. + * @param {ChromeWindow} [options.win] + * - An optional ChromeWindow, for multi-window tests. + */ + static async changeSelectedToLanguage({ langTag, win = window }) { + logAction(langTag); + const { toMenuList: menuList, toMenuPopup: menuPopup } = + win.FullPageTranslationsPanel.elements; + await FullPageTranslationsTestUtils.#changeSelectedLanguage( + langTag, + { + menuList, + menuPopup, + }, + win + ); + } + + /** + * 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 + * @param {Function} postEventAssertion + * An optional assertion to be made immediately after the event occurs. + * @param {ChromeWindow} [win] + * @returns {Promise} + */ + static async waitForPanelPopupEvent( + eventName, + callback, + postEventAssertion = null, + win = window + ) { + // De-lazify the panel elements. + win.FullPageTranslationsPanel.elements; + await SharedTranslationsTestUtils._waitForPopupEvent( + "full-page-translations-panel", + eventName, + callback, + postEventAssertion, + win + ); + } +} + +/** + * A class containing test utility functions specific to testing select translations. + */ +class SelectTranslationsTestUtils { + /** + * Opens the context menu then asserts properties of the translate-selection item in the context menu. + * + * @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. + * + * @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

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. + * @param {boolean} options.selectFrenchSentence - Selects a French sentence. + * @param {boolean} options.selectEnglishSentence - Selects an English sentence. + * @param {boolean} options.selectSpanishSentence - Selects a Spanish sentence. + * @param {boolean} options.openAtFrenchSection - Opens the context menu at the section of French text. + * @param {boolean} options.openAtEnglishSection - Opens the context menu at the section of English text. + * @param {boolean} options.openAtSpanishSection - Opens the context menu at the section of Spanish text. + * @param {boolean} options.openAtFrenchSentence - Opens the context menu at a French sentence. + * @param {boolean} options.openAtEnglishSentence - Opens the context menu at an English sentence. + * @param {boolean} options.openAtSpanishSentence - Opens the context menu at a Spanish sentence. + * @param {boolean} options.openAtFrenchHyperlink - Opens the context menu at a hyperlinked French text. + * @param {boolean} options.openAtEnglishHyperlink - Opens the context menu at a hyperlinked English text. + * @param {boolean} options.openAtSpanishHyperlink - Opens the context menu at a hyperlinked Spanish text. + * @param {boolean} options.openAtURLHyperlink - Opens the context menu at a hyperlinked URL text. + * @param {string} [message] - A message to log to info. + * @throws Throws an error if the properties of the translate-selection item do not match the expected options. + */ + static async assertContextMenuTranslateSelectionItem( + runInPage, + { + expectMenuItemVisible, + expectedTargetLanguage, + selectH1, + selectPdfSpan, + selectFrenchSection, + selectEnglishSection, + selectSpanishSection, + selectFrenchSentence, + selectEnglishSentence, + selectSpanishSentence, + openAtH1, + openAtPdfSpan, + openAtFrenchSection, + openAtEnglishSection, + openAtSpanishSection, + openAtFrenchSentence, + openAtEnglishSentence, + openAtSpanishSentence, + openAtFrenchHyperlink, + openAtEnglishHyperlink, + openAtSpanishHyperlink, + openAtURLHyperlink, + }, + message + ) { + logAction(); + + if (message) { + info(message); + } + + await closeAllOpenPanelsAndMenus(); + + await SelectTranslationsTestUtils.openContextMenu(runInPage, { + expectMenuItemVisible, + expectedTargetLanguage, + selectH1, + selectPdfSpan, + selectFrenchSection, + selectEnglishSection, + selectSpanishSection, + selectFrenchSentence, + selectEnglishSentence, + selectSpanishSentence, + openAtH1, + openAtPdfSpan, + openAtFrenchSection, + openAtEnglishSection, + openAtSpanishSection, + openAtFrenchSentence, + openAtEnglishSentence, + openAtSpanishSentence, + openAtFrenchHyperlink, + openAtEnglishHyperlink, + openAtSpanishHyperlink, + openAtURLHyperlink, + }); + + const menuItem = maybeGetById( + "context-translate-selection", + /* ensureIsVisible */ false + ); + + if (expectMenuItemVisible !== undefined) { + const visibility = expectMenuItemVisible ? "visible" : "hidden"; + assertVisibility({ [visibility]: { menuItem } }); + } + + if (expectMenuItemVisible === true) { + if (expectedTargetLanguage) { + // Target language expected, check for the data-l10n-id with a `{$language}` argument. + const expectedL10nId = + selectH1 || + selectPdfSpan || + selectFrenchSection || + selectEnglishSection || + selectSpanishSection || + selectFrenchSentence || + selectEnglishSentence || + selectSpanishSentence + ? "main-context-menu-translate-selection-to-language" + : "main-context-menu-translate-link-text-to-language"; + + await waitForCondition( + () => + TranslationsUtils.langTagsMatch( + menuItem.getAttribute("target-language"), + expectedTargetLanguage + ), + `Waiting for translate-selection context menu item to match the expected target language ${expectedTargetLanguage}` + ); + await waitForCondition( + () => menuItem.getAttribute("data-l10n-id") === expectedL10nId, + `Waiting for translate-selection context menu item to have the correct data-l10n-id '${expectedL10nId}` + ); + + if (Services.locale.appLocaleAsBCP47 === "en-US") { + // We only want to test the localized name in CI if the current app locale is the default (en-US). + const expectedLanguageDisplayName = getIntlDisplayName( + expectedTargetLanguage + ); + await waitForCondition(() => { + const l10nArgs = JSON.parse( + menuItem.getAttribute("data-l10n-args") + ); + return l10nArgs.language === expectedLanguageDisplayName; + }, `Waiting for translate-selection context menu item to have the correct data-l10n-args '${expectedLanguageDisplayName}`); + } + } else { + // No target language expected, check for the data-l10n-id that has no `{$language}` argument. + const expectedL10nId = + selectH1 || + selectPdfSpan || + selectFrenchSection || + selectEnglishSection || + selectSpanishSection || + selectFrenchSentence || + selectEnglishSentence || + selectSpanishSentence + ? "main-context-menu-translate-selection" + : "main-context-menu-translate-link-text"; + await waitForCondition( + () => !menuItem.getAttribute("target-language"), + "Waiting for translate-selection context menu item to remove its target-language attribute." + ); + await waitForCondition( + () => menuItem.getAttribute("data-l10n-id") === expectedL10nId, + `Waiting for translate-selection context menu item to have the correct data-l10n-id '${expectedL10nId}` + ); + } + } + } + + /** + * Tests that the context menu displays the expected target language for translation based on + * the provided configurations. + * + * @param {object} options - Options for configuring the test environment and expected language behavior. + * @param {Array.} options.runInPage - A content-exposed function to run within the context of the page. + * @param {Array.} [options.systemLocales=[]] - Locales to mock as system locales. + * @param {Array.} [options.appLocales=[]] - Locales to mock as application locales. + * @param {Array.} [options.webLanguages=[]] - Languages to mock as web languages. + * @param {string} options.expectedTargetLanguage - The expected target language for the translate-selection item. + */ + static async testContextMenuItemWithLocales({ + runInPage, + systemLocales = [], + appLocales = [], + webLanguages = [], + expectedTargetLanguage, + }) { + const cleanupLocales = await mockLocales({ + systemLocales, + appLocales, + webLanguages, + }); + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + { + selectSpanishSentence: true, + openAtSpanishSentence: true, + expectMenuItemVisible: true, + expectedTargetLanguage, + }, + `The translate-selection context menu item should match the expected target language '${expectedTargetLanguage}'` + ); + + await closeAllOpenPanelsAndMenus(); + await cleanupLocales(); + } + + /** + * Asserts that for each provided expectation, the visible state of the corresponding + * element in FullPageTranslationsPanel.elements both exists and matches the visibility expectation. + * + * @param {object} expectations + * A list of expectations for the visibility of any subset of SelectTranslationsPanel.elements + */ + static #assertPanelElementVisibility(expectations = {}) { + SharedTranslationsTestUtils._assertPanelElementVisibility( + SelectTranslationsPanel.elements, + { + 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, + } + ); + } + + /** + * 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", + false, + event => event.detail.phase === phase + ); + } + } + + /** + * Asserts that the SelectTranslationsPanel UI matches the expected + * state when the panel has completed its translation. + */ + 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({ + betaIcon: true, + copyButton: true, + doneButtonPrimary: true, + fromLabel: true, + fromMenuList: true, + header: true, + mainContent: true, + settingsButton: true, + textArea: true, + toLabel: true, + toMenuList: true, + translateFullPageButton: !( + isFullPageTranslationsRestrictedForPage || + isFullPageTranslationsActive() + ), + }); + SelectTranslationsTestUtils.#assertConditionalUIEnabled({ + copyButton: true, + doneButtonPrimary: true, + textArea: true, + translateFullPageButton: !( + sameLanguageSelected || + isFullPageTranslationsRestrictedForPage || + isFullPageTranslationsActive() + ), + }); + + 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(); + await SelectTranslationsTestUtils.#assertPanelTextAreaOverflow(); + + let footerButtons; + if ( + sameLanguageSelected || + isFullPageTranslationsRestrictedForPage || + isFullPageTranslationsActive() + ) { + 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, + initFailureMessageBar, + 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); + const ariaDescribedBy = tryAgainButton.getAttribute("aria-describedby"); + ok(ariaDescribedBy.includes(initFailureMessageBar.id)); + } + + /** + * 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); + const ariaDescribedBy = tryAgainButton.getAttribute("aria-describedby"); + ok(ariaDescribedBy.includes(translationFailureMessageBar.id)); + } + + static #assertPanelTextAreaDirection(langTag = null) { + const expectedTextDirection = langTag + ? Services.intl.getScriptDirection(langTag) + : null; + const { textArea } = SelectTranslationsPanel.elements; + const actualTextDirection = textArea.getAttribute("dir"); + + is( + actualTextDirection, + expectedTextDirection, + `The text direction should be ${expectedTextDirection}` + ); + } + + /** + * 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 async #assertPanelTextAreaOverflow() { + const { textArea } = SelectTranslationsPanel.elements; + 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); + + info("Ensuring that the textarea cursor is at the beginning."); + await waitForCondition( + () => textArea.selectionStart === 0 && textArea.selectionEnd === 0 + ); + } + } + + /** + * Asserts that the SelectTranslationsPanel translated text area is + * the correct height for the length of the translated text. + */ + static #assertPanelTextAreaHeight() { + const { textArea } = SelectTranslationsPanel.elements; + + if ( + SelectTranslationsPanel.getSourceText().length < + SelectTranslationsPanel.textLengthThreshold + ) { + is( + textArea.style.height, + SelectTranslationsPanel.shortTextHeight, + "The panel text area should have the short-text height" + ); + } else { + is( + textArea.style.height, + SelectTranslationsPanel.longTextHeight, + "The panel text area should have the long-text height" + ); + } + } + + /** + * Asserts that the SelectTranslationsPanel UI matches the expected + * state when the panel is actively translating text. + */ + 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({ + betaIcon: true, + copyButton: true, + doneButtonPrimary: true, + fromLabel: true, + fromMenuList: true, + header: true, + mainContent: true, + settingsButton: true, + textArea: true, + toLabel: true, + toMenuList: true, + translateFullPageButton: !( + isFullPageTranslationsRestrictedForPage || + isFullPageTranslationsActive() + ), + }); + SelectTranslationsTestUtils.#assertPanelHasTranslatingPlaceholder(); + } + + /** + * Asserts that the SelectTranslationsPanel UI contains the + * translating placeholder text. + */ + static async #assertPanelHasTranslatingPlaceholder() { + 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, + "Active translation text area should have the translating placeholder." + ); + SelectTranslationsTestUtils.#assertPanelTextAreaDirection(); + SelectTranslationsTestUtils.#assertConditionalUIEnabled({ + textArea: true, + copyButton: false, + doneButtonPrimary: true, + translateFullPageButton: + fromMenuList.value !== toMenuList.value && + !isFullPageTranslationsRestrictedForPage && + !isFullPageTranslationsActive(), + }); + } + + /** + * Asserts that the SelectTranslationsPanel UI contains the + * translated text. + */ + static #assertPanelHasTranslatedText() { + const { textArea, fromMenuList, toMenuList } = + 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 && + !isFullPageTranslationsActive(), + }); + + 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), + `Translated text should match ${fromLanguage} to ${toLanguage}` + ); + is( + SelectTranslationsPanel.getSourceText().length, + SelectTranslationsPanel.getTranslatedText().length - + translatedSuffix.length, + "Expected translated text length to correspond to the source text length." + ); + } + + /** + * Asserts the enabled state of action buttons in the SelectTranslationsPanel. + * + * @param {Record} enabledStates + * - An object that maps whether each element should be enabled (true) or disabled (false). + */ + 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" + }.` + ); + } + } + + /** + * Asserts that the selected from-language matches the provided language tag. + * + * @param {string} langTag - A BCP-47 language tag. + */ + static assertSelectedFromLanguage(langTag = null) { + const { fromMenuList } = SelectTranslationsPanel.elements; + SelectTranslationsTestUtils.#assertSelectedLanguage(fromMenuList, langTag); + } + + /** + * Asserts that the selected to-language matches the provided language tag. + * + * @param {string} langTag - A BCP-47 language tag. + */ + static assertSelectedToLanguage(langTag = null) { + const { toMenuList } = SelectTranslationsPanel.elements; + SelectTranslationsTestUtils.#assertSelectedLanguage(toMenuList, langTag); + } + + /** + * Asserts the selected language in the given menu list if a langTag is provided. + * If no langTag is given, asserts that the menulist displays the localized placeholder. + * + * @param {object} menuList - The menu list object to check. + * @param {string} [langTag] - The optional language tag to assert against. + */ + static #assertSelectedLanguage(menuList, langTag) { + if (langTag) { + SharedTranslationsTestUtils._assertSelectedLanguage(menuList, { + langTag, + }); + } else { + SharedTranslationsTestUtils._assertSelectedLanguage(menuList, { + l10nId: "translations-panel-choose-language", + }); + SharedTranslationsTestUtils._assertHasFocus(menuList); + } + } + + /** + * Simulates clicking the done button and waits for the panel to close. + */ + static async clickDoneButton() { + logAction(); + 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(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]), + ]); + + const translatablePhasePromise = + SelectTranslationsTestUtils.waitForPanelState("translatable"); + click(translateButton); + await translatablePhasePromise; + + 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: false, locale: true, icon: true }, + "The icon presents the locale." + ); + } + + /** + * 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 } }); + + const translatablePhasePromise = downloadHandler + ? SelectTranslationsTestUtils.waitForPanelState("translatable") + : Promise.resolve(); + + if (SelectTranslationsPanel.phase() === "init-failure") { + // The try-again button reopens the panel from the "init-failure" phase. + await SelectTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + () => click(tryAgainButton, "Clicking the try-again button") + ); + } else { + // Otherwise the try-again button just attempts to re-translate. + click(tryAgainButton, "Clicking the try-again button"); + } + + if (downloadHandler) { + await translatablePhasePromise; + 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

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. + * @param {boolean} options.selectFrenchSentence - Selects a French sentence. + * @param {boolean} options.selectEnglishSentence - Selects an English sentence. + * @param {boolean} options.selectSpanishSentence - Selects a Spanish sentence. + * @param {boolean} options.openAtFrenchSection - Opens the context menu at the section of French text. + * @param {boolean} options.openAtEnglishSection - Opens the context menu at the section of English text. + * @param {boolean} options.openAtSpanishSection - Opens the context menu at the section of Spanish text. + * @param {boolean} options.openAtFrenchSentence - Opens the context menu at a French sentence. + * @param {boolean} options.openAtEnglishSentence - Opens the context menu at an English sentence. + * @param {boolean} options.openAtSpanishSentence - Opens the context menu at a Spanish sentence. + * @param {boolean} options.openAtFrenchHyperlink - Opens the context menu at a hyperlinked French text. + * @param {boolean} options.openAtEnglishHyperlink - Opens the context menu at a hyperlinked English text. + * @param {boolean} options.openAtSpanishHyperlink - Opens the context menu at a hyperlinked Spanish text. + * @param {boolean} options.openAtURLHyperlink - Opens the context menu at a hyperlinked URL text. + * @throws Throws an error if no valid option was provided for opening the menu. + */ + static async openContextMenu(runInPage, options) { + logAction(); + + const maybeSelectContentFrom = async keyword => { + const conditionVariableName = `select${keyword}`; + const selectorFunctionName = `get${keyword}`; + + if (options[conditionVariableName]) { + await runInPage( + async (TranslationsTest, data) => { + const selectorFunction = + TranslationsTest.getSelectors()[data.selectorFunctionName]; + if (typeof selectorFunction === "function") { + const element = await selectorFunction(); + TranslationsTest.selectContentElement(element); + } + }, + { selectorFunctionName } + ); + } + }; + + await maybeSelectContentFrom("H1"); + await maybeSelectContentFrom("PdfSpan"); + await maybeSelectContentFrom("FrenchSection"); + await maybeSelectContentFrom("EnglishSection"); + await maybeSelectContentFrom("SpanishSection"); + await maybeSelectContentFrom("FrenchSentence"); + await maybeSelectContentFrom("EnglishSentence"); + await maybeSelectContentFrom("SpanishSentence"); + + const maybeOpenContextMenuAt = async keyword => { + const optionVariableName = `openAt${keyword}`; + const selectorFunctionName = `get${keyword}`; + + if (options[optionVariableName]) { + await SharedTranslationsTestUtils._waitForPopupEvent( + "contentAreaContextMenu", + "popupshown", + async () => { + await runInPage( + async (TranslationsTest, data) => { + const selectorFunction = + TranslationsTest.getSelectors()[data.selectorFunctionName]; + if (typeof selectorFunction === "function") { + const element = await selectorFunction(); + await TranslationsTest.rightClickContentElement(element); + } + }, + { selectorFunctionName } + ); + } + ); + } + }; + + await maybeOpenContextMenuAt("H1"); + await maybeOpenContextMenuAt("PdfSpan"); + await maybeOpenContextMenuAt("FrenchSection"); + await maybeOpenContextMenuAt("EnglishSection"); + await maybeOpenContextMenuAt("SpanishSection"); + await maybeOpenContextMenuAt("FrenchSentence"); + await maybeOpenContextMenuAt("EnglishSentence"); + await maybeOpenContextMenuAt("SpanishSentence"); + await maybeOpenContextMenuAt("FrenchHyperlink"); + await maybeOpenContextMenuAt("EnglishHyperlink"); + await maybeOpenContextMenuAt("SpanishHyperlink"); + await maybeOpenContextMenuAt("URLHyperlink"); + } + + /** + * Handles language-model downloads for the SelectTranslationsPanel, ensuring that expected + * UI states match based on the resolved download state. + * + * @param {object} options - Configuration options for downloads. + * @param {function(number): Promise} options.downloadHandler - The function to resolve or reject the downloads. + * @param {boolean} [options.pivotTranslation] - Whether to expect a pivot translation. + * + * @returns {Promise} + */ + static async handleDownloads({ downloadHandler, pivotTranslation }) { + if (downloadHandler) { + await SelectTranslationsTestUtils.assertPanelViewActivelyTranslating(); + await downloadHandler(pivotTranslation ? 2 : 1); + } + } + + /** + * Switches the selected from-language to the provided language tags + * + * @param {string[]} langTags - An array of BCP-47 language tags. + * @param {object} options - Configuration options for the language change. + * @param {boolean} options.openDropdownMenu - Determines whether the language change should be made via a dropdown menu or directly. + * + * @returns {Promise} + */ + static async changeSelectedFromLanguage(langTags, options) { + logAction(langTags); + const { fromMenuList, fromMenuPopup } = SelectTranslationsPanel.elements; + const { openDropdownMenu } = options; + + const switchFn = openDropdownMenu + ? SelectTranslationsTestUtils.#changeSelectedLanguageViaDropdownMenu + : SelectTranslationsTestUtils.#changeSelectedLanguageDirectly; + + await switchFn( + langTags, + { menuList: fromMenuList, menuPopup: fromMenuPopup }, + options + ); + } + + /** + * 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. + * @param {object} options - Options for selecting paragraphs and opening the context menu. + * @param {boolean} options.openDropdownMenu - Determines whether the language change should be made via a dropdown menu or directly. + * @param {Function} options.downloadHandler - Handler for initiating downloads post language change, if applicable. + * @param {Function} options.onChangeLanguage - Callback function to be executed after the language change. + * + * @returns {Promise} + */ + static async changeSelectedToLanguage(langTags, options) { + logAction(langTags); + const { toMenuList, toMenuPopup } = SelectTranslationsPanel.elements; + const { openDropdownMenu } = options; + + const switchFn = openDropdownMenu + ? SelectTranslationsTestUtils.#changeSelectedLanguageViaDropdownMenu + : SelectTranslationsTestUtils.#changeSelectedLanguageDirectly; + + await switchFn( + langTags, + { menuList: toMenuList, menuPopup: toMenuPopup }, + options + ); + } + + /** + * Directly changes the selected language to each provided language tag without using a dropdown menu. + * + * @param {string[]} langTags - An array of BCP-47 language tags for direct selection. + * @param {object} elements - Elements required for changing the selected language. + * @param {Element} elements.menuList - The menu list element where languages are directly changed. + * @param {object} options - Configuration options for language change and additional actions. + * @param {Function} options.downloadHandler - Handler for initiating downloads post language change, if applicable. + * @param {Function} options.onChangeLanguage - Callback function to be executed after the language change. + * + * @returns {Promise} + */ + static async #changeSelectedLanguageDirectly(langTags, elements, options) { + const { menuList } = elements; + const { textArea } = SelectTranslationsPanel.elements; + const { onChangeLanguage, downloadHandler } = options; + + for (const langTag of langTags) { + const menuListUpdated = BrowserTestUtils.waitForMutationCondition( + menuList, + { attributes: true, attributeFilter: ["value"] }, + () => menuList.value === langTag + ); + + menuList.focus(); + menuList.value = langTag; + menuList.dispatchEvent(new Event("command", { bubbles: true })); + await menuListUpdated; + } + + // 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); + } + + if (onChangeLanguage) { + await onChangeLanguage(); + } + } + + /** + * Changes the selected language by opening the dropdown menu for each provided language tag. + * + * @param {string[]} langTags - An array of BCP-47 language tags for selection via dropdown. + * @param {object} elements - Elements involved in the dropdown language selection process. + * @param {Element} elements.menuList - The element that triggers the dropdown menu. + * @param {Element} elements.menuPopup - The dropdown menu element containing selectable languages. + * @param {object} options - Configuration options for language change and additional actions. + * @param {Function} options.downloadHandler - Handler for initiating downloads post language change, if applicable. + * @param {Function} options.onChangeLanguage - Callback function to be executed after the language change. + * + * @returns {Promise} + */ + static async #changeSelectedLanguageViaDropdownMenu( + langTags, + elements, + options + ) { + const { menuList, menuPopup } = elements; + const { onChangeLanguage } = options; + for (const langTag of langTags) { + await SelectTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + () => click(menuList) + ); + + const menuItem = menuPopup.querySelector(`[value="${langTag}"]`); + await SelectTranslationsTestUtils.waitForPanelPopupEvent( + "popuphidden", + () => { + click(menuItem); + // Synthesizing a click on the menuitem isn't closing the popup + // as a click normally would, so this tab keypress is added to + // ensure the popup closes. + EventUtils.synthesizeKey("KEY_Tab"); + } + ); + + await SelectTranslationsTestUtils.handleDownloads(options); + if (onChangeLanguage) { + await onChangeLanguage(); + } + } + } + + /** + * Opens the Select Translations panel via the context menu based on specified options. + * + * @param {Function} runInPage - A content-exposed function to run within the context of the page. + * @param {object} options - Options for selecting paragraphs and opening the context menu. + * + * The following options will only work when testing SELECT_TEST_PAGE_URL. + * + * @param {string} options.expectedFromLanguage - The expected from-language tag. + * @param {string} options.expectedToLanguage - The expected to-language tag. + * @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. + * @param {boolean} options.selectFrenchSentence - Selects a French sentence. + * @param {boolean} options.selectEnglishSentence - Selects an English sentence. + * @param {boolean} options.selectSpanishSentence - Selects a Spanish sentence. + * @param {boolean} options.openAtFrenchSection - Opens the context menu at the section of French text. + * @param {boolean} options.openAtEnglishSection - Opens the context menu at the section of English text. + * @param {boolean} options.openAtSpanishSection - Opens the context menu at the section of Spanish text. + * @param {boolean} options.openAtFrenchSentence - Opens the context menu at a French sentence. + * @param {boolean} options.openAtEnglishSentence - Opens the context menu at an English sentence. + * @param {boolean} options.openAtSpanishSentence - Opens the context menu at a Spanish sentence. + * @param {boolean} options.openAtFrenchHyperlink - Opens the context menu at a hyperlinked French text. + * @param {boolean} options.openAtEnglishHyperlink - Opens the context menu at a hyperlinked English text. + * @param {boolean} options.openAtSpanishHyperlink - Opens the context menu at a hyperlinked Spanish text. + * @param {boolean} options.openAtURLHyperlink - Opens the context menu at a hyperlinked URL text. + * @param {Function} [options.onOpenPanel] - An optional callback function to execute after the panel opens. + * @param {string|null} [message] - An optional message to log to info. + * @throws Throws an error if the context menu could not be opened with the provided options. + * @returns {Promise} + */ + static async openPanel(runInPage, options, message) { + logAction(); + + if (message) { + info(message); + } + + await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( + runInPage, + options, + message + ); + + const menuItem = getById("context-translate-selection"); + + await SelectTranslationsTestUtils.waitForPanelPopupEvent( + "popupshown", + async () => { + click(menuItem); + await closeContextMenuIfOpen(); + }, + async () => { + const { onOpenPanel } = options; + await SelectTranslationsTestUtils.handleDownloads(options); + if (onOpenPanel) { + await onOpenPanel(); + } + } + ); + + const { expectedFromLanguage, expectedToLanguage } = options; + if (expectedFromLanguage !== undefined) { + SelectTranslationsTestUtils.assertSelectedFromLanguage( + expectedFromLanguage + ); + } + if (expectedToLanguage !== undefined) { + SelectTranslationsTestUtils.assertSelectedToLanguage(expectedToLanguage); + } + + const { panel } = SelectTranslationsPanel.elements; + + const documentRoleElement = panel.querySelector('[role="document"]'); + ok(documentRoleElement, "The document-role element can be found."); + + const ariaDescription = document.getElementById( + documentRoleElement.getAttribute("aria-describedby") + ); + ok(ariaDescription, "The a11y description for the panel can be found."); + + const ariaLabelIds = documentRoleElement + .getAttribute("aria-labelledby") + .split(" "); + for (const id of ariaLabelIds) { + const ariaLabel = document.getElementById(id); + ok(ariaLabel, `The a11y label element '${id}' can be found.`); + assertVisibility({ visible: { ariaLabel } }); + } + } + + /** + * 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 + * @param {Function} postEventAssertion + * An optional assertion to be made immediately after the event occurs. + * @returns {Promise} + */ + static async waitForPanelPopupEvent( + eventName, + callback, + postEventAssertion = null + ) { + // De-lazify the panel elements. + SelectTranslationsPanel.elements; + await SharedTranslationsTestUtils._waitForPopupEvent( + "select-translations-panel", + eventName, + callback, + postEventAssertion + ); + } +} + +class TranslationsSettingsTestUtils { + /** + * Opens the Translation Settings page by clicking the settings button sent in the argument. + * + * @param {HTMLElement} settingsButton + * @returns {Element} + */ + static async openAboutPreferencesTranslationsSettingsPane(settingsButton) { + const document = gBrowser.selectedBrowser.contentDocument; + + const translationsPane = + content.window.gCategoryModules.get("paneTranslations"); + const promise = BrowserTestUtils.waitForEvent( + document, + "paneshown", + false, + event => event.detail.category === "paneTranslations" + ); + + click(settingsButton, "Click settings button"); + await promise; + + return translationsPane.elements; + } + + /** + * Utility function to handle the click event for a `moz-button` element that controls + * the Download/Remove Language functionality. + * + * The button's icon reflects the current state of the language (downloaded, loading, or removed), + * which is represented by a corresponding CSS class. + * + * When this button is clicked for any language, the function waits for the button's state and icon + * to update. It then checks whether the button's state and icon match the expected state as defined + * by the test case, and logs the respective message provided by the test case. + * + * @param {Element} langButton - The `moz-button` element representing the download/remove button. + * @param {string} buttonIcon - The expected CSS class representing the button's state/icon (e.g., download, loading, or remove icon). + * @param {string} logMsg - A custom log message provided by the test case indicating the expected result. + */ + + static async downaloadButtonClick(langButton, buttonIcon, logMsg) { + if ( + !langButton.parentNode + .querySelector("moz-button") + .classList.contains(buttonIcon) + ) { + await BrowserTestUtils.waitForMutationCondition( + langButton.parentNode.querySelector("moz-button"), + { attributes: true, attributeFilter: ["class"] }, + () => + langButton.parentNode + .querySelector("moz-button") + .classList.contains(buttonIcon) + ); + } + ok( + langButton.parentNode + .querySelector("moz-button") + .classList.contains(buttonIcon), + logMsg + ); + } +} diff --git a/src/zen/tests/mochitests/translations/perftest.toml b/src/zen/tests/mochitests/translations/perftest.toml new file mode 100644 index 0000000000..93a251a884 --- /dev/null +++ b/src/zen/tests/mochitests/translations/perftest.toml @@ -0,0 +1,9 @@ +[DEFAULT] +support-files = [ + "head.js", + "!/toolkit/components/translations/tests/browser/shared-head.js", + "!/toolkit/components/translations/tests/browser/translations-test.mjs", +] + +["browser_translations_perf_es_en.js"] +disabled = "Disabled since we want to run this only as perftest, not in regular CI." diff --git a/src/zen/tests/moz.build b/src/zen/tests/moz.build index fd6101bce8..d857475e71 100644 --- a/src/zen/tests/moz.build +++ b/src/zen/tests/moz.build @@ -15,3 +15,7 @@ BROWSER_CHROME_MANIFESTS += [ "welcome/browser.toml", "workspaces/browser.toml", ] + +DIRS += [ + "mochitests", +] From c5058746de1d92eb23b8624e2defb3b74ea096df Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Wed, 22 Oct 2025 01:18:49 +0200 Subject: [PATCH 2/3] feat: Added lint rules to ignore mochi tests, b=no-bug, c=tests --- eslint.config.mjs | 3 ++- src/zen/tests/manifest.toml | 3 +++ src/zen/tests/mochitests/reportbrokensite/browser.toml | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 6353523ceb..19ed435152 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -4,7 +4,7 @@ import js from '@eslint/js'; import globals from 'globals'; -import { defineConfig } from 'eslint/config'; +import { defineConfig, globalIgnores } from 'eslint/config'; import zenGlobals from './src/zen/zen.globals.js'; export default defineConfig([ @@ -23,4 +23,5 @@ export default defineConfig([ }, ignores: ['**/vendor/**', '**/tests/**'], }, + globalIgnores(['**/mochitests/**']), ]); diff --git a/src/zen/tests/manifest.toml b/src/zen/tests/manifest.toml index aeb652ed68..caabc861f1 100644 --- a/src/zen/tests/manifest.toml +++ b/src/zen/tests/manifest.toml @@ -6,6 +6,9 @@ [reportbrokensite] source = "browser/components/reportbrokensite/test/browser" is_direct_path = true +disable = [ + "browser_addon_data_sent.js" +] [reportbrokensite.replace-manifest] "../../../../../" = "../../../../" diff --git a/src/zen/tests/mochitests/reportbrokensite/browser.toml b/src/zen/tests/mochitests/reportbrokensite/browser.toml index 5681f17948..f88c3bf265 100644 --- a/src/zen/tests/mochitests/reportbrokensite/browser.toml +++ b/src/zen/tests/mochitests/reportbrokensite/browser.toml @@ -7,6 +7,7 @@ support-files = [ ] ["browser_addon_data_sent.js"] +disabled="Disabled by import_external_tests.py" support-files = [ "send_more_info.js" ] skip-if = ["os == 'win' && os_version == '11.26100' && processor == 'x86_64' && opt"] # Bug 1955805 From c7e27a50cef266e3ee529cd478ec83cdc8c8503b Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Mon, 15 Dec 2025 12:08:12 +0100 Subject: [PATCH 3/3] chore: Finish importing tests, b=no-bug, c=workflows, tests, scripts, tabs --- .github/workflows/sync-upstream.yml | 4 + scripts/import_external_tests.py | 23 +- scripts/run_tests.py | 1 + src/zen/tests/ignorePrefs.json | 6 +- src/zen/tests/manifest.toml | 7 +- src/zen/tests/mochitests/moz.build | 1 - .../mochitests/reportbrokensite/browser.toml | 9 +- .../browser_antitracking_data_sent.js | 13 +- .../browser_learn_more_link.js | 36 + .../reportbrokensite/browser_tab_key_order.js | 2 + .../tests/mochitests/reportbrokensite/head.js | 21 + .../tests/mochitests/reportbrokensite/send.js | 25 + .../reportbrokensite/send_more_info.js | 4 +- src/zen/tests/mochitests/shell/browser.toml | 2 + .../tests/mochitests/shell/browser_1119088.js | 10 +- .../shell/browser_setDefaultPDFHandler.js | 2 +- .../mochitests/shell/mac_desktop_image.py | 254 +- .../tests/mochitests/shell/unit/xpcshell.toml | 1 + .../mochitests/translations/browser.toml | 285 -- ...preferences_manage_downloaded_languages.js | 225 - ...ces_settings_always_translate_languages.js | 97 - ...nces_settings_download_languages_all_ui.js | 159 - ...es_settings_download_languages_error_ui.js | 173 - ...ferences_settings_download_languages_ui.js | 117 - ...nces_settings_never_translate_languages.js | 89 - ...ferences_settings_never_translate_sites.js | 124 - ...nslations_about_preferences_settings_ui.js | 462 -- ...t_preferences_settings_ui_keyboard_a11y.js | 635 --- ...tions_about_preferences_settings_ui_tab.js | 56 - ...l_page_translate_with_lexical_shortlist.js | 100 - ...age_translate_without_lexical_shortlist.js | 100 - ...ns_full_page_intersection_content_eager.js | 156 - ...lations_full_page_intersection_find_bar.js | 256 - ...section_find_bar_move_tab_to_new_window.js | 267 - ...ll_page_intersection_find_bar_multi_tab.js | 256 - ...ranslations_full_page_intersection_lazy.js | 161 - ...ge_intersection_mutations_content_eager.js | 247 - ...s_full_page_intersection_mutations_lazy.js | 235 - ...slations_full_page_language_id_behavior.js | 298 -- ...ations_full_page_move_tab_to_new_window.js | 68 - ...er_translations_full_page_moz_extension.js | 79 - ...translations_full_page_multiple_windows.js | 65 - ...translations_full_page_panel_a11y_focus.js | 34 - ...anel_always_translate_language_bad_data.js | 41 - ...e_panel_always_translate_language_basic.js | 81 - ..._panel_always_translate_language_manual.js | 88 - ...panel_always_translate_language_restore.js | 109 - ...panel_app_menu_never_translate_language.js | 42 - ...age_panel_app_menu_never_translate_site.js | 151 - ...ll_page_panel_auto_translate_error_view.js | 88 - ..._page_panel_auto_translate_revisit_view.js | 92 - ...ser_translations_full_page_panel_basics.js | 69 - ...ser_translations_full_page_panel_button.js | 77 - ...ser_translations_full_page_panel_cancel.js | 29 - ...tions_full_page_panel_change_app_locale.js | 74 - ...slate_language_with_translations_active.js | 159 - ...ate_language_with_translations_inactive.js | 99 - ..._panel_close_panel_never_translate_site.js | 170 - ...slations_full_page_panel_engine_destroy.js | 64 - ..._full_page_panel_engine_destroy_pending.js | 77 - ...ions_full_page_panel_engine_unsupported.js | 59 - ...r_translations_full_page_panel_firstrun.js | 55 - ...ations_full_page_panel_firstrun_revisit.js | 64 - ..._full_page_panel_flip_lexical_shortlist.js | 146 - ...er_translations_full_page_panel_fuzzing.js | 243 - ...owser_translations_full_page_panel_gear.js | 34 - ...anslations_full_page_panel_init_failure.js | 25 - ..._panel_modify_available_language_models.js | 148 - ...ull_page_panel_never_translate_language.js | 198 - ...ns_full_page_panel_never_translate_site.js | 261 - ...ll_page_panel_never_translate_site_auto.js | 115 - ...l_page_panel_never_translate_site_basic.js | 64 - ..._page_panel_never_translate_site_manual.js | 89 - ...wser_translations_full_page_panel_retry.js | 59 - ...ranslations_full_page_panel_script_tags.js | 153 - ...ll_page_panel_settings_unsupported_lang.js | 76 - ...ations_full_page_panel_switch_languages.js | 79 - ...e_panel_switch_tabs_before_engine_ready.js | 300 -- ...anel_target_language_persists_on_reopen.js | 46 - ...ations_full_page_panel_unsupported_lang.js | 33 - ...page_panel_weblanguage_differs_from_app.js | 42 - ...wser_translations_full_page_reader_mode.js | 141 - ...ions_full_page_telemetry_auto_translate.js | 127 - ...translations_full_page_telemetry_basics.js | 93 - ...slations_full_page_telemetry_open_panel.js | 93 - ...ns_full_page_telemetry_panel_auto_offer.js | 87 - ...age_telemetry_panel_auto_offer_settings.js | 120 - ...lations_full_page_telemetry_retranslate.js | 164 - ...ns_full_page_telemetry_switch_languages.js | 192 - ...full_page_telemetry_translation_failure.js | 197 - ...full_page_telemetry_translation_request.js | 157 - ...ns_full_page_telemetry_unsupported_lang.js | 212 - .../browser_translations_perf_es_en.js | 109 - ...s_recent_language_memory_auto_translate.js | 82 - ...nt_language_memory_full_page_and_select.js | 103 - ...emory_full_page_and_select_multi_window.js | 135 - ..._language_memory_full_page_multi_window.js | 127 - ...memory_full_page_multi_window_multi_tab.js | 321 -- ...cent_language_memory_full_page_navigate.js | 104 - ...t_language_memory_full_page_retranslate.js | 85 - ..._select_context_menu_engine_unsupported.js | 35 - ...ns_select_context_menu_feature_disabled.js | 114 - ...lect_context_menu_preferred_app_locales.js | 106 - ...text_menu_preferred_language_edge_cases.js | 74 - ...ct_context_menu_preferred_web_languages.js | 65 - ...menu_with_full_page_translations_active.js | 174 - ...ions_select_context_menu_with_hyperlink.js | 139 - ...lect_context_menu_with_no_text_selected.js | 37 - ..._select_context_menu_with_text_selected.js | 76 - ...er_translations_select_panel_a11y_utils.js | 87 - ...slations_select_panel_change_app_locale.js | 74 - ...nslations_select_panel_close_on_new_tab.js | 46 - ...r_translations_select_panel_copy_button.js | 95 - ..._translations_select_panel_engine_cache.js | 59 - ...s_select_panel_fallback_to_doc_language.js | 89 - ...ons_select_panel_flip_lexical_shortlist.js | 104 - ..._translations_select_panel_init_failure.js | 119 - ..._panel_modify_available_language_models.js | 163 - .../browser_translations_select_panel_pdf.js | 42 - ...r_translations_select_panel_reader_mode.js | 44 - ...retranslate_on_change_language_directly.js | 70 - ...e_on_change_language_from_dropdown_menu.js | 68 - ...r_translations_select_panel_script_tags.js | 126 - ..._panel_select_current_language_directly.js | 71 - ...ect_current_language_from_dropdown_menu.js | 71 - ...ect_same_from_and_to_languages_directly.js | 66 - ...rom_and_to_languages_from_dropdown_menu.js | 66 - ...translations_select_panel_settings_menu.js | 70 - ...select_panel_translate_full_page_button.js | 87 - ...l_translate_on_change_language_directly.js | 67 - ...e_on_change_language_from_dropdown_menu.js | 67 - ...change_language_multiple_times_directly.js | 98 - ...guage_multiple_times_from_dropdown_menu.js | 99 - ...slations_select_panel_translate_on_open.js | 86 - ...tion_failure_after_unsupported_language.js | 55 - ...elect_panel_translation_failure_on_open.js | 92 - ...anel_translation_failure_on_retranslate.js | 128 - ...tions_select_panel_unsupported_language.js | 163 - ...elemetry_change_both_languages_together.js | 333 -- ...lemetry_change_languages_multiple_times.js | 374 -- ...t_telemetry_init_failure_ui_then_cancel.js | 102 - ..._telemetry_init_failure_ui_then_succeed.js | 122 - ...lect_telemetry_keypresses_cancel_button.js | 174 - ...select_telemetry_keypresses_copy_button.js | 88 - ...select_telemetry_keypresses_done_button.js | 180 - ...ct_telemetry_keypresses_settings_button.js | 87 - ...t_telemetry_keypresses_translate_button.js | 121 - ...y_keypresses_translate_full_page_button.js | 118 - ...eypresses_try_again_button_init_failure.js | 106 - ...es_try_again_button_translation_failure.js | 110 - ...ranslations_select_telemetry_multi_page.js | 138 - ...ranslations_select_telemetry_primary_ui.js | 306 -- ...slations_select_telemetry_settings_menu.js | 98 - ...etry_translation_failure_ui_then_cancel.js | 146 - ...try_translation_failure_ui_then_succeed.js | 136 - ...lure_with_full_page_translations_active.js | 212 - ...cess_with_full_page_translations_active.js | 249 - ...elect_telemetry_unsupported_language_ui.js | 162 - src/zen/tests/mochitests/translations/head.js | 4291 ----------------- .../mochitests/translations/perftest.toml | 9 - 160 files changed, 269 insertions(+), 22298 deletions(-) create mode 100644 src/zen/tests/mochitests/reportbrokensite/browser_learn_more_link.js delete mode 100644 src/zen/tests/mochitests/translations/browser.toml delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_manage_downloaded_languages.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_always_translate_languages.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_all_ui.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_error_ui.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_ui.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_languages.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_sites.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_keyboard_a11y.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_tab.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_with_lexical_shortlist.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_without_lexical_shortlist.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_content_eager.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_move_tab_to_new_window.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_multi_tab.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_lazy.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_content_eager.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_lazy.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_language_id_behavior.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_move_tab_to_new_window.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_moz_extension.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_multiple_windows.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_a11y_focus.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_bad_data.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_basic.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_manual.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_restore.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_language.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_site.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_error_view.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_revisit_view.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_basics.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_button.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_cancel.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_change_app_locale.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_active.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_inactive.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_site.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy_pending.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_unsupported.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun_revisit.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_flip_lexical_shortlist.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_fuzzing.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_gear.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_init_failure.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_modify_available_language_models.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_language.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_auto.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_basic.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_manual.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_retry.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_script_tags.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_settings_unsupported_lang.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_languages.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_tabs_before_engine_ready.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_target_language_persists_on_reopen.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_unsupported_lang.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_panel_weblanguage_differs_from_app.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_reader_mode.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_auto_translate.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_basics.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_open_panel.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer_settings.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_retranslate.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_switch_languages.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_failure.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_request.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_unsupported_lang.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_perf_es_en.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_auto_translate.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select_multi_window.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window_multi_tab.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_navigate.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_retranslate.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_engine_unsupported.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_feature_disabled.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_app_locales.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_language_edge_cases.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_web_languages.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_full_page_translations_active.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_hyperlink.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_no_text_selected.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_text_selected.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_a11y_utils.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_change_app_locale.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_close_on_new_tab.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_copy_button.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_engine_cache.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_fallback_to_doc_language.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_flip_lexical_shortlist.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_init_failure.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_modify_available_language_models.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_pdf.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_reader_mode.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_directly.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_script_tags.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_directly.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_from_dropdown_menu.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_directly.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_from_dropdown_menu.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_settings_menu.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_full_page_button.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_directly.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_from_dropdown_menu.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_directly.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_from_dropdown_menu.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_open.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_after_unsupported_language.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_open.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_retranslate.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_panel_unsupported_language.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_both_languages_together.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_languages_multiple_times.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_cancel.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_succeed.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_cancel_button.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_copy_button.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_done_button.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_settings_button.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_button.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_full_page_button.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_init_failure.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_translation_failure.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_multi_page.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_primary_ui.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_settings_menu.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_cancel.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_succeed.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_with_full_page_translations_active.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_success_with_full_page_translations_active.js delete mode 100644 src/zen/tests/mochitests/translations/browser_translations_select_telemetry_unsupported_language_ui.js delete mode 100644 src/zen/tests/mochitests/translations/head.js delete mode 100644 src/zen/tests/mochitests/translations/perftest.toml diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index be6c531205..e88a8ca6a1 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -95,6 +95,10 @@ jobs: echo "Checking if patches apply cleanly..." npm run import + - name: Import external tests + if: steps.git-check.outputs.files_changed == 'true' + run: python3 scripts/import_external_tests.py + - name: Create pull request uses: peter-evans/create-pull-request@v7 if: steps.git-check.outputs.files_changed == 'true' diff --git a/scripts/import_external_tests.py b/scripts/import_external_tests.py index 0808a2abc9..535686c619 100644 --- a/scripts/import_external_tests.py +++ b/scripts/import_external_tests.py @@ -23,14 +23,17 @@ FILE_SUFFIX = "]" + def get_tests_manifest(): with open(EXTERNAL_TESTS_MANIFEST, "rb") as f: return tomllib.load(f) + def die_with_error(message): print(f"ERROR: {message}") exit(1) + def validate_tests_path(path, files, ignore_list): for ignore in ignore_list: if ignore not in files: @@ -38,6 +41,7 @@ def validate_tests_path(path, files, ignore_list): if "browser.toml" not in files or "browser.js" in ignore_list: die_with_error(f"'browser.toml' not found in tests folder '{path}'") + def disable_and_replace_manifest(manifest, output_path): toml_file = os.path.join(output_path, "browser.toml") disabled_tests = manifest.get("disable", []) @@ -56,6 +60,7 @@ def disable_and_replace_manifest(manifest, output_path): with open(toml_file, "w") as f: f.write(data) + def import_test_suite(test_suite, source_path, output_path, ignore_list, manifest, is_direct_path=False): print(f"Importing test suite '{test_suite}' from '{source_path}'") tests_folder = os.path.join("engine", source_path) @@ -79,6 +84,7 @@ def import_test_suite(test_suite, source_path, output_path, ignore_list, manifes shutil.copy2(s, d) disable_and_replace_manifest(manifest[test_suite], output_path) + def write_moz_build_file(manifest): moz_build_path = os.path.join(EXTERNAL_TESTS_OUTPUT, "moz.build") print(f"Writing moz.build file to '{moz_build_path}'") @@ -88,11 +94,13 @@ def write_moz_build_file(manifest): f.write(f'\t"{test_suite}/browser.toml",\n') f.write(FILE_SUFFIX) + def make_sure_ordered_tests(manifest): ordered_tests = sorted(manifest.keys()) if list(manifest.keys()) != ordered_tests: die_with_error("Test suites in manifest.toml are not in alphabetical order.") + def main(): manifest = get_tests_manifest() if os.path.exists(EXTERNAL_TESTS_OUTPUT): @@ -102,14 +110,15 @@ def main(): make_sure_ordered_tests(manifest) for test_suite, config in manifest.items(): import_test_suite( - test_suite=test_suite, - source_path=config["source"], - output_path=os.path.join(EXTERNAL_TESTS_OUTPUT, test_suite), - ignore_list=config.get("ignore", []), - is_direct_path=config.get("is_direct_path", False), - manifest=manifest + test_suite=test_suite, + source_path=config["source"], + output_path=os.path.join(EXTERNAL_TESTS_OUTPUT, test_suite), + ignore_list=config.get("ignore", []), + is_direct_path=config.get("is_direct_path", False), + manifest=manifest ) write_moz_build_file(manifest) + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/scripts/run_tests.py b/scripts/run_tests.py index ffdcf24439..958b09ce41 100644 --- a/scripts/run_tests.py +++ b/scripts/run_tests.py @@ -17,6 +17,7 @@ MOCHITEST_NAME = "mochitests" + def copy_ignore_prefs(): print("Copying ignorePrefs.json from src/zen/tests to engine/testing/mochitest...") # if there are prefs that dont exist on output file, copy them from input file diff --git a/src/zen/tests/ignorePrefs.json b/src/zen/tests/ignorePrefs.json index b7244e6546..74187ca68f 100644 --- a/src/zen/tests/ignorePrefs.json +++ b/src/zen/tests/ignorePrefs.json @@ -10,5 +10,9 @@ "zen.mods.last-update", "zen.view.compact.enable-at-startup", "zen.urlbar.suggestions-learner", - "browser.newtabpage.activity-stream.trendingSearch.defaultSearchEngine" + "browser.newtabpage.activity-stream.trendingSearch.defaultSearchEngine", + + // From the imported safebrowsing tests + "urlclassifier.phishTable", + "urlclassifier.malwareTable" ] diff --git a/src/zen/tests/manifest.toml b/src/zen/tests/manifest.toml index caabc861f1..5541986838 100644 --- a/src/zen/tests/manifest.toml +++ b/src/zen/tests/manifest.toml @@ -20,10 +20,11 @@ is_direct_path = true [shell] source = "browser/components/shell/test" is_direct_path = true +disable = [ + "browser_1119088.js", + "browser_setDesktopBackgroundPreview.js", +] [tooltiptext] source = "toolkit/components/tooltiptext" -[translations] -source = "browser/components/translations/tests/browser" -is_direct_path = true diff --git a/src/zen/tests/mochitests/moz.build b/src/zen/tests/mochitests/moz.build index 2fa5fb2a60..593fada640 100644 --- a/src/zen/tests/mochitests/moz.build +++ b/src/zen/tests/mochitests/moz.build @@ -11,5 +11,4 @@ BROWSER_CHROME_MANIFESTS += [ "safebrowsing/browser.toml", "shell/browser.toml", "tooltiptext/browser.toml", - "translations/browser.toml", ] \ No newline at end of file diff --git a/src/zen/tests/mochitests/reportbrokensite/browser.toml b/src/zen/tests/mochitests/reportbrokensite/browser.toml index f88c3bf265..4ae01db0ef 100644 --- a/src/zen/tests/mochitests/reportbrokensite/browser.toml +++ b/src/zen/tests/mochitests/reportbrokensite/browser.toml @@ -22,7 +22,14 @@ support-files = [ "send_more_info.js" ] support-files = [ "send_more_info.js" ] ["browser_keyboard_navigation.js"] -skip-if = ["os == 'linux' && os_version == '24.04' && processor == 'x86_64' && tsan"] # Bug 1867132 +skip-if = [ + "os == 'linux' && os_version == '24.04' && processor == 'x86_64' && tsan", # Bug 1867132 + "os == 'linux' && os_version == '24.04' && processor == 'x86_64' && asan", # Bug 1867132 + "os == 'linux' && os_version == '24.04' && processor == 'x86_64' && debug", # Bug 1867132 + "os == 'win' && os_version == '11.26100' && processor == 'x86_64' && asan", # Bug 1867132 +] + +["browser_learn_more_link.js"] ["browser_parent_menuitems.js"] diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_antitracking_data_sent.js b/src/zen/tests/mochitests/reportbrokensite/browser_antitracking_data_sent.js index 675c583561..dd0b5ceafa 100644 --- a/src/zen/tests/mochitests/reportbrokensite/browser_antitracking_data_sent.js +++ b/src/zen/tests/mochitests/reportbrokensite/browser_antitracking_data_sent.js @@ -19,6 +19,13 @@ add_common_setup(); add_task(setupStrictETP); +function getEtpCategory() { + return Services.prefs.getStringPref( + "browser.contentblocking.category", + "standard" + ); +} + add_task(async function testSendButton() { ensureReportBrokenSitePreffedOn(); ensureReasonOptional(); @@ -33,12 +40,13 @@ add_task(async function testSendButton() { description: "another test description", antitracking: { blockList: "strict", + blockedOrigins: null, isPrivateBrowsing: true, hasTrackingContentBlocked: true, hasMixedActiveContentBlocked: true, hasMixedDisplayContentBlocked: true, btpHasPurgedSite: false, - etpCategory: "strict", + etpCategory: getEtpCategory(), }, frameworks: { fastclick: true, @@ -62,12 +70,13 @@ add_task(async function testSendingMoreInfo() { await testSendMoreInfo(tab, HelpMenu(win), { antitracking: { blockList: "strict", + blockedOrigins: ["https://trackertest.org"], isPrivateBrowsing: true, hasTrackingContentBlocked: true, hasMixedActiveContentBlocked: true, hasMixedDisplayContentBlocked: true, btpHasPurgedSite: false, - etpCategory: "strict", + etpCategory: getEtpCategory(), }, frameworks: { fastclick: true, mobify: true, marfeel: true }, consoleLog: [ diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_learn_more_link.js b/src/zen/tests/mochitests/reportbrokensite/browser_learn_more_link.js new file mode 100644 index 0000000000..4040bef59b --- /dev/null +++ b/src/zen/tests/mochitests/reportbrokensite/browser_learn_more_link.js @@ -0,0 +1,36 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Tests to ensure that the reason dropdown is shown or hidden + * based on its pref, and that its optional and required modes affect + * the Send button and report appropriately. + */ + +"use strict"; + +add_common_setup(); + +async function ensureLearnMoreLinkWorks(menu) { + const rbs = await menu.openReportBrokenSite(); + const { win, mainView, learnMoreLink } = rbs; + ok(learnMoreLink, "Found a learn more link"); + + const promises = [ + BrowserTestUtils.waitForEvent(mainView, "ViewHiding"), + BrowserTestUtils.waitForNewTab(win.gBrowser, LEARN_MORE_TEST_URL), + ]; + EventUtils.synthesizeMouseAtCenter(learnMoreLink, {}, win); + const results = await Promise.all(promises); + gBrowser.removeTab(results[1]); +} + +add_task(async function testLearnMoreLink() { + ensureReportBrokenSitePreffedOn(); + await BrowserTestUtils.withNewTab(REPORTABLE_PAGE_URL, async function () { + await ensureLearnMoreLinkWorks(AppMenu()); + await ensureLearnMoreLinkWorks(HelpMenu()); + await ensureLearnMoreLinkWorks(ProtectionsPanel()); + }); + const telemetry = Glean.webcompatreporting.learnMore.testGetValue(); + is(telemetry.length, 3, "Got telemetry"); +}); diff --git a/src/zen/tests/mochitests/reportbrokensite/browser_tab_key_order.js b/src/zen/tests/mochitests/reportbrokensite/browser_tab_key_order.js index e02c6a8394..ab776fb268 100644 --- a/src/zen/tests/mochitests/reportbrokensite/browser_tab_key_order.js +++ b/src/zen/tests/mochitests/reportbrokensite/browser_tab_key_order.js @@ -55,6 +55,7 @@ async function ensureExpectedTabOrder( order.push("#report-broken-site-popup-reason"); } order.push("#report-broken-site-popup-description"); + order.push("#report-broken-site-popup-blocked-trackers-checkbox"); if (expectSendMoreInfo) { order.push("#report-broken-site-popup-send-more-info-link"); } @@ -67,6 +68,7 @@ async function ensureExpectedTabOrder( if (expectBackButton) { order.push(".subviewbutton-back"); } + order.push("#report-broken-site-popup-learn-more-link"); order.push("#report-broken-site-popup-url"); // check that we've cycled back return ensureTabOrder(order); } diff --git a/src/zen/tests/mochitests/reportbrokensite/head.js b/src/zen/tests/mochitests/reportbrokensite/head.js index 2b4c1d8eb0..04357acad1 100644 --- a/src/zen/tests/mochitests/reportbrokensite/head.js +++ b/src/zen/tests/mochitests/reportbrokensite/head.js @@ -27,6 +27,11 @@ const REPORTABLE_PAGE_URL2 = REPORTABLE_PAGE_URL.replace(".com", ".org"); const REPORTABLE_PAGE_URL3 = `${BASE_URL}example_report_page.html`; +const SUMO_BASE_URL = Services.urlFormatter.formatURLPref( + "app.support.baseURL" +); +const LEARN_MORE_TEST_URL = `${SUMO_BASE_URL}report-broken-site`; + const NEW_REPORT_ENDPOINT_TEST_URL = `${BASE_URL}sendMoreInfoTestEndpoint.html`; const PREFS = { @@ -54,6 +59,8 @@ function add_common_setup() { for (const prefName of Object.values(PREFS)) { Services.prefs.clearUserPref(prefName); } + Services.telemetry.clearEvents(); + Services.fog.testResetFOG(); }); }); } @@ -399,6 +406,10 @@ class ReportBrokenSiteHelper { return this.getViewNode("report-broken-site-popup-description"); } + get learnMoreLink() { + return this.getViewNode("report-broken-site-popup-learn-more-link"); + } + get sendMoreInfoLink() { return this.getViewNode("report-broken-site-popup-send-more-info-link"); } @@ -407,6 +418,16 @@ class ReportBrokenSiteHelper { return this.mainView.querySelector(".subviewbutton-back"); } + get blockedTrackersCheckbox() { + return this.getViewNode( + "report-broken-site-popup-blocked-trackers-checkbox" + ); + } + + set blockedTrackersCheckbox(checked) { + this.blockedTrackersCheckbox.checked = checked; + } + get sendButton() { return this.getViewNode("report-broken-site-popup-send-button"); } diff --git a/src/zen/tests/mochitests/reportbrokensite/send.js b/src/zen/tests/mochitests/reportbrokensite/send.js index d3b7b1f502..5083868cf3 100644 --- a/src/zen/tests/mochitests/reportbrokensite/send.js +++ b/src/zen/tests/mochitests/reportbrokensite/send.js @@ -207,6 +207,7 @@ async function getExpectedWebCompatInfo(tab, snapshot, fullAppData = false) { devicePixelRatio: `${content.devicePixelRatio}`, antitracking: { blockList: "basic", + blockedOrigins: null, isPrivateBrowsing: false, hasTrackingContentBlocked: false, hasMixedActiveContentBlocked: false, @@ -286,6 +287,10 @@ async function testSend(tab, menu, expectedOverrides = {}) { if (expectedOverrides.antitracking) { expected.tabInfo.antitracking = expectedOverrides.antitracking; + + if (expectedOverrides.antitracking.blockedOrigins) { + rbs.blockedTrackersCheckbox = true; + } } if (expectedOverrides.frameworks) { @@ -308,6 +313,14 @@ async function testSend(tab, menu, expectedOverrides = {}) { ["basic", "strict"].includes(tabInfo.antitracking.blockList), "Got a blockList" ); + if (rbs.blockedTrackersCheckbox.checked) { + ok( + Array.isArray(tabInfo.antitracking.blockedOrigins), + "Got an array for blockedOrigins" + ); + } else { + ok(!tabInfo.antitracking.blockedOrigins, "No blockedOrigins included"); + } ok(tabInfo.useragentString?.length, "Got a final UA string"); ok( browserInfo.app.defaultUseragentString?.length, @@ -323,8 +336,20 @@ async function testSend(tab, menu, expectedOverrides = {}) { await rbs.clickOkay(); + const telemetry = Glean.webcompatreporting.send.testGetValue(); + is(telemetry?.length, 1, "Got a 'send' telemetry event"); + is( + telemetry[0].extra.sent_with_blocked_trackers, + String(!!expectedOverrides.antitracking?.blockedOrigins), + "Got correct 'sent_with_blocked_trackers' flag" + ); + // re-opening the panel, the url and description should be reset rbs = await menu.openReportBrokenSite(); rbs.isMainViewResetToCurrentTab(); + ok( + !rbs.blockedTrackersCheckbox.checked, + "blocked trackers checkbox is reset" + ); rbs.close(); } diff --git a/src/zen/tests/mochitests/reportbrokensite/send_more_info.js b/src/zen/tests/mochitests/reportbrokensite/send_more_info.js index 32ef77a59f..f5d28248df 100644 --- a/src/zen/tests/mochitests/reportbrokensite/send_more_info.js +++ b/src/zen/tests/mochitests/reportbrokensite/send_more_info.js @@ -38,6 +38,8 @@ async function reformatExpectedWebCompatInfo(tab, overrides) { const experiments = overrides.experiments || []; const atOverrides = overrides.antitracking; const blockList = atOverrides?.blockList ?? antitracking.blockList; + const blockedOrigins = + atOverrides?.blockedOrigins ?? antitracking.blockedOrigins ?? []; const hasMixedActiveContentBlocked = atOverrides?.hasMixedActiveContentBlocked ?? antitracking.hasMixedActiveContentBlocked; @@ -89,6 +91,7 @@ async function reformatExpectedWebCompatInfo(tab, overrides) { addons, applicationName, blockList, + blockedOrigins, buildId: snapshot.application.buildID, devicePixelRatio: parseInt(devicePixelRatio), experiments, @@ -149,7 +152,6 @@ async function reformatExpectedWebCompatInfo(tab, overrides) { const { gfxData } = reformatted.details.additionalData; for (const optional of [ - "direct2DEnabled", "directWriteEnabled", "directWriteVersion", "clearTypeParameters", diff --git a/src/zen/tests/mochitests/shell/browser.toml b/src/zen/tests/mochitests/shell/browser.toml index 4de6e830fb..6439fa0430 100644 --- a/src/zen/tests/mochitests/shell/browser.toml +++ b/src/zen/tests/mochitests/shell/browser.toml @@ -1,6 +1,7 @@ [DEFAULT] ["browser_1119088.js"] +disabled="Disabled by import_external_tests.py" support-files = ["mac_desktop_image.py"] run-if = ["os == 'mac'"] tags = "os_integration" @@ -98,4 +99,5 @@ run-if = ["os == 'win'"] tags = "os_integration" ["browser_setDesktopBackgroundPreview.js"] +disabled="Disabled by import_external_tests.py" tags = "os_integration" diff --git a/src/zen/tests/mochitests/shell/browser_1119088.js b/src/zen/tests/mochitests/shell/browser_1119088.js index 259176b6ab..6702769a34 100644 --- a/src/zen/tests/mochitests/shell/browser_1119088.js +++ b/src/zen/tests/mochitests/shell/browser_1119088.js @@ -13,9 +13,7 @@ if (AppConstants.isPlatformAndVersionAtLeast("macosx", 23.0)) { const kDesktopCheckerScriptPath = "browser/browser/components/shell/test/mac_desktop_image.py"; -const kDefaultBackgroundImage_10_14 = - "/Library/Desktop Pictures/Solid Colors/Teal.png"; -const kDefaultBackgroundImage_10_15 = +const kDefaultBackgroundImage = "/System/Library/Desktop Pictures/Solid Colors/Teal.png"; ChromeUtils.defineESModuleGetters(this, { @@ -81,11 +79,7 @@ function setAndCheckDesktopBackgroundCLI(imagePath) { // in the automated test environment, not the OS default. function restoreDefaultBackground() { let defaultBackgroundPath; - if (AppConstants.isPlatformAndVersionAtLeast("macosx", 19)) { - defaultBackgroundPath = kDefaultBackgroundImage_10_15; - } else { - defaultBackgroundPath = kDefaultBackgroundImage_10_14; - } + defaultBackgroundPath = kDefaultBackgroundImage; setAndCheckDesktopBackgroundCLI(defaultBackgroundPath); } diff --git a/src/zen/tests/mochitests/shell/browser_setDefaultPDFHandler.js b/src/zen/tests/mochitests/shell/browser_setDefaultPDFHandler.js index 0deb2cd1e6..443c8f69f5 100644 --- a/src/zen/tests/mochitests/shell/browser_setDefaultPDFHandler.js +++ b/src/zen/tests/mochitests/shell/browser_setDefaultPDFHandler.js @@ -23,7 +23,7 @@ XPCOMUtils.defineLazyServiceGetter( this, "XreDirProvider", "@mozilla.org/xre/directory-provider;1", - "nsIXREDirProvider" + Ci.nsIXREDirProvider ); const _userChoiceImpossibleTelemetryResultStub = sinon diff --git a/src/zen/tests/mochitests/shell/mac_desktop_image.py b/src/zen/tests/mochitests/shell/mac_desktop_image.py index e3ccc77190..d664a23cb9 100755 --- a/src/zen/tests/mochitests/shell/mac_desktop_image.py +++ b/src/zen/tests/mochitests/shell/mac_desktop_image.py @@ -31,138 +31,138 @@ def main(): - parser = argparse.ArgumentParser( - description="Utility to print, set, or " - + "check the path to image being used as " - + "the desktop background image. By " - + "default, prints the path to the " - + "current desktop background image." + parser = argparse.ArgumentParser( + description="Utility to print, set, or " + + "check the path to image being used as " + + "the desktop background image. By " + + "default, prints the path to the " + + "current desktop background image." + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + help="print verbose debugging information", + default=False, + ) + group = parser.add_mutually_exclusive_group() + group.add_argument( + "-s", + "--set-background-image", + dest="newBackgroundImagePath", + required=False, + help="path to the new background image to set. A zero " + + "exit code indicates no errors occurred.", + default=None, + ) + group.add_argument( + "-c", + "--check-background-image", + dest="checkBackgroundImagePath", + required=False, + help="check if the provided background image path " + + "matches the provided path. A zero exit code " + + "indicates the paths match.", + default=None, + ) + args = parser.parse_args() + + # Using logging for verbose output + if args.verbose: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.CRITICAL) + logger = logging.getLogger("desktopImage") + + # Print what we're going to do + if args.checkBackgroundImagePath is not None: + logger.debug( + "checking provided desktop image %s matches current " + "image" % args.checkBackgroundImagePath ) - parser.add_argument( - "-v", - "--verbose", - action="store_true", - help="print verbose debugging information", - default=False, + elif args.newBackgroundImagePath is not None: + logger.debug("setting image to %s " % args.newBackgroundImagePath) + else: + logger.debug("retrieving desktop image path") + + focussedScreen = NSScreen.mainScreen() + if not focussedScreen: + raise RuntimeError("mainScreen error") + + ws = NSWorkspace.sharedWorkspace() + if not ws: + raise RuntimeError("sharedWorkspace error") + + # If we're just checking the image path, check it and then return. + # A successful exit code (0) indicates the paths match. + if args.checkBackgroundImagePath is not None: + # Get existing desktop image path and resolve it + existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) + existingImagePath = existingImageURL.path() + existingImagePathReal = os.path.realpath(existingImagePath) + logger.debug("existing desktop image: %s" % existingImagePath) + logger.debug("existing desktop image realpath: %s" % existingImagePath) + + # Resolve the path we're going to check + checkImagePathReal = os.path.realpath(args.checkBackgroundImagePath) + logger.debug("check desktop image: %s" % args.checkBackgroundImagePath) + logger.debug("check desktop image realpath: %s" % checkImagePathReal) + + if existingImagePathReal == checkImagePathReal: + print("desktop image path matches provided path") + return True + + print("desktop image path does NOT match provided path") + return False + + # Log the current desktop image + if args.verbose: + existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) + logger.debug("existing desktop image: %s" % existingImageURL.path()) + + # Set the desktop image + if args.newBackgroundImagePath is not None: + newImagePath = args.newBackgroundImagePath + if not os.path.exists(newImagePath): + logger.critical("%s does not exist" % newImagePath) + return False + if not os.access(newImagePath, os.R_OK): + logger.critical("%s is not readable" % newImagePath) + return False + + logger.debug("new desktop image to set: %s" % newImagePath) + newImageURL = NSURL.fileURLWithPath_(newImagePath) + logger.debug("new desktop image URL to set: %s" % newImageURL) + + status = False + (status, error) = ws.setDesktopImageURL_forScreen_options_error_( + newImageURL, focussedScreen, None, None ) - group = parser.add_mutually_exclusive_group() - group.add_argument( - "-s", - "--set-background-image", - dest="newBackgroundImagePath", - required=False, - help="path to the new background image to set. A zero " - + "exit code indicates no errors occurred.", - default=None, - ) - group.add_argument( - "-c", - "--check-background-image", - dest="checkBackgroundImagePath", - required=False, - help="check if the provided background image path " - + "matches the provided path. A zero exit code " - + "indicates the paths match.", - default=None, - ) - args = parser.parse_args() - - # Using logging for verbose output - if args.verbose: - logging.basicConfig(level=logging.DEBUG) - else: - logging.basicConfig(level=logging.CRITICAL) - logger = logging.getLogger("desktopImage") - - # Print what we're going to do - if args.checkBackgroundImagePath is not None: - logger.debug( - "checking provided desktop image %s matches current " - "image" % args.checkBackgroundImagePath - ) - elif args.newBackgroundImagePath is not None: - logger.debug("setting image to %s " % args.newBackgroundImagePath) - else: - logger.debug("retrieving desktop image path") - - focussedScreen = NSScreen.mainScreen() - if not focussedScreen: - raise RuntimeError("mainScreen error") - - ws = NSWorkspace.sharedWorkspace() - if not ws: - raise RuntimeError("sharedWorkspace error") - - # If we're just checking the image path, check it and then return. - # A successful exit code (0) indicates the paths match. - if args.checkBackgroundImagePath is not None: - # Get existing desktop image path and resolve it - existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) - existingImagePath = existingImageURL.path() - existingImagePathReal = os.path.realpath(existingImagePath) - logger.debug("existing desktop image: %s" % existingImagePath) - logger.debug("existing desktop image realpath: %s" % existingImagePath) - - # Resolve the path we're going to check - checkImagePathReal = os.path.realpath(args.checkBackgroundImagePath) - logger.debug("check desktop image: %s" % args.checkBackgroundImagePath) - logger.debug("check desktop image realpath: %s" % checkImagePathReal) - - if existingImagePathReal == checkImagePathReal: - print("desktop image path matches provided path") - return True - - print("desktop image path does NOT match provided path") - return False - - # Log the current desktop image - if args.verbose: - existingImageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) - logger.debug("existing desktop image: %s" % existingImageURL.path()) - - # Set the desktop image - if args.newBackgroundImagePath is not None: - newImagePath = args.newBackgroundImagePath - if not os.path.exists(newImagePath): - logger.critical("%s does not exist" % newImagePath) - return False - if not os.access(newImagePath, os.R_OK): - logger.critical("%s is not readable" % newImagePath) - return False - - logger.debug("new desktop image to set: %s" % newImagePath) - newImageURL = NSURL.fileURLWithPath_(newImagePath) - logger.debug("new desktop image URL to set: %s" % newImageURL) - - status = False - (status, error) = ws.setDesktopImageURL_forScreen_options_error_( - newImageURL, focussedScreen, None, None - ) - if not status: - raise RuntimeError("setDesktopImageURL error") - - # Print the current desktop image - imageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) - imagePath = imageURL.path() - imagePathReal = os.path.realpath(imagePath) - logger.debug("updated desktop image URL: %s" % imageURL) - logger.debug("updated desktop image path: %s" % imagePath) - logger.debug("updated desktop image path (resolved): %s" % imagePathReal) - print(imagePathReal) - return True + if not status: + raise RuntimeError("setDesktopImageURL error") + + # Print the current desktop image + imageURL = getCurrentDesktopImageURL(focussedScreen, ws, logger) + imagePath = imageURL.path() + imagePathReal = os.path.realpath(imagePath) + logger.debug("updated desktop image URL: %s" % imageURL) + logger.debug("updated desktop image path: %s" % imagePath) + logger.debug("updated desktop image path (resolved): %s" % imagePathReal) + print(imagePathReal) + return True def getCurrentDesktopImageURL(focussedScreen, workspace, logger): - imageURL = workspace.desktopImageURLForScreen_(focussedScreen) - if not imageURL: - raise RuntimeError("desktopImageURLForScreen returned invalid URL") - if not imageURL.isFileURL(): - logger.warning("desktop image URL is not a file URL") - return imageURL + imageURL = workspace.desktopImageURLForScreen_(focussedScreen) + if not imageURL: + raise RuntimeError("desktopImageURLForScreen returned invalid URL") + if not imageURL.isFileURL(): + logger.warning("desktop image URL is not a file URL") + return imageURL if __name__ == "__main__": - if not main(): - sys.exit(1) - else: - sys.exit(0) + if not main(): + sys.exit(1) + else: + sys.exit(0) diff --git a/src/zen/tests/mochitests/shell/unit/xpcshell.toml b/src/zen/tests/mochitests/shell/unit/xpcshell.toml index 8939e6af96..445dc9edd0 100644 --- a/src/zen/tests/mochitests/shell/unit/xpcshell.toml +++ b/src/zen/tests/mochitests/shell/unit/xpcshell.toml @@ -1,4 +1,5 @@ [DEFAULT] +run-if = ["os != 'android'"] firefox-appdir = "browser" tags = "os_integration" diff --git a/src/zen/tests/mochitests/translations/browser.toml b/src/zen/tests/mochitests/translations/browser.toml deleted file mode 100644 index ae7d8a5cc2..0000000000 --- a/src/zen/tests/mochitests/translations/browser.toml +++ /dev/null @@ -1,285 +0,0 @@ -[DEFAULT] -subsuite = "translations" -support-files = [ - "head.js", - "!/toolkit/components/translations/tests/browser/shared-head.js", - "!/toolkit/components/translations/tests/browser/translations-test.mjs", -] - -["browser_translations_about_preferences_manage_downloaded_languages.js"] - -["browser_translations_about_preferences_settings_always_translate_languages.js"] - -["browser_translations_about_preferences_settings_download_languages_all_ui.js"] - -["browser_translations_about_preferences_settings_download_languages_error_ui.js"] - -["browser_translations_about_preferences_settings_download_languages_ui.js"] - -["browser_translations_about_preferences_settings_never_translate_languages.js"] - -["browser_translations_about_preferences_settings_never_translate_sites.js"] - -["browser_translations_about_preferences_settings_ui.js"] - -["browser_translations_about_preferences_settings_ui_keyboard_a11y.js"] - -["browser_translations_about_preferences_settings_ui_tab.js"] - -["browser_translations_e2e_full_page_translate_with_lexical_shortlist.js"] - -["browser_translations_e2e_full_page_translate_without_lexical_shortlist.js"] - -["browser_translations_full_page_intersection_content_eager.js"] - -["browser_translations_full_page_intersection_find_bar.js"] - -["browser_translations_full_page_intersection_find_bar_move_tab_to_new_window.js"] - -["browser_translations_full_page_intersection_find_bar_multi_tab.js"] - -["browser_translations_full_page_intersection_lazy.js"] - -["browser_translations_full_page_intersection_mutations_content_eager.js"] - -["browser_translations_full_page_intersection_mutations_lazy.js"] - -["browser_translations_full_page_language_id_behavior.js"] - -["browser_translations_full_page_move_tab_to_new_window.js"] - -["browser_translations_full_page_moz_extension.js"] - -["browser_translations_full_page_multiple_windows.js"] -skip-if = ["os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && ccov"] # Bug 1893021 - -["browser_translations_full_page_panel_a11y_focus.js"] - -["browser_translations_full_page_panel_always_translate_language_bad_data.js"] - -["browser_translations_full_page_panel_always_translate_language_basic.js"] - -["browser_translations_full_page_panel_always_translate_language_manual.js"] - -["browser_translations_full_page_panel_always_translate_language_restore.js"] - -["browser_translations_full_page_panel_app_menu_never_translate_language.js"] - -["browser_translations_full_page_panel_app_menu_never_translate_site.js"] - -["browser_translations_full_page_panel_auto_translate_error_view.js"] - -["browser_translations_full_page_panel_auto_translate_revisit_view.js"] - -["browser_translations_full_page_panel_basics.js"] - -["browser_translations_full_page_panel_button.js"] - -["browser_translations_full_page_panel_cancel.js"] - -["browser_translations_full_page_panel_change_app_locale.js"] - -["browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_active.js"] - -["browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_inactive.js"] - -["browser_translations_full_page_panel_close_panel_never_translate_site.js"] - -["browser_translations_full_page_panel_engine_destroy.js"] - -["browser_translations_full_page_panel_engine_destroy_pending.js"] -skip-if = ["os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && ccov"] # Bug 1893021 - -["browser_translations_full_page_panel_engine_unsupported.js"] - -["browser_translations_full_page_panel_firstrun.js"] - -["browser_translations_full_page_panel_firstrun_revisit.js"] - -["browser_translations_full_page_panel_flip_lexical_shortlist.js"] - -["browser_translations_full_page_panel_fuzzing.js"] -skip-if = ["true"] - -["browser_translations_full_page_panel_gear.js"] - -["browser_translations_full_page_panel_init_failure.js"] - -["browser_translations_full_page_panel_modify_available_language_models.js"] - -["browser_translations_full_page_panel_never_translate_language.js"] - -["browser_translations_full_page_panel_never_translate_site_auto.js"] - -["browser_translations_full_page_panel_never_translate_site_basic.js"] - -["browser_translations_full_page_panel_never_translate_site_manual.js"] - -["browser_translations_full_page_panel_retry.js"] - -["browser_translations_full_page_panel_script_tags.js"] - -["browser_translations_full_page_panel_settings_unsupported_lang.js"] - -["browser_translations_full_page_panel_switch_languages.js"] - -["browser_translations_full_page_panel_switch_tabs_before_engine_ready.js"] - -["browser_translations_full_page_panel_target_language_persists_on_reopen.js"] - -["browser_translations_full_page_panel_unsupported_lang.js"] - -["browser_translations_full_page_panel_weblanguage_differs_from_app.js"] - -["browser_translations_full_page_reader_mode.js"] - -["browser_translations_full_page_telemetry_auto_translate.js"] - -["browser_translations_full_page_telemetry_basics.js"] - -["browser_translations_full_page_telemetry_open_panel.js"] - -["browser_translations_full_page_telemetry_panel_auto_offer.js"] - -["browser_translations_full_page_telemetry_panel_auto_offer_settings.js"] - -["browser_translations_full_page_telemetry_retranslate.js"] - -["browser_translations_full_page_telemetry_switch_languages.js"] - -["browser_translations_full_page_telemetry_translation_failure.js"] - -["browser_translations_full_page_telemetry_translation_request.js"] - -["browser_translations_full_page_telemetry_unsupported_lang.js"] - -["browser_translations_recent_language_memory_auto_translate.js"] - -["browser_translations_recent_language_memory_full_page_and_select.js"] - -["browser_translations_recent_language_memory_full_page_and_select_multi_window.js"] -skip-if = ["os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && ccov"] # Bug 1972458 - -["browser_translations_recent_language_memory_full_page_multi_window.js"] - -["browser_translations_recent_language_memory_full_page_multi_window_multi_tab.js"] - -["browser_translations_recent_language_memory_full_page_navigate.js"] - -["browser_translations_recent_language_memory_full_page_retranslate.js"] - -["browser_translations_select_context_menu_engine_unsupported.js"] - -["browser_translations_select_context_menu_feature_disabled.js"] - -["browser_translations_select_context_menu_preferred_app_locales.js"] - -["browser_translations_select_context_menu_preferred_language_edge_cases.js"] - -["browser_translations_select_context_menu_preferred_web_languages.js"] - -["browser_translations_select_context_menu_with_full_page_translations_active.js"] - -["browser_translations_select_context_menu_with_hyperlink.js"] - -["browser_translations_select_context_menu_with_no_text_selected.js"] - -["browser_translations_select_context_menu_with_text_selected.js"] - -["browser_translations_select_panel_a11y_utils.js"] - -["browser_translations_select_panel_change_app_locale.js"] - -["browser_translations_select_panel_close_on_new_tab.js"] - -["browser_translations_select_panel_copy_button.js"] - -["browser_translations_select_panel_engine_cache.js"] - -["browser_translations_select_panel_fallback_to_doc_language.js"] - -["browser_translations_select_panel_flip_lexical_shortlist.js"] - -["browser_translations_select_panel_init_failure.js"] - -["browser_translations_select_panel_modify_available_language_models.js"] - -["browser_translations_select_panel_pdf.js"] - -["browser_translations_select_panel_reader_mode.js"] - -["browser_translations_select_panel_retranslate_on_change_language_directly.js"] - -["browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js"] - -["browser_translations_select_panel_script_tags.js"] - -["browser_translations_select_panel_select_current_language_directly.js"] - -["browser_translations_select_panel_select_current_language_from_dropdown_menu.js"] - -["browser_translations_select_panel_select_same_from_and_to_languages_directly.js"] - -["browser_translations_select_panel_select_same_from_and_to_languages_from_dropdown_menu.js"] - -["browser_translations_select_panel_settings_menu.js"] - -["browser_translations_select_panel_translate_full_page_button.js"] - -["browser_translations_select_panel_translate_on_change_language_directly.js"] - -["browser_translations_select_panel_translate_on_change_language_from_dropdown_menu.js"] - -["browser_translations_select_panel_translate_on_change_language_multiple_times_directly.js"] - -["browser_translations_select_panel_translate_on_change_language_multiple_times_from_dropdown_menu.js"] - -["browser_translations_select_panel_translate_on_open.js"] - -["browser_translations_select_panel_translation_failure_after_unsupported_language.js"] - -["browser_translations_select_panel_translation_failure_on_open.js"] - -["browser_translations_select_panel_translation_failure_on_retranslate.js"] - -["browser_translations_select_panel_unsupported_language.js"] - -["browser_translations_select_telemetry_change_both_languages_together.js"] - -["browser_translations_select_telemetry_change_languages_multiple_times.js"] - -["browser_translations_select_telemetry_init_failure_ui_then_cancel.js"] - -["browser_translations_select_telemetry_init_failure_ui_then_succeed.js"] - -["browser_translations_select_telemetry_keypresses_cancel_button.js"] - -["browser_translations_select_telemetry_keypresses_copy_button.js"] - -["browser_translations_select_telemetry_keypresses_done_button.js"] - -["browser_translations_select_telemetry_keypresses_settings_button.js"] - -["browser_translations_select_telemetry_keypresses_translate_button.js"] - -["browser_translations_select_telemetry_keypresses_translate_full_page_button.js"] - -["browser_translations_select_telemetry_keypresses_try_again_button_init_failure.js"] - -["browser_translations_select_telemetry_keypresses_try_again_button_translation_failure.js"] - -["browser_translations_select_telemetry_multi_page.js"] - -["browser_translations_select_telemetry_primary_ui.js"] - -["browser_translations_select_telemetry_settings_menu.js"] - -["browser_translations_select_telemetry_translation_failure_ui_then_cancel.js"] - -["browser_translations_select_telemetry_translation_failure_ui_then_succeed.js"] - -["browser_translations_select_telemetry_translation_failure_with_full_page_translations_active.js"] - -["browser_translations_select_telemetry_translation_success_with_full_page_translations_active.js"] - -["browser_translations_select_telemetry_unsupported_language_ui.js"] diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_manage_downloaded_languages.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_manage_downloaded_languages.js deleted file mode 100644 index a6d7cce5f9..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_manage_downloaded_languages.js +++ /dev/null @@ -1,225 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -function getFrenchModels() { - return languageModelNames([ - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ]); -} - -add_task(async function test_about_preferences_manage_languages() { - await testWithAndWithoutLexicalShortlist(async lexicalShortlistPrefs => { - const { - cleanup, - remoteClients, - elements: { - downloadAllLabel, - downloadAll, - deleteAll, - frenchLabel, - frenchDownload, - frenchDelete, - spanishLabel, - spanishDownload, - spanishDelete, - ukrainianLabel, - ukrainianDownload, - ukrainianDelete, - }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [ - ["browser.translations.newSettingsUI.enable", false], - ...lexicalShortlistPrefs, - ], - }); - - is( - downloadAllLabel.getAttribute("data-l10n-id"), - "translations-manage-download-description", - "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."); - is(ukrainianLabel.textContent, "Ukrainian", "There is a Ukrainian row."); - - await ensureVisibility({ - message: "Everything starts out as available to download", - visible: { - downloadAll, - frenchDownload, - spanishDownload, - ukrainianDownload, - }, - hidden: { deleteAll, frenchDelete, spanishDelete, ukrainianDelete }, - }); - - click(frenchDownload, "Downloading French"); - - const frenchModels = getFrenchModels(); - - Assert.deepEqual( - await remoteClients.translationModels.resolvePendingDownloads( - frenchModels.length - ), - frenchModels, - "French models were downloaded." - ); - - await ensureVisibility({ - message: "French can now be deleted, and delete all is available.", - visible: { - downloadAll, - deleteAll, - frenchDelete, - spanishDownload, - ukrainianDownload, - }, - hidden: { frenchDownload, spanishDelete, ukrainianDelete }, - }); - - click(frenchDelete, "Deleting French"); - - await ensureVisibility({ - message: "Everything can be downloaded.", - visible: { - downloadAll, - frenchDownload, - spanishDownload, - ukrainianDownload, - }, - hidden: { deleteAll, frenchDelete, spanishDelete, ukrainianDelete }, - }); - - click(downloadAll, "Downloading all languages."); - - const allModels = languageModelNames(LANGUAGE_PAIRS); - Assert.deepEqual( - await remoteClients.translationModels.resolvePendingDownloads( - allModels.length - ), - allModels, - "All models were downloaded." - ); - Assert.deepEqual( - await remoteClients.translationsWasm.resolvePendingDownloads(1), - ["bergamot-translator"], - "Wasm was downloaded." - ); - - await ensureVisibility({ - message: "Everything can be deleted.", - visible: { deleteAll, frenchDelete, spanishDelete, ukrainianDelete }, - hidden: { - downloadAll, - frenchDownload, - spanishDownload, - ukrainianDownload, - }, - }); - - click(deleteAll, "Deleting all languages."); - - await ensureVisibility({ - message: "Everything can be downloaded again", - visible: { - downloadAll, - frenchDownload, - spanishDownload, - ukrainianDownload, - }, - hidden: { deleteAll, frenchDelete, spanishDelete, ukrainianDelete }, - }); - - click(frenchDownload, "Downloading French."); - click(spanishDownload, "Downloading Spanish."); - click(ukrainianDownload, "Downloading Ukrainian."); - - Assert.deepEqual( - await remoteClients.translationModels.resolvePendingDownloads( - allModels.length - ), - allModels, - "All models were downloaded again." - ); - - remoteClients.translationsWasm.assertNoNewDownloads(); - - await ensureVisibility({ - message: "Everything is downloaded again.", - visible: { deleteAll, frenchDelete, spanishDelete, ukrainianDelete }, - hidden: { - downloadAll, - frenchDownload, - spanishDownload, - ukrainianDownload, - }, - }); - - await cleanup(); - }); -}); - -add_task(async function test_about_preferences_download_reject() { - const { - cleanup, - remoteClients, - elements: { document, frenchDownload }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", false]], - }); - - click(frenchDownload, "Downloading French"); - - is( - maybeGetByL10nId("translations-manage-error-download", document), - null, - "No error messages are present." - ); - - const failureErrors = await captureTranslationsError(() => - remoteClients.translationModels.rejectPendingDownloads( - getFrenchModels().length - ) - ); - - ok( - !!failureErrors.length, - `The errors for download should have been reported, found ${failureErrors.length} errors` - ); - for (const { error } of failureErrors) { - is( - error?.message, - "Failed to download file.", - "The error reported was a download error." - ); - } - - await 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." - ); - - const successErrors = await captureTranslationsError(() => - remoteClients.translationModels.resolvePendingDownloads( - getFrenchModels().length - ) - ); - - is( - successErrors.length, - 0, - "Expected no errors downloading French the second time" - ); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_always_translate_languages.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_always_translate_languages.js deleted file mode 100644 index 9f40003bfc..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_always_translate_languages.js +++ /dev/null @@ -1,97 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_task( - async function test_about_preferences_always_translate_language_settings() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", false]], - }); - - info("Ensuring the list of always-translate languages is empty"); - is( - getAlwaysTranslateLanguagesFromPref().length, - 0, - "The list of always-translate languages is empty" - ); - - info("Adding two languages to the alwaysTranslateLanguages pref"); - Services.prefs.setCharPref(ALWAYS_TRANSLATE_LANGS_PREF, "fr,de"); - - const dialogWindow = await waitForOpenDialogWindow( - "chrome://browser/content/preferences/dialogs/translations.xhtml", - () => { - click( - settingsButton, - "Opening the about:preferences Translations Settings" - ); - } - ); - let tree = dialogWindow.document.getElementById( - "alwaysTranslateLanguagesTree" - ); - let remove = dialogWindow.document.getElementById( - "removeAlwaysTranslateLanguage" - ); - let removeAll = dialogWindow.document.getElementById( - "removeAllAlwaysTranslateLanguages" - ); - - is( - tree.view.rowCount, - 2, - "The always-translate languages list has 2 items" - ); - ok(remove.disabled, "The 'Remove Language' button is disabled"); - ok(!removeAll.disabled, "The 'Remove All Languages' button is enabled"); - - info("Selecting the first always-translate language."); - tree.view.selection.select(0); - ok(!remove.disabled, "The 'Remove Language' button is enabled"); - - click(remove, "Clicking the remove-language button"); - is( - tree.view.rowCount, - 1, - "The always-translate languages list now contains 1 item" - ); - is( - getAlwaysTranslateLanguagesFromPref().length, - 1, - "One language tag in the pref" - ); - - info("Removing all languages from the alwaysTranslateLanguages pref"); - Services.prefs.setCharPref(ALWAYS_TRANSLATE_LANGS_PREF, ""); - is(tree.view.rowCount, 0, "The always-translate languages list is empty"); - ok(remove.disabled, "The 'Remove Language' button is disabled"); - ok(removeAll.disabled, "The 'Remove All Languages' button is disabled"); - - info("Adding more languages to the alwaysTranslateLanguages pref"); - Services.prefs.setCharPref(ALWAYS_TRANSLATE_LANGS_PREF, "fr,en,es"); - is( - tree.view.rowCount, - 3, - "The always-translate languages list has 3 items" - ); - ok(remove.disabled, "The 'Remove Language' button is disabled"); - ok(!removeAll.disabled, "The 'Remove All Languages' button is enabled"); - - click(removeAll, "Clicking the remove-all languages button"); - is(tree.view.rowCount, 0, "The always-translate languages list is empty"); - ok(remove.disabled, "The 'Remove Language' button is disabled"); - ok(removeAll.disabled, "The 'Remove All Languages' button is disabled"); - is( - getAlwaysTranslateLanguagesFromPref().length, - 0, - "There are no languages in the alwaysTranslateLanguages pref" - ); - - await waitForCloseDialogWindow(dialogWindow); - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_all_ui.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_all_ui.js deleted file mode 100644 index f9e7aab9fb..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_all_ui.js +++ /dev/null @@ -1,159 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_task(async function test_translations_settings_download_languages_all() { - const { - cleanup, - remoteClients, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - const frenchModels = languageModelNames([ - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ]); - - const spanishModels = languageModelNames([ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - ]); - - const ukrainianModels = languageModelNames([ - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ]); - - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - const { downloadLanguageList } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - info( - "Install each language French, Spanish and Ukrainian and check if All language state changes to 'all language downloaded' by changing the all language button icon to 'remove icon'" - ); - - info("Download French language model."); - let langFr = Array.from(downloadLanguageList.querySelectorAll("label")).find( - el => el.getAttribute("value") === "fr" - ); - - let clickButton = BrowserTestUtils.waitForEvent( - langFr.parentNode.querySelector("moz-button"), - "click" - ); - langFr.parentNode.querySelector("moz-button").click(); - await clickButton; - - Assert.deepEqual( - await remoteClients.translationModels.resolvePendingDownloads( - frenchModels.length - ), - frenchModels, - "French models were downloaded." - ); - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langFr, - "translations-settings-remove-icon", - "Delete icon is visible for French language hence downloaded" - ); - - info("Download Spanish language model."); - - let langEs = Array.from(downloadLanguageList.querySelectorAll("label")).find( - el => el.getAttribute("value") === "es" - ); - - clickButton = BrowserTestUtils.waitForEvent( - langEs.parentNode.querySelector("moz-button"), - "click" - ); - langEs.parentNode.querySelector("moz-button").click(); - await clickButton; - - Assert.deepEqual( - await remoteClients.translationModels.resolvePendingDownloads( - spanishModels.length - ), - spanishModels, - "Spanish models were downloaded." - ); - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langEs, - "translations-settings-remove-icon", - "Delete icon is visible for Spanish language hence downloaded" - ); - - info("Download Ukrainian language model."); - - let langUk = Array.from(downloadLanguageList.querySelectorAll("label")).find( - el => el.getAttribute("value") === "uk" - ); - - clickButton = BrowserTestUtils.waitForEvent( - langUk.parentNode.querySelector("moz-button"), - "click" - ); - langUk.parentNode.querySelector("moz-button").click(); - await clickButton; - - Assert.deepEqual( - await remoteClients.translationModels.resolvePendingDownloads( - ukrainianModels.length - ), - ukrainianModels, - "Ukrainian models were downloaded." - ); - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langUk, - "translations-settings-remove-icon", - "Delete icon is visible for Ukranian language hence downloaded." - ); - - // Download "All languages" is the first child - let langAll = downloadLanguageList.children[0]; - - ok( - langAll - .querySelector("moz-button") - .classList.contains("translations-settings-remove-icon"), - "Delete icon is visible for All Languages after all individual language models were downloaded." - ); - - info( - "Remove one language ensure that All Languages change state changes to 'removed' to indicate that all languages are not downloaded." - ); - - info("Remove Spanish language model."); - langEs.parentNode.querySelector("moz-button").click(); - await clickButton; - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langEs, - "translations-settings-download-icon", - "Download icon is visible for Spanish language hence removed" - ); - - ok( - langAll - .querySelector("moz-button") - .classList.contains("translations-settings-download-icon"), - "Download icon is visible for all languages i.e. all languages are not downloaded since one language, Spanish was removed." - ); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_error_ui.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_error_ui.js deleted file mode 100644 index 3406256b93..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_error_ui.js +++ /dev/null @@ -1,173 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_task( - async function test_translations_settings_download_languages_error_handling() { - const { - cleanup, - remoteClients, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - const frenchModels = languageModelNames([ - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ]); - - const spanishModels = languageModelNames([ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - ]); - - const allModels = languageModelNames(LANGUAGE_PAIRS); - - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - const { downloadLanguageList } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - info("Test French language model for download error"); - - let langFr = Array.from( - downloadLanguageList.querySelectorAll("label") - ).find(el => el.getAttribute("value") === "fr"); - - let clickButton = BrowserTestUtils.waitForEvent( - langFr.parentNode.querySelector("moz-button"), - "click" - ); - langFr.parentNode.querySelector("moz-button").click(); - await clickButton; - - await captureTranslationsError(() => - remoteClients.translationModels.rejectPendingDownloads( - frenchModels.length - ) - ); - - const errorElement = gBrowser.selectedBrowser.contentDocument.querySelector( - ".translations-settings-language-error" - ); - - assertVisibility({ - message: "Moz-message-bar with error message is visible", - visible: { errorElement }, - }); - is( - document.l10n.getAttributes(errorElement).id, - "translations-settings-language-download-error", - "Error message correctly shows download error" - ); - is( - document.l10n.getAttributes(errorElement).args.name, - "French", - "Error message correctly shows download error for French language" - ); - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langFr, - "translations-settings-download-icon", - "Download icon is visible on French button" - ); - - remoteClients.translationsWasm.assertNoNewDownloads(); - - info("Download Spanish language model successfully."); - - let langEs = Array.from( - downloadLanguageList.querySelectorAll("label") - ).find(el => el.getAttribute("value") === "es"); - - clickButton = BrowserTestUtils.waitForEvent( - langEs.parentNode.querySelector("moz-button"), - "click" - ); - langEs.parentNode.querySelector("moz-button").click(); - await clickButton; - - const errorElementEs = - gBrowser.selectedBrowser.contentDocument.querySelector( - ".translations-settings-language-error" - ); - - ok( - !errorElementEs, - "Previous error is remove when new action occured, i.e. click download Spanish button" - ); - - Assert.deepEqual( - await remoteClients.translationModels.resolvePendingDownloads( - spanishModels.length - ), - spanishModels, - "Spanish models were downloaded." - ); - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langEs, - "translations-settings-remove-icon", - "Delete icon is visible for Spanish language hence downloaded" - ); - - info("Test All language models download error"); - // Download "All languages" is the first child - let langAll = downloadLanguageList.children[0]; - - let clickButtonAll = BrowserTestUtils.waitForEvent( - langAll.querySelector("moz-button"), - "click" - ); - langAll.querySelector("moz-button").click(); - await clickButtonAll; - - await captureTranslationsError(() => - remoteClients.translationModels.rejectPendingDownloads(allModels.length) - ); - - await captureTranslationsError(() => - remoteClients.translationsWasm.rejectPendingDownloads(allModels.length) - ); - - remoteClients.translationsWasm.assertNoNewDownloads(); - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langAll, - "translations-settings-download-icon", - "Download icon is visible for 'all languages'" - ); - - const errorElementAll = - gBrowser.selectedBrowser.contentDocument.querySelector( - ".translations-settings-language-error" - ); - - assertVisibility({ - message: "Moz-message-bar with error message is visible", - visible: { errorElementAll }, - }); - is( - document.l10n.getAttributes(errorElementAll).id, - "translations-settings-language-download-error", - "Error message correctly shows download error" - ); - is( - document.l10n.getAttributes(errorElementAll).args.name, - "all", - "Error message correctly shows download error for all language" - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_ui.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_ui.js deleted file mode 100644 index 8bc0301f14..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_download_languages_ui.js +++ /dev/null @@ -1,117 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_task(async function test_translations_settings_download_languages() { - await testWithAndWithoutLexicalShortlist(async lexicalShortlistPrefs => { - const { - cleanup, - remoteClients, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [ - ["browser.translations.newSettingsUI.enable", true], - ...lexicalShortlistPrefs, - ], - }); - - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - const { downloadLanguageList } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - info("Test French language model install and uninstall function."); - - let langFr = Array.from( - downloadLanguageList.querySelectorAll("label") - ).find(el => el.getAttribute("value") === "fr"); - - let clickButton = BrowserTestUtils.waitForEvent( - langFr.parentNode.querySelector("moz-button"), - "click" - ); - langFr.parentNode.querySelector("moz-button").click(); - await clickButton; - - const frenchModels = languageModelNames([ - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ]); - - Assert.deepEqual( - await remoteClients.translationModels.resolvePendingDownloads( - frenchModels.length - ), - frenchModels, - "French models were downloaded." - ); - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langFr, - "translations-settings-remove-icon", - "Delete icon is visible on French button." - ); - - langFr.parentNode.querySelector("moz-button").click(); - await clickButton; - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langFr, - "translations-settings-download-icon", - "Download icon is visible on French Button." - ); - - info("Test 'All language' models install and uninstall function"); - - // Download "All languages" is the first child - let langAll = downloadLanguageList.children[0]; - - let clickButtonAll = BrowserTestUtils.waitForEvent( - langAll.querySelector("moz-button"), - "click" - ); - langAll.querySelector("moz-button").click(); - await clickButtonAll; - - const allModels = languageModelNames(LANGUAGE_PAIRS); - - Assert.deepEqual( - await remoteClients.translationModels.resolvePendingDownloads( - allModels.length - ), - allModels, - "All models were downloaded." - ); - Assert.deepEqual( - await remoteClients.translationsWasm.resolvePendingDownloads(1), - ["bergamot-translator"], - "Wasm was downloaded." - ); - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langAll, - "translations-settings-remove-icon", - "Delete icon is visible on 'All languages' button" - ); - - langAll.querySelector("moz-button").click(); - await clickButton; - - await TranslationsSettingsTestUtils.downaloadButtonClick( - langAll, - "translations-settings-download-icon", - "Download icon is visible on 'All Language' button." - ); - - await cleanup(); - }); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_languages.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_languages.js deleted file mode 100644 index 758cfb4fba..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_languages.js +++ /dev/null @@ -1,89 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_task( - async function test_about_preferences_never_translate_language_settings() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", false]], - }); - - info("Ensuring the list of never-translate languages is empty"); - is( - getNeverTranslateLanguagesFromPref().length, - 0, - "The list of never-translate languages is empty" - ); - - info("Adding two languages to the neverTranslateLanguages pref"); - Services.prefs.setCharPref(NEVER_TRANSLATE_LANGS_PREF, "fr,de"); - - const dialogWindow = await waitForOpenDialogWindow( - "chrome://browser/content/preferences/dialogs/translations.xhtml", - () => { - click( - settingsButton, - "Opening the about:preferences Translations Settings" - ); - } - ); - let tree = dialogWindow.document.getElementById( - "neverTranslateLanguagesTree" - ); - let remove = dialogWindow.document.getElementById( - "removeNeverTranslateLanguage" - ); - let removeAll = dialogWindow.document.getElementById( - "removeAllNeverTranslateLanguages" - ); - - is(tree.view.rowCount, 2, "The never-translate languages list has 2 items"); - ok(remove.disabled, "The 'Remove Language' button is disabled"); - ok(!removeAll.disabled, "The 'Remove All Languages' button is enabled"); - - info("Selecting the first never-translate language."); - tree.view.selection.select(0); - ok(!remove.disabled, "The 'Remove Language' button is enabled"); - - click(remove, "Clicking the remove-language button"); - is( - tree.view.rowCount, - 1, - "The never-translate languages list now contains 1 item" - ); - is( - getNeverTranslateLanguagesFromPref().length, - 1, - "One language tag in the pref" - ); - - info("Removing all languages from the neverTranslateLanguages pref"); - Services.prefs.setCharPref(NEVER_TRANSLATE_LANGS_PREF, ""); - is(tree.view.rowCount, 0, "The never-translate languages list is empty"); - ok(remove.disabled, "The 'Remove Language' button is disabled"); - ok(removeAll.disabled, "The 'Remove All Languages' button is disabled"); - - info("Adding more languages to the neverTranslateLanguages pref"); - Services.prefs.setCharPref(NEVER_TRANSLATE_LANGS_PREF, "fr,en,es"); - is(tree.view.rowCount, 3, "The never-translate languages list has 3 items"); - ok(remove.disabled, "The 'Remove Language' button is disabled"); - ok(!removeAll.disabled, "The 'Remove All Languages' button is enabled"); - - click(removeAll, "Clicking the remove-all languages button"); - is(tree.view.rowCount, 0, "The never-translate languages list is empty"); - ok(remove.disabled, "The 'Remove Language' button is disabled"); - ok(removeAll.disabled, "The 'Remove All Languages' button is disabled"); - is( - getNeverTranslateLanguagesFromPref().length, - 0, - "There are no languages in the neverTranslateLanguages pref" - ); - - await waitForCloseDialogWindow(dialogWindow); - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_sites.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_sites.js deleted file mode 100644 index dea7b1c473..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_never_translate_sites.js +++ /dev/null @@ -1,124 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -const { PermissionTestUtils } = ChromeUtils.importESModule( - "resource://testing-common/PermissionTestUtils.sys.mjs" -); - -add_task(async function test_about_preferences_never_translate_site_settings() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", false]], - permissionsUrls: [ - "https://example.com", - "https://example.org", - "https://example.net", - ], - }); - - info("Ensuring the list of never-translate sites is empty"); - is( - getNeverTranslateSitesFromPerms().length, - 0, - "The list of never-translate sites is empty" - ); - - info("Adding two sites to the neverTranslateSites perms"); - PermissionTestUtils.add( - "https://example.com", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - PermissionTestUtils.add( - "https://example.org", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - PermissionTestUtils.add( - "https://example.net", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - - const dialogWindow = await waitForOpenDialogWindow( - "chrome://browser/content/preferences/dialogs/translations.xhtml", - () => { - click( - settingsButton, - "Opening the about:preferences Translations Settings" - ); - } - ); - let tree = dialogWindow.document.getElementById("neverTranslateSitesTree"); - let remove = dialogWindow.document.getElementById("removeNeverTranslateSite"); - let removeAll = dialogWindow.document.getElementById( - "removeAllNeverTranslateSites" - ); - - is(tree.view.rowCount, 3, "The never-translate sites list has 2 items"); - ok(remove.disabled, "The 'Remove Site' button is disabled"); - ok(!removeAll.disabled, "The 'Remove All Sites' button is enabled"); - - info("Selecting the first never-translate site."); - tree.view.selection.select(0); - ok(!remove.disabled, "The 'Remove Site' button is enabled"); - - click(remove, "Clicking the remove-site button"); - is( - tree.view.rowCount, - 2, - "The never-translate sites list now contains 2 items" - ); - is( - getNeverTranslateSitesFromPerms().length, - 2, - "There are 2 sites with permissions" - ); - - info("Removing all sites from the neverTranslateSites perms"); - PermissionTestUtils.remove("https://example.com", TRANSLATIONS_PERMISSION); - PermissionTestUtils.remove("https://example.org", TRANSLATIONS_PERMISSION); - PermissionTestUtils.remove("https://example.net", TRANSLATIONS_PERMISSION); - - is(tree.view.rowCount, 0, "The never-translate sites list is empty"); - ok(remove.disabled, "The 'Remove Site' button is disabled"); - ok(removeAll.disabled, "The 'Remove All Sites' button is disabled"); - - info("Adding more sites to the neverTranslateSites perms"); - PermissionTestUtils.add( - "https://example.org", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - PermissionTestUtils.add( - "https://example.com", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - PermissionTestUtils.add( - "https://example.net", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - - is(tree.view.rowCount, 3, "The never-translate sites list has 3 items"); - ok(remove.disabled, "The 'Remove Site' button is disabled"); - ok(!removeAll.disabled, "The 'Remove All Sites' button is enabled"); - - click(removeAll, "Clicking the remove-all sites button"); - is(tree.view.rowCount, 0, "The never-translate sites list is empty"); - ok(remove.disabled, "The 'Remove Site' button is disabled"); - ok(removeAll.disabled, "The 'Remove All Sites' button is disabled"); - is( - getNeverTranslateSitesFromPerms().length, - 0, - "There are no sites in the neverTranslateSites perms" - ); - - await waitForCloseDialogWindow(dialogWindow); - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui.js deleted file mode 100644 index 733b3822b5..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui.js +++ /dev/null @@ -1,462 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_task(async function test_translations_settings_pane_elements() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - const { - translationsSettingsBackButton, - translationsSettingsHeader, - translationsSettingsDescription, - translateAlwaysHeader, - translateNeverHeader, - alwaysTranslateMenuList, - neverTranslateMenuList, - translateNeverSiteHeader, - translateNeverSiteDesc, - downloadLanguageSection, - translateDownloadLanguagesLearnMore, - } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - const translateDownloadLanguagesHeader = - downloadLanguageSection.querySelector("h2"); - assertVisibility({ - message: "Expect paneTranslations elements to be visible.", - visible: { - translationsSettingsBackButton, - translationsSettingsHeader, - translationsSettingsDescription, - translateAlwaysHeader, - translateNeverHeader, - alwaysTranslateMenuList, - neverTranslateMenuList, - translateNeverSiteHeader, - translateNeverSiteDesc, - translateDownloadLanguagesLearnMore, - }, - hidden: { - settingsButton, - }, - }); - - info( - "In translations settings page, click on back button to go back to main preferences page." - ); - const paneEvent = BrowserTestUtils.waitForEvent( - document, - "paneshown", - false, - event => event.detail.category === "paneGeneral" - ); - - click(translationsSettingsBackButton); - await paneEvent; - - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { - settingsButton, - }, - hidden: { - translationsSettingsBackButton, - translationsSettingsHeader, - translationsSettingsDescription, - translateAlwaysHeader, - translateNeverHeader, - alwaysTranslateMenuList, - neverTranslateMenuList, - translateNeverSiteHeader, - translateNeverSiteDesc, - translateDownloadLanguagesHeader, - translateDownloadLanguagesLearnMore, - }, - }); - await cleanup(); -}); - -add_task(async function test_translations_settings_always_translate() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - const { - alwaysTranslateMenuList, - alwaysTranslateLanguageList, - alwaysTranslateMenuPopup, - } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - info("Testing the Always translate langauge settings"); - await testLanguageList( - alwaysTranslateLanguageList, - alwaysTranslateMenuList, - alwaysTranslateMenuPopup, - ALWAYS_TRANSLATE_LANGS_PREF, - "Always" - ); - await testLanguageListWithPref( - alwaysTranslateLanguageList, - ALWAYS_TRANSLATE_LANGS_PREF, - "Always" - ); - - await cleanup(); -}); - -add_task(async function test_translations_settings_never_translate() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - const { - neverTranslateMenuList, - neverTranslateLanguageList, - neverTranslateMenuPopup, - } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - info("Testing the Never translate langauge settings"); - await testLanguageList( - neverTranslateLanguageList, - neverTranslateMenuList, - neverTranslateMenuPopup, - NEVER_TRANSLATE_LANGS_PREF, - "Never" - ); - await testLanguageListWithPref( - neverTranslateLanguageList, - NEVER_TRANSLATE_LANGS_PREF, - "Never" - ); - await cleanup(); -}); -function getLangsFromPref(pref) { - let rawLangs = Services.prefs.getCharPref(pref); - if (!rawLangs) { - return []; - } - let langArr = rawLangs.split(","); - return langArr; -} - -async function testLanguageList( - languageList, - menuList, - menuPopup, - pref, - sectionName -) { - info("Ensure the Always/Never list is empty initially."); - - is( - languageList.childElementCount, - 0, - `Language list empty in ${sectionName} Translate list` - ); - - const menuItems = menuPopup.children; - - info( - "Click each language on the menulist to add it into the Always/Never list." - ); - for (const menuItem of menuItems) { - menuList.open = true; - - let clickMenu = BrowserTestUtils.waitForEvent( - menuList.querySelector("menupopup"), - "popuphidden" - ); - click(menuItem); - menuList.querySelector("menupopup").hidePopup(); - await clickMenu; - - /** Languages are always added on the top, so check the firstChild - * for newly added languages. - * the firstChild.querySelector("label").innerText is the language display name - * which is compared with the menulist display name that is selected - */ - let langElem = languageList.firstElementChild; - const displayName = getIntlDisplayName(menuItem.value); - is( - langElem.querySelector("label").innerText, - displayName, - `Language list has element ${displayName}` - ); - - const langTag = langElem.querySelector("label").getAttribute("value"); - ok( - getLangsFromPref(pref).includes(langTag), - `Perferences contains ${langTag}` - ); - } - /** The test cases has 4 languages, so check if 4 languages are added to the list */ - let langNum = languageList.childElementCount; - is(langNum, 4, "Number of languages added is 4"); - - info( - "Remove each language from the Always/Never list that we added initially." - ); - for (let i = 0; i < langNum; i++) { - // Delete the first language in the list - let langElem = languageList.children[0]; - let langName = langElem.querySelector("label").innerText; - const langTag = langElem.querySelector("label").getAttribute("value"); - let langButton = langElem.querySelector("moz-button"); - let clickButton = BrowserTestUtils.waitForEvent(langButton, "click"); - langButton.click(); - await clickButton; - - ok( - !getLangsFromPref(pref).includes(langTag), - `Perferences does not contain ${langTag}` - ); - - if (i < langNum) { - is( - languageList.childElementCount, - langNum - i - 1, - `${langName} removed from ${sectionName} Translate` - ); - } - } -} - -async function testLanguageListWithPref(languageList, pref, sectionName) { - const langs = [ - "fr", - "de", - "en", - "es", - "fr,de", - "fr,en", - "fr,es", - "de,en", - "de,en,es", - "es,fr,en", - "en,es,fr,de", - ]; - - info("Ensure the Always/Never list is empty initially."); - - is( - languageList.childElementCount, - 0, - `Language list is empty in ${sectionName} Translate list` - ); - - info( - "Add languages to the Always/Never list in translations setting by setting the ALWAYS_TRANSLATE_LANGS_PREF/NEVER_TRANSLATE_LANGS_PREF." - ); - - for (const langOptions of langs) { - Services.prefs.setCharPref(pref, langOptions); - - /** Languages are always added on the top, so check the firstChild - * for newly added languages. - * the firstChild.querySelector("label").innerText is the language display name - * which is compared with the menulist display name that is selected - */ - - const langsAdded = langOptions.split(","); - is( - languageList.childElementCount, - langsAdded.length, - `Language list has ${langsAdded.length} elements ` - ); - - let langsAddedHtml = Array.from(languageList.querySelectorAll("label")); - - for (const lang of langsAdded) { - const langFind = langsAddedHtml - .find(el => el.getAttribute("value") === lang) - .getAttribute("value"); - is(langFind, lang, `Language list has element ${lang}`); - } - } - - Services.prefs.setCharPref(pref, ""); - is( - languageList.childElementCount, - 0, - `All removed from ${sectionName} Translate` - ); -} - -const { PermissionTestUtils } = ChromeUtils.importESModule( - "resource://testing-common/PermissionTestUtils.sys.mjs" -); - -add_task(async function test_translations_settings_never_translate_site() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - const { neverTranslateSiteList } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - info("Ensuring the list of never-translate sites is empty"); - is( - getNeverTranslateSitesFromPerms().length, - 0, - "The list of never-translate sites is empty" - ); - - is( - neverTranslateSiteList.childElementCount, - 0, - "The never-translate sites html list is empty" - ); - - info("Adding sites to the neverTranslateSites perms"); - await PermissionTestUtils.add( - "https://example.com", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - await PermissionTestUtils.add( - "https://example.org", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - await PermissionTestUtils.add( - "https://example.net", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - - is( - getNeverTranslateSitesFromPerms().length, - 3, - "The list of never-translate sites has 3 elements" - ); - - is( - neverTranslateSiteList.childElementCount, - 3, - "The never-translate sites html list has 3 elements" - ); - - const permissionsUrls = [ - "https://example.com", - "https://example.org", - "https://example.net", - ]; - - info( - "Ensure that the Never translate sites in permissions settings are reflected in Never translate sites section of translations settings page" - ); - - const siteNum = neverTranslateSiteList.children.length; - for (let i = siteNum; i > 0; i--) { - is( - neverTranslateSiteList.children[i - 1].querySelector("label").textContent, - permissionsUrls[permissionsUrls.length - i], - `Never translate URL ${ - permissionsUrls[permissionsUrls.length - i] - } is added` - ); - } - - info( - "Delete each site by clicking the button in Never translate sites section of translations settings page and check if it is removed in the Never translate sites in permissions settings" - ); - for (let i = 0; i < siteNum; i++) { - // Delete the first site in the list - let siteElem = neverTranslateSiteList.children[0]; - // Delete the first language in the list - let siteName = siteElem.querySelector("label").innerText; - let siteButton = siteElem.querySelector("moz-button"); - - ok( - neverTranslateSiteList.querySelector(`label[value="${siteName}"]`), - `Site ${siteName} present in the Never transalate site list` - ); - - ok( - getNeverTranslateSitesFromPerms().find(p => p.origin === siteName), - `Site ${siteName} present in the Never transalate site permissions list` - ); - - let clickButton = BrowserTestUtils.waitForEvent(siteButton, "click"); - siteButton.click(); - await clickButton; - - ok( - !neverTranslateSiteList.querySelector(`label[value="${siteName}"]`), - `Site ${siteName} removed successfully from the Never transalate site list` - ); - - ok( - !getNeverTranslateSitesFromPerms().find(p => p.origin === siteName), - `Site ${siteName} removed from successfully from the Never transalate site permissions list` - ); - - if (i < siteNum) { - is( - neverTranslateSiteList.childElementCount, - siteNum - i - 1, - `${siteName} removed from Never Translate Site` - ); - } - const siteLen = siteNum - i - 1; - is( - getNeverTranslateSitesFromPerms().length, - siteLen, - `There are ${siteLen} site in Never translate site` - ); - } - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_keyboard_a11y.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_keyboard_a11y.js deleted file mode 100644 index b60344194f..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_keyboard_a11y.js +++ /dev/null @@ -1,635 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -const { PermissionTestUtils } = ChromeUtils.importESModule( - "resource://testing-common/PermissionTestUtils.sys.mjs" -); - -add_task(async function test_translations_settings_keyboard_a11y() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - const { - translationsSettingsBackButton, - alwaysTranslateMenuList, - neverTranslateMenuList, - translateDownloadLanguagesLearnMore, - downloadLanguageList, - } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - const document = gBrowser.selectedBrowser.contentDocument; - - info("Press the Tab key to focus the first page element, the back button"); - - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - translationsSettingsBackButton.id, - "Key is focused on back button" - ); - - info( - "Press the Tab key to focus the next page element, the Always Translate Menulist button" - ); - - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - alwaysTranslateMenuList.id, - "Key is focused on Always Translate Menulist button" - ); - - info( - "Press the Tab key to focus the next page element, the Never Translate Menulist button" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - neverTranslateMenuList.id, - "Key is focused on Never Translate Menulist button" - ); - - info( - "Press the Tab key to focus the next page element, the Download Languages' Learn More link" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - translateDownloadLanguagesLearnMore.id, - "Key is focused on Download Languages' Learn More link" - ); - - info( - "Press the Tab key to focus the next page element, the Download Languages list section" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - downloadLanguageList.id, - "Key is focused on Download Languages list section" - ); - - await cleanup(); -}); - -add_task(async function test_translations_settings_keyboard_download_a11y() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - const { - translationsSettingsBackButton, - alwaysTranslateMenuList, - neverTranslateMenuList, - translateDownloadLanguagesLearnMore, - downloadLanguageList, - } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - const document = gBrowser.selectedBrowser.contentDocument; - - info("Press the Tab key to focus the first page element, the back button"); - - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - translationsSettingsBackButton.id, - "Key is focused on back button" - ); - - info( - "Press the Tab key to focus the next page element, the Always Translate Menulist button" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - alwaysTranslateMenuList.id, - "Key is focused on Always Translate Menulist button" - ); - - info( - "Press the Tab key to focus the next page element, the Never Translate Menulist button" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - neverTranslateMenuList.id, - "Key is focused on Never Translate Menulist button" - ); - - info( - "Press the Tab key to focus the next page element, the Download Languages' Learn More link" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - translateDownloadLanguagesLearnMore.id, - "Key is focused on Download Languages' Learn More link" - ); - - info( - "Press the Tab key to focus the next page element, the Download Languages list section" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - downloadLanguageList.id, - "Key is focused on Download Languages list section" - ); - - info( - "Press the Arrow Down key to focus the first language element in the Download List Section" - ); - - for (let element of downloadLanguageList.children) { - info( - "Press the Arrow Down key to focus the next language element in the Download List Section" - ); - EventUtils.synthesizeKey("KEY_ArrowDown"); - is( - document.activeElement.parentNode.id, - element.id, - "Key is focused on the language " + - element.querySelector("label").textContent + - " within the language list" - ); - } - - is( - document.activeElement.parentNode.id, - downloadLanguageList.lastElementChild.id, - "Key is focused on the last language " + - downloadLanguageList.lastElementChild.querySelector("label").textContent + - " within the language list" - ); - - info( - "Press the Arrow up key to focus the previous language element in the Download List Section" - ); - for (let i = downloadLanguageList.children.length - 2; i >= 0; i--) { - info( - "Press the Arrow up key to focus the previous language element in the Download List Section" - ); - EventUtils.synthesizeKey("KEY_ArrowUp"); - is( - document.activeElement.parentNode.id, - downloadLanguageList.children[i].id, - "Key is focused on the language " + - downloadLanguageList.children[i].querySelector("label").textContent + - " within the language list" - ); - } - - is( - document.activeElement.parentNode.id, - downloadLanguageList.firstElementChild.id, - "Key is focused on the first language within the language list" - ); - - await cleanup(); -}); - -add_task( - async function test_translations_settings_keyboard_never_translate_site_a11y() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - const { - translationsSettingsBackButton, - alwaysTranslateMenuList, - neverTranslateMenuList, - neverTranslateSiteList, - translateDownloadLanguagesLearnMore, - } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - is( - neverTranslateSiteList.childElementCount, - 0, - "The never-translate sites html list is empty" - ); - - info("Adding sites to the neverTranslateSites perms"); - await PermissionTestUtils.add( - "https://example.com", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - await PermissionTestUtils.add( - "https://example.org", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - await PermissionTestUtils.add( - "https://example.net", - TRANSLATIONS_PERMISSION, - Services.perms.DENY_ACTION - ); - - is( - getNeverTranslateSitesFromPerms().length, - 3, - "The list of never-translate sites has 3 elements" - ); - - const document = gBrowser.selectedBrowser.contentDocument; - - info("Press the Tab key to focus the first page element, the back button"); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - translationsSettingsBackButton.id, - "Key is focused on back button" - ); - - info( - "Press the Tab key to focus the next page element, the Always Translate Menulist button" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - alwaysTranslateMenuList.id, - "Key is focused on Always Translate Menulist button" - ); - - info( - "Press the Tab key to focus the next page element, the Never Translate Menulist button" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - neverTranslateMenuList.id, - "Key focus is now Never Translate List Menu button" - ); - - info( - "Press the Tab key to focus the next page element, the Never Translate Site List section" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - neverTranslateSiteList.id, - "Key focus is now Never Translate Site List" - ); - info( - "Press the Arrow Down key to focus the first site element in the Never Translate Site List" - ); - for (const site of neverTranslateSiteList.children) { - info( - "Press the Arrow Down key to focus the next site element in the Never Translate Site List" - ); - EventUtils.synthesizeKey("KEY_ArrowDown"); - is( - document.activeElement.parentNode.id, - site.id, - "Key focus is now Never Translate Site list element " + - site.querySelector("label").textContent - ); - } - is( - document.activeElement.parentNode.id, - neverTranslateSiteList.lastElementChild.id, - "Key is focused on the last site " + - neverTranslateSiteList.lastElementChild.querySelector("label") - .textContent + - " within the site list" - ); - - info( - "Press the Arrow up key to focus the previous site element in the Never Translate Site List" - ); - for (let i = neverTranslateSiteList.children.length - 2; i >= 0; i--) { - info( - "Press the Arrow up key to focus the previous site element in the Never Translate Site List" - ); - EventUtils.synthesizeKey("KEY_ArrowUp"); - is( - document.activeElement.parentNode.id, - neverTranslateSiteList.children[i].id, - "Key is focused on the site " + - neverTranslateSiteList.children[i].querySelector("label") - .textContent + - " within the site list" - ); - } - - info( - "Press the Tab key to focus the next page element, the Download Languages' Learn More link" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - translateDownloadLanguagesLearnMore.id, - "Key is focused on Download Languages' Learn More link" - ); - - await cleanup(); - } -); - -add_task( - async function test_translations_settings_keyboard_never_translate_a11y() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - const { - translationsSettingsBackButton, - alwaysTranslateMenuList, - neverTranslateMenuList, - neverTranslateLanguageList, - neverTranslateMenuPopup, - translateDownloadLanguagesLearnMore, - } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - const document = gBrowser.selectedBrowser.contentDocument; - - info("Press the Tab key to focus the first page element, the back button"); - - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - translationsSettingsBackButton.id, - "Key is focused on back button" - ); - - info( - "Press the Tab key to focus the next page element, the Always Translate Menulist button" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - alwaysTranslateMenuList.id, - "Key is focused on Always Translate Menulist button" - ); - - info( - "Press the Tab key to focus the next page element, the Never Translate Menulist button." - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - neverTranslateMenuList.id, - "Key is focused on Never Translate Menulist button" - ); - - info("Press the Arrow Down key to focus on the first list element."); - for (const menuItem of neverTranslateMenuPopup.children) { - if (AppConstants.platform === "macosx") { - info("Opening the menu popup."); - const popupPromise = BrowserTestUtils.waitForEvent( - neverTranslateMenuPopup, - "popupshown" - ); - EventUtils.synthesizeKey("KEY_ArrowDown"); - await popupPromise; - } - - EventUtils.synthesizeKey("KEY_ArrowDown"); - - if (AppConstants.platform === "macosx") { - info("Closing the menu popup."); - const popupPromise = BrowserTestUtils.waitForEvent( - neverTranslateMenuPopup, - "popuphidden" - ); - EventUtils.synthesizeKey("KEY_Enter"); - await popupPromise; - } else { - const { promise, resolve } = Promise.withResolvers(); - requestAnimationFrame(() => { - requestAnimationFrame(resolve); - }); - - EventUtils.synthesizeKey("KEY_Enter"); - await promise; - } - - is( - neverTranslateLanguageList.firstElementChild.querySelector("label") - .textContent, - menuItem.textContent, - menuItem.textContent + "is added to never translate language" - ); - } - - info( - "Press the Tab key to focus the next page element, the Never Translate list" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - neverTranslateLanguageList.id, - document.activeElement.id, - "Key is focused on Always Translate list." - ); - - info("Press the Arrow Down key to focus on the first list element."); - - for (const lang of neverTranslateLanguageList.children) { - EventUtils.synthesizeKey("KEY_ArrowDown"); - is( - document.activeElement.parentNode.id, - lang.id, - "Key is focused on " + - lang.querySelector("label").textContent + - " element of Never Translate list." - ); - } - - info( - "Press the Tab key to focus the next page element, the Download Languages' Learn More link" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - translateDownloadLanguagesLearnMore.id, - "Key is focused on Download Languages' Learn More link" - ); - - await cleanup(); - } -); - -add_task( - async function test_translations_settings_keyboard_always_translate_a11y() { - const { - cleanup, - elements: { settingsButton }, - } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - info( - "Open translations settings page by clicking on translations settings button." - ); - assertVisibility({ - message: "Expect paneGeneral elements to be visible.", - visible: { settingsButton }, - }); - - const { - translationsSettingsBackButton, - alwaysTranslateMenuList, - neverTranslateMenuList, - alwaysTranslateLanguageList, - alwaysTranslateMenuPopup, - } = - await TranslationsSettingsTestUtils.openAboutPreferencesTranslationsSettingsPane( - settingsButton - ); - - const document = gBrowser.selectedBrowser.contentDocument; - - info("Press the Tab key to focus the first page element, the back button"); - - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - translationsSettingsBackButton.id, - "Key is focused on back button" - ); - - info( - "Press the Tab key to focus the next page element, the Always Translate Menulist button" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - alwaysTranslateMenuList.id, - "Key is focused on Always Translate Menulist button" - ); - - info("Press the Arrow Down key to focus on the first list element."); - for (const menuItem of alwaysTranslateMenuPopup.children) { - if (AppConstants.platform === "macosx") { - info("Opening the menu popup."); - const popupPromise = BrowserTestUtils.waitForEvent( - alwaysTranslateMenuPopup, - "popupshown" - ); - EventUtils.synthesizeKey("KEY_ArrowDown"); - await popupPromise; - } - - EventUtils.synthesizeKey("KEY_ArrowDown"); - - if (AppConstants.platform === "macosx") { - info("Closing the menu popup."); - const popupPromise = BrowserTestUtils.waitForEvent( - alwaysTranslateMenuPopup, - "popuphidden" - ); - EventUtils.synthesizeKey("KEY_Enter"); - await popupPromise; - } else { - const { promise, resolve } = Promise.withResolvers(); - requestAnimationFrame(() => { - requestAnimationFrame(resolve); - }); - - EventUtils.synthesizeKey("KEY_Enter"); - await promise; - } - - is( - alwaysTranslateLanguageList.firstElementChild.querySelector("label") - .textContent, - menuItem.textContent, - menuItem.textContent + "is added to always translate language" - ); - } - - info( - "Press the Tab key to focus the next page element, the Always Translate list" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - alwaysTranslateLanguageList.id, - document.activeElement.id, - "Key is focused on Always Translate list." - ); - - info("Press the Arrow Down key to focus on the first list element."); - - for (const lang of alwaysTranslateLanguageList.children) { - EventUtils.synthesizeKey("KEY_ArrowDown"); - is( - document.activeElement.parentNode.id, - lang.id, - "Key is focused on " + - lang.querySelector("label").textContent + - " element of Always Translate list." - ); - } - - info( - "Press the Tab key to focus the next page element, the Never Translate list" - ); - EventUtils.synthesizeKey("KEY_Tab"); - is( - document.activeElement.id, - neverTranslateMenuList.id, - "Key focus is now Never Translate List Menu button" - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_tab.js b/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_tab.js deleted file mode 100644 index 51991c6662..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_about_preferences_settings_ui_tab.js +++ /dev/null @@ -1,56 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_task( - async function test_translations_settings_about_preferences_translations_tab() { - const { cleanup } = await setupAboutPreferences(LANGUAGE_PAIRS, { - prefs: [["browser.translations.newSettingsUI.enable", true]], - }); - - info( - 'Open translations settings directly with URL "about:preferences#translations" to ensure that the translations settings elements are visible. This proves that the attribute data-subpanel="true" in the translations settings elements is working' - ); - const tab = await BrowserTestUtils.openNewForegroundTab( - gBrowser, - "about:preferences#translations", - true // waitForLoad - ); - - const translationsPane = - content.window.gCategoryModules.get("paneTranslations"); - const { - translationsSettingsBackButton, - translationsSettingsHeader, - translationsSettingsDescription, - translateAlwaysHeader, - translateNeverHeader, - alwaysTranslateMenuList, - neverTranslateMenuList, - translateNeverSiteHeader, - translateNeverSiteDesc, - translateDownloadLanguagesLearnMore, - } = translationsPane.elements; - - assertVisibility({ - message: "Expect paneTranslations elements to be visible.", - visible: { - translationsSettingsBackButton, - translationsSettingsHeader, - translationsSettingsDescription, - translateAlwaysHeader, - translateNeverHeader, - alwaysTranslateMenuList, - neverTranslateMenuList, - translateNeverSiteHeader, - translateNeverSiteDesc, - translateDownloadLanguagesLearnMore, - }, - }); - - BrowserTestUtils.removeTab(tab); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_with_lexical_shortlist.js b/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_with_lexical_shortlist.js deleted file mode 100644 index f1e895d22e..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_with_lexical_shortlist.js +++ /dev/null @@ -1,100 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests that Lazy Full Page Translations work from Spanish to English work when - * loading pre-downloaded model and WASM artifacts from the file system with - * the useLexicalShortlist pref turned on. - */ -add_task( - async function test_lazy_full_page_translate_end_to_end_with_lexical_shortlist() { - const { cleanup, runInPage } = await loadTestPage({ - endToEndTest: true, - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.useLexicalShortlist", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton(); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - endToEndTest: true, - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await cleanup(); - } -); - -/** - * Tests that Content-Eager Full Page Translations work from Spanish to English work - * when loading pre-downloaded model and WASM artifacts from the file system with - * the useLexicalShortlist pref turned on. - */ -add_task( - async function test_content_eager_full_page_translate_end_to_end_with_lexical_shortlist() { - const { cleanup, runInPage } = await loadTestPage({ - endToEndTest: true, - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - contentEagerMode: true, - prefs: [["browser.translations.useLexicalShortlist", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton(); - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - endToEndTest: true, - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ - endToEndTest: true, - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: - "The page's H1's title should be translated because it intersects with the viewport.", - }); - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - message: - "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_without_lexical_shortlist.js b/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_without_lexical_shortlist.js deleted file mode 100644 index b1f71473c7..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_e2e_full_page_translate_without_lexical_shortlist.js +++ /dev/null @@ -1,100 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests that Lazy Full Page Translations work from Spanish to English work when - * loading pre-downloaded model and WASM artifacts from the file system with - * the useLexicalShortlist pref turned off. - */ -add_task( - async function test_lazy_full_page_translate_end_to_end_with_lexical_shortlist() { - const { cleanup, runInPage } = await loadTestPage({ - endToEndTest: true, - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.useLexicalShortlist", false]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton(); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - endToEndTest: true, - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await cleanup(); - } -); - -/** - * Tests that Content-Eager Full Page Translations work from Spanish to English work - * when loading pre-downloaded model and WASM artifacts from the file system with - * the useLexicalShortlist pref turned off. - */ -add_task( - async function test_content_eager_full_page_translate_end_to_end_with_lexical_shortlist() { - const { cleanup, runInPage } = await loadTestPage({ - endToEndTest: true, - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - contentEagerMode: true, - prefs: [["browser.translations.useLexicalShortlist", false]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton(); - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - endToEndTest: true, - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ - endToEndTest: true, - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: - "The page's H1's title should be translated because it intersects with the viewport.", - }); - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - message: - "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_content_eager.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_content_eager.js deleted file mode 100644 index c6aa0cfddb..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_content_eager.js +++ /dev/null @@ -1,156 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that elements with attribute translations are still picked - * up and translated once they are observed for intersection, even in content-eager mode. - */ -add_task( - async function test_nodes_entering_proximity_are_translated_in_content_eager_mode() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - contentEagerMode: true, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - message: - "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", - } - ); - - await scrollToBottomOfPage(runInPage); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await cleanup(); - } -); - -/** - * This test case ensures that translation requests for attributes leaving the viewport proximity are - * cancelled, but translation requests for content are retained in content-eager mode, even though the - * elements they belong to have left viewport proximity. - */ -add_task( - async function test_nodes_exiting_proximity_before_translation_are_cancelled_in_content_eager_mode() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - contentEagerMode: true, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton(); - - await FullPageTranslationsTestUtils.waitForAnyRequestToInitialize( - runInPage - ); - - await scrollToBottomOfPage(runInPage); - - await FullPageTranslationsTestUtils.assertPageH1ContentIsNotTranslated({ - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageH1TitleIsNotTranslated({ - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsNotTranslated( - { - runInPage, - } - ); - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - } - ); - - info("Resolving downloads after scrolling to the bottom of the page."); - await resolveDownloads(1); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - await FullPageTranslationsTestUtils.assertPageH1ContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - await FullPageTranslationsTestUtils.assertPageH1TitleIsNotTranslated({ - runInPage, - message: - "Attribute translations are always lazy based on intersection, so the page h1's title should remain untranslated.", - }); - - await scrollToTopOfPage(runInPage); - - await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar.js deleted file mode 100644 index 3dc2e8e5df..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar.js +++ /dev/null @@ -1,256 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that opening the FindBar on a page where Full-Page Translations - * is already active will enter into content-eager translations mode, allowing all content - * translations on the page to be fulfilled while attribute translations remain lazy based - * on proximity with the viewport. - */ -add_task( - async function test_findbar_open_switches_to_content_eager_mode_from_lazy_mode() { - const { cleanup, resolveDownloads, runInPage, tab } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - info( - "Opening the find bar, which should switch us into content eager mode." - ); - await openFindBar(tab); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - message: - "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", - } - ); - - await scrollToBottomOfPage(runInPage); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - info("Mutating the H1 text content and title attribute."); - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - const h1 = getH1(); - - h1.innerText = "Este contenido de texto de h1 se modificó."; - h1.setAttribute("title", "Este atributo de título de h1 se modificó."); - h1.setAttribute( - "aria-label", - "Este atributo de etiqueta aria de h1 se añadió." - ); - }); - - info( - "Ensuring mutated H1 content is translated, but the mutated attributes are not." - ); - await runInPage(async TranslationsTest => { - const { getH1, getH1Title, getH1AriaLabel } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The re-mutated h1 text content is translated.", - getH1, - "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The re-mutated h1 title attribute is not translated.", - getH1Title, - "Este atributo de título de h1 se modificó." - ); - - await TranslationsTest.assertTranslationResult( - "The h1 aria-label attribute remains untranslated.", - getH1AriaLabel, - "Este atributo de etiqueta aria de h1 se añadió." - ); - }); - - info( - "Scrolling back to the top of the page so the mutated H1 intersects the viewport." - ); - await scrollToTopOfPage(runInPage); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info("Asserting the H1 is now fully translated (text and attributes)."); - await runInPage(async TranslationsTest => { - const { getH1, getH1Title, getH1AriaLabel } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The h1 text content remains translated.", - getH1, - "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The h1 title attribute is now translated after intersecting.", - getH1Title, - "ESTE ATRIBUTO DE TÍTULO DE H1 SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The h1 aria-label attribute is now translated after intersecting.", - getH1AriaLabel, - "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" - ); - }); - - await cleanup(); - } -); - -/** - * This test case ensures that closing the FindBar on a page where Full-Page Translations - * is already active will enter into lazy translations mode, ensuring that translations - * for both content and attributes are not fulfilled until the elements that they belong - * to enter proximity with the viewport. - */ -add_task( - async function test_findbar_close_switches_to_lazy_mode_from_content_eager_mode() { - const { cleanup, resolveDownloads, runInPage, tab } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - contentEagerMode: true, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - info( - "Closing the find bar, which should switch the page from content eager mode back to lazy mode." - ); - await closeFindBar(tab); - - info("Mutating the final paragraph text content and title attribute."); - await runInPage(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - const p = getFinalParagraph(); - - p.innerText = "Este contenido de texto de último párrafo se modificó."; - p.setAttribute( - "title", - "Este atributo de título de último párrafo se modificó." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info( - "Ensuring mutated final paragraph content and attributes are not translated while out of view in lazy mode." - ); - await runInPage(async TranslationsTest => { - const { getFinalParagraph, getFinalParagraphTitle } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph text content is not translated.", - getFinalParagraph, - "Este contenido de texto de último párrafo se modificó." - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph title attribute is not translated.", - getFinalParagraphTitle, - "Este atributo de título de último párrafo se modificó." - ); - }); - - info("Scrolling to the bottom of the page so the paragraph intersects."); - await scrollToBottomOfPage(runInPage); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info( - "Asserting the mutated final paragraph content and title are now translated after intersecting." - ); - await runInPage(async TranslationsTest => { - const { getFinalParagraph, getFinalParagraphTitle } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph text content is translated.", - getFinalParagraph, - "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph title attribute is translated.", - getFinalParagraphTitle, - "ESTE ATRIBUTO DE TÍTULO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_move_tab_to_new_window.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_move_tab_to_new_window.js deleted file mode 100644 index f15b734bfd..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_move_tab_to_new_window.js +++ /dev/null @@ -1,267 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that opening the FindBar on a page where Full-Page Translations is active - * transitions into content-eager translations mode, even after moving the tab to a new window, which - * necessarily changes to a different FindBar instance. - */ -add_task( - async function test_findbar_open_switches_to_content_eager_mode_after_moving_tab_to_new_window() { - const window1 = window; - const { cleanup, resolveDownloads, runInPage, tab } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible.", - window1 - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - win: window1, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - win: window1, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - info("Moving the tab to a new window of its own."); - const window2 = await window1.gBrowser.replaceTabWithWindow(tab); - const swapDocShellPromise = BrowserTestUtils.waitForEvent( - tab.linkedBrowser, - "SwapDocShells" - ); - await swapDocShellPromise; - - const tab2 = window2.gBrowser.selectedTab; - function runInPage2(callback, data = {}) { - return ContentTask.spawn( - tab2.linkedBrowser, - { contentData: data, callbackSource: callback.toString() }, - function ({ contentData, callbackSource }) { - const TranslationsTest = ChromeUtils.importESModule( - "chrome://mochitests/content/browser/toolkit/components/translations/tests/browser/translations-test.mjs" - ); - TranslationsTest.setup({ Assert, ContentTaskUtils, content }); - // eslint-disable-next-line no-eval - let contentCallback = eval(`(${callbackSource})`); - return contentCallback(TranslationsTest, contentData); - } - ); - } - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible.", - window2 - ); - - info( - "Opening the find bar in the new window, which should switch us into content eager mode." - ); - await openFindBar(tab2, window2); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - win: window2, - fromLanguage: "es", - toLanguage: "en", - runInPage: runInPage2, - }); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - win: window2, - runInPage: runInPage2, - message: - "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", - } - ); - - await scrollToBottomOfPage(runInPage2); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( - { - win: window2, - fromLanguage: "es", - toLanguage: "en", - runInPage: runInPage2, - } - ); - - await cleanup(); - await BrowserTestUtils.closeWindow(window2); - } -); - -/** - * This test case ensures that closing the FindBar on a page where Full-Page Translations is active - * transitions into lazy translations mode, even after moving the tab to a new window, which - * necessarily changes to a different FindBar instance. - */ -add_task( - async function test_findbar_close_switches_to_lazy_mode_after_moving_tab_to_new_window() { - const window1 = window; - const { cleanup, resolveDownloads, runInPage, tab } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - contentEagerMode: true, - }); - - // Moving a tab to a new window with the findbar open appears to modify this pref. - // Pushing it to a pref env ensures that a failure will not be reported due to the pref changing. - await SpecialPowers.pushPrefEnv({ - set: [["accessibility.typeaheadfind.flashBar", 0]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible.", - window1 - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - win: window1, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - win: window1, - }); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - info("Moving the tab to a new window of its own."); - const window2 = await window1.gBrowser.replaceTabWithWindow(tab); - const swapDocShellPromise = BrowserTestUtils.waitForEvent( - tab.linkedBrowser, - "SwapDocShells" - ); - await swapDocShellPromise; - - const tab2 = window2.gBrowser.selectedTab; - function runInPage2(callback, data = {}) { - return ContentTask.spawn( - tab2.linkedBrowser, - { contentData: data, callbackSource: callback.toString() }, - function ({ contentData, callbackSource }) { - const TranslationsTest = ChromeUtils.importESModule( - "chrome://mochitests/content/browser/toolkit/components/translations/tests/browser/translations-test.mjs" - ); - TranslationsTest.setup({ Assert, ContentTaskUtils, content }); - // eslint-disable-next-line no-eval - let contentCallback = eval(`(${callbackSource})`); - return contentCallback(TranslationsTest, contentData); - } - ); - } - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible.", - window2 - ); - - info( - "Closing the find bar in the new window, which should switch the page back to lazy mode." - ); - await closeFindBar(tab2, window2); - - info("Mutating the final paragraph text content and title attribute."); - await runInPage2(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - const p = getFinalParagraph(); - - p.innerText = "Este contenido de texto de último párrafo se modificó."; - p.setAttribute( - "title", - "Este atributo de título de último párrafo se modificó." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage2 - ); - - info( - "Ensuring mutated final paragraph content and attributes are not translated while out of view in lazy mode." - ); - await runInPage2(async TranslationsTest => { - const { getFinalParagraph, getFinalParagraphTitle } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph text content is not translated.", - getFinalParagraph, - "Este contenido de texto de último párrafo se modificó." - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph title attribute is not translated.", - getFinalParagraphTitle, - "Este atributo de título de último párrafo se modificó." - ); - }); - - info("Scrolling to the bottom of the page so the paragraph intersects."); - await scrollToBottomOfPage(runInPage2); - - await resolveDownloads(1); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage2 - ); - - info( - "Asserting the mutated final paragraph content and title are now translated after intersecting." - ); - await runInPage2(async TranslationsTest => { - const { getFinalParagraph, getFinalParagraphTitle } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph text content is translated.", - getFinalParagraph, - "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph title attribute is translated.", - getFinalParagraphTitle, - "ESTE ATRIBUTO DE TÍTULO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - }); - - await SpecialPowers.popPrefEnv(); - - await cleanup(); - await BrowserTestUtils.closeWindow(window2); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_multi_tab.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_multi_tab.js deleted file mode 100644 index cb0e5d702d..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_find_bar_multi_tab.js +++ /dev/null @@ -1,256 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that when more than one tab is open to a page - * each with Full-Page Translations active, that opening the FindBar - * in one tab and transitioning to content-eager translations mode - * does not affect the other tab. - */ -add_task(async function test_findbar_open_affects_only_target_tab() { - const { - cleanup, - resolveDownloads, - runInPage: runInSpanishDotCom, - tab: spanishDotComTab, - } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage: runInSpanishDotCom, - }); - - const { - tab: spanishDotOrgTab, - runInPage: runInSpanishDotOrg, - removeTab: removeSpanishDotOrgTab, - } = await addTab(SPANISH_PAGE_URL_DOT_ORG); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - await FullPageTranslationsTestUtils.clickTranslateButton(); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage: runInSpanishDotOrg, - }); - - info("Opening the find bar in the .org tab."); - await openFindBar(spanishDotOrgTab); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage: runInSpanishDotOrg, - }); - - await switchTab(spanishDotComTab); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage: runInSpanishDotCom, - }); - - info("Mutating the final paragraph in the .com tab."); - await runInSpanishDotCom(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - const p = getFinalParagraph(); - p.innerText = "Este contenido de texto de último párrafo se modificó."; - p.setAttribute( - "title", - "Este atributo de título de último párrafo se modificó." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInSpanishDotCom - ); - - await runInSpanishDotCom(async TranslationsTest => { - const { getFinalParagraph, getFinalParagraphTitle } = - TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "Paragraph text remains untranslated in .com tab.", - getFinalParagraph, - "Este contenido de texto de último párrafo se modificó." - ); - await TranslationsTest.assertTranslationResult( - "Paragraph title remains untranslated in .com tab.", - getFinalParagraphTitle, - "Este atributo de título de último párrafo se modificó." - ); - }); - - info("Opening the find bar in the .com tab."); - await openFindBar(spanishDotComTab); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInSpanishDotCom - ); - - await runInSpanishDotCom(async TranslationsTest => { - const { getFinalParagraph, getFinalParagraphTitle } = - TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "Paragraph text translated in .com tab.", - getFinalParagraph, - "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "Paragraph title remains untranslated in .com tab.", - getFinalParagraphTitle, - "Este atributo de título de último párrafo se modificó." - ); - }); - - await removeSpanishDotOrgTab(); - await cleanup(); -}); - -/** - * This test case ensures that when more than one tab is open to a page - * each with Full-Page Translations active, that closing the FindBar - * in one tab and transitioning to lazy translations mode does not affect - * the other tab. - */ -add_task(async function test_findbar_close_affects_only_target_tab() { - const { - cleanup, - resolveDownloads, - runInPage: runInSpanishDotCom, - tab: spanishDotComTab, - } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - contentEagerMode: true, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage: runInSpanishDotCom, - }); - - const { - tab: spanishDotOrgTab, - runInPage: runInSpanishDotOrg, - removeTab: removeSpanishDotOrgTab, - } = await addTab(SPANISH_PAGE_URL_DOT_ORG); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - await FullPageTranslationsTestUtils.clickTranslateButton(); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage: runInSpanishDotOrg, - }); - - info("Opening the find bar in the .org tab."); - await openFindBar(spanishDotOrgTab); - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage: runInSpanishDotOrg, - }); - - await switchTab(spanishDotComTab); - - info("Closing the find bar in the .com tab."); - await closeFindBar(spanishDotComTab); - - info("Mutating the final paragraph in the .com tab."); - await runInSpanishDotCom(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - const p = getFinalParagraph(); - p.innerText = "Este contenido de texto de último párrafo se modificó."; - p.setAttribute( - "title", - "Este atributo de título de último párrafo se modificó." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInSpanishDotCom - ); - - await runInSpanishDotCom(async TranslationsTest => { - const { getFinalParagraph, getFinalParagraphTitle } = - TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "Paragraph text remains untranslated in .com tab.", - getFinalParagraph, - "Este contenido de texto de último párrafo se modificó." - ); - await TranslationsTest.assertTranslationResult( - "Paragraph title remains untranslated in .com tab.", - getFinalParagraphTitle, - "Este atributo de título de último párrafo se modificó." - ); - }); - - await switchTab(spanishDotOrgTab); - - info("Mutating the final paragraph in the .org tab."); - await runInSpanishDotOrg(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - const p = getFinalParagraph(); - p.innerText = "Este contenido de texto de último párrafo se modificó."; - p.setAttribute( - "title", - "Este atributo de título de último párrafo se modificó." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInSpanishDotOrg - ); - - await runInSpanishDotOrg(async TranslationsTest => { - const { getFinalParagraph, getFinalParagraphTitle } = - TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "Paragraph text translated in .org tab.", - getFinalParagraph, - "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - await TranslationsTest.assertTranslationResult( - "Paragraph title remains untranslated in .org tab.", - getFinalParagraphTitle, - "Este atributo de título de último párrafo se modificó." - ); - }); - - await removeSpanishDotOrgTab(); - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_lazy.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_lazy.js deleted file mode 100644 index 9e311901ef..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_lazy.js +++ /dev/null @@ -1,161 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that elements with translatable content and attributes are - * picked up and translated once they enter viewport proximity in lazy translations mode. - */ -add_task( - async function test_nodes_entering_proximity_are_translated_in_lazy_mode() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await scrollToBottomOfPage(runInPage); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await cleanup(); - } -); - -/** - * This test case ensures that elements with translatable content and attributes that - * exit viewport proximity are prevented from translating in lazy translations mode. - */ -add_task( - async function test_nodes_exiting_proximity_before_translation_are_cancelled_in_lazy_mode() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton(); - - await FullPageTranslationsTestUtils.waitForAnyRequestToInitialize( - runInPage - ); - - await scrollToBottomOfPage(runInPage); - - await FullPageTranslationsTestUtils.assertPageH1ContentIsNotTranslated({ - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageH1TitleIsNotTranslated({ - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsNotTranslated( - { - runInPage, - } - ); - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - } - ); - - info("Resolving downloads after scrolling to the bottom of the page."); - await resolveDownloads(1); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - await FullPageTranslationsTestUtils.assertPageH1ContentIsNotTranslated({ - runInPage, - message: "The h1 left viewport proximity before its requests completed.", - }); - await FullPageTranslationsTestUtils.assertPageH1TitleIsNotTranslated({ - runInPage, - message: "The h1 left viewport proximity before its requests completed.", - }); - - await scrollToTopOfPage(runInPage); - - await FullPageTranslationsTestUtils.assertPageH1ContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_content_eager.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_content_eager.js deleted file mode 100644 index 25ba633104..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_content_eager.js +++ /dev/null @@ -1,247 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that nodes with mutated content are picked up and translated - * regardless of their proximity to the viewport in content-eager translations mode, - * but attributes that are mutated will not be translated until the elements they - * belong to enter proximity with the viewport. - */ -add_task( - async function test_mutated_nodes_are_translated_in_content_eager_mode() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - contentEagerMode: true, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - info( - "Ensuring intersecting attributes are translated and non-intersecting attributes are not translated." - ); - await runInPage(async TranslationsTest => { - const { getH1Title, getFinalParagraphTitle } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The

title attribute is translated.", - getH1Title, - "ESTE ES EL TÍTULO DEL ENCABEZADO DE PÁGINA [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The final paragraph title attribute is not translated.", - getFinalParagraphTitle, - "Este es el título del último párrafo" - ); - }); - - info("Mutating the H1 text content and title attribute."); - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - const h1 = getH1(); - - h1.innerText = "Este contenido de texto de h1 se modificó."; - h1.setAttribute("title", "Este atributo de título de h1 se modificó."); - h1.setAttribute( - "aria-label", - "Este atributo de etiqueta aria de h1 se añadió." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info("Ensuring all H1 mutations are translated."); - await runInPage(async TranslationsTest => { - const { getH1, getH1Title, getH1AriaLabel } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The mutated h1 text content is translated.", - getH1, - "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated h1 title attribute is translated.", - getH1Title, - "ESTE ATRIBUTO DE TÍTULO DE H1 SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated h1 aria-label attribute is translated.", - getH1AriaLabel, - "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" - ); - }); - - info("Mutating the final paragraph text content and attributes."); - await runInPage(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - const p = getFinalParagraph(); - - p.innerText = "Este contenido de texto de último párrafo se modificó."; - p.setAttribute( - "title", - "Este atributo de título de último párrafo se modificó." - ); - p.setAttribute( - "aria-label", - "Este atributo de etiqueta aria de último párrafo se añadió." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info( - "Ensuring that only the final paragraph's content mutations are translated." - ); - await runInPage(async TranslationsTest => { - const { - getFinalParagraph, - getFinalParagraphTitle, - getFinalParagraphAriaLabel, - } = TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph text content is translated.", - getFinalParagraph, - "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph title attribute is not translated.", - getFinalParagraphTitle, - "Este atributo de título de último párrafo se modificó." - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph aria-label attribute is not translated.", - getFinalParagraphAriaLabel, - "Este atributo de etiqueta aria de último párrafo se añadió." - ); - }); - - await scrollToBottomOfPage(runInPage); - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - await scrollToBottomOfPage(runInPage); - - info("Ensuring all final paragraph mutations are translated."); - await runInPage(async TranslationsTest => { - const { - getFinalParagraph, - getFinalParagraphTitle, - getFinalParagraphAriaLabel, - } = TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph text content remains translated.", - getFinalParagraph, - "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph title attribute is translated.", - getFinalParagraphTitle, - "ESTE ATRIBUTO DE TÍTULO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph aria-label attribute is translated.", - getFinalParagraphAriaLabel, - "ESTE ATRIBUTO DE ETIQUETA ARIA DE ÚLTIMO PÁRRAFO SE AÑADIÓ. [es to en]" - ); - }); - - info("Mutating the H1 content and title again."); - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - const h1 = getH1(); - - h1.innerText = "Este contenido de texto de h1 se modificó otra vez."; - h1.setAttribute( - "title", - "Este atributo de título de h1 se modificó otra vez." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info( - "Ensuring mutated H1 content is translated, but the mutated attribute is not." - ); - await runInPage(async TranslationsTest => { - const { getH1, getH1Title, getH1AriaLabel } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The re-mutated h1 text content is translated.", - getH1, - "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ OTRA VEZ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The re-mutated h1 title attribute is not translated.", - getH1Title, - "Este atributo de título de h1 se modificó otra vez." - ); - - await TranslationsTest.assertTranslationResult( - "The h1 aria-label attribute remains previously translated.", - getH1AriaLabel, - "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" - ); - }); - - await scrollToTopOfPage(runInPage); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info("Ensuring re-mutated H1 title attribute is translated."); - await runInPage(async TranslationsTest => { - const { getH1Title } = TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The re-mutated h1 title attribute is translated.", - getH1Title, - "ESTE ATRIBUTO DE TÍTULO DE H1 SE MODIFICÓ OTRA VEZ. [es to en]" - ); - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_lazy.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_lazy.js deleted file mode 100644 index 9e3c660100..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_intersection_mutations_lazy.js +++ /dev/null @@ -1,235 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that both content and attribute mutations are not picked up - * and translated until the elements that they belong to enter proximity with the viewport. - */ -add_task( - async function test_mutated_nodes_entering_proximity_are_translated_in_lazy_mode() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - info("Mutating the H1 text content and title attribute."); - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - const h1 = getH1(); - - h1.innerText = "Este contenido de texto de h1 se modificó."; - h1.setAttribute("title", "Este atributo de título de h1 se modificó."); - h1.setAttribute( - "aria-label", - "Este atributo de etiqueta aria de h1 se añadió." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info("Ensuring all H1 mutations are translated."); - await runInPage(async TranslationsTest => { - const { getH1, getH1Title, getH1AriaLabel } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The mutated h1 text content is translated.", - getH1, - "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated h1 title attribute is translated.", - getH1Title, - "ESTE ATRIBUTO DE TÍTULO DE H1 SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated h1 aria-label attribute is translated.", - getH1AriaLabel, - "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" - ); - }); - - info("Mutating the final paragraph text content and attributes."); - await runInPage(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - const p = getFinalParagraph(); - - p.innerText = "Este contenido de texto de último párrafo se modificó."; - p.setAttribute( - "title", - "Este atributo de título de último párrafo se modificó." - ); - p.setAttribute( - "aria-label", - "Este atributo de etiqueta aria de último párrafo se añadió." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info("Ensuring final paragraph mutations are NOT translated yet."); - await runInPage(async TranslationsTest => { - const { - getFinalParagraph, - getFinalParagraphTitle, - getFinalParagraphAriaLabel, - } = TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph text content is not translated.", - getFinalParagraph, - "Este contenido de texto de último párrafo se modificó." - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph title attribute is not translated.", - getFinalParagraphTitle, - "Este atributo de título de último párrafo se modificó." - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph aria-label attribute is not translated.", - getFinalParagraphAriaLabel, - "Este atributo de etiqueta aria de último párrafo se añadió." - ); - }); - - await scrollToBottomOfPage(runInPage); - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - await scrollToBottomOfPage(runInPage); - - info("Ensuring all final paragraph mutations are translated."); - await runInPage(async TranslationsTest => { - const { - getFinalParagraph, - getFinalParagraphTitle, - getFinalParagraphAriaLabel, - } = TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph text content is translated.", - getFinalParagraph, - "ESTE CONTENIDO DE TEXTO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph title attribute is translated.", - getFinalParagraphTitle, - "ESTE ATRIBUTO DE TÍTULO DE ÚLTIMO PÁRRAFO SE MODIFICÓ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The mutated final paragraph aria-label attribute is translated.", - getFinalParagraphAriaLabel, - "ESTE ATRIBUTO DE ETIQUETA ARIA DE ÚLTIMO PÁRRAFO SE AÑADIÓ. [es to en]" - ); - }); - - info("Mutating the H1 content and title again."); - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - const h1 = getH1(); - - h1.innerText = "Este contenido de texto de h1 se modificó otra vez."; - h1.setAttribute( - "title", - "Este atributo de título de h1 se modificó otra vez." - ); - }); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info("Ensuring re-mutated H1 content is NOT translated yet."); - await runInPage(async TranslationsTest => { - const { getH1, getH1Title, getH1AriaLabel } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The re-mutated h1 text content is not translated.", - getH1, - "Este contenido de texto de h1 se modificó otra vez." - ); - - await TranslationsTest.assertTranslationResult( - "The re-mutated h1 title attribute is not translated.", - getH1Title, - "Este atributo de título de h1 se modificó otra vez." - ); - - await TranslationsTest.assertTranslationResult( - "The h1 aria-label attribute remains previously translated.", - getH1AriaLabel, - "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" - ); - }); - - await scrollToTopOfPage(runInPage); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info("Ensuring re-mutated H1 content is translated."); - await runInPage(async TranslationsTest => { - const { getH1, getH1Title, getH1AriaLabel } = - TranslationsTest.getSelectors(); - - await TranslationsTest.assertTranslationResult( - "The re-mutated h1 text content is translated.", - getH1, - "ESTE CONTENIDO DE TEXTO DE H1 SE MODIFICÓ OTRA VEZ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The re-mutated h1 title attribute is translated.", - getH1Title, - "ESTE ATRIBUTO DE TÍTULO DE H1 SE MODIFICÓ OTRA VEZ. [es to en]" - ); - - await TranslationsTest.assertTranslationResult( - "The h1 aria-label attribute remains previously translated.", - getH1AriaLabel, - "ESTE ATRIBUTO DE ETIQUETA ARIA DE H1 SE AÑADIÓ. [es to en]" - ); - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_language_id_behavior.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_language_id_behavior.js deleted file mode 100644 index cdd059e923..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_language_id_behavior.js +++ /dev/null @@ -1,298 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Run through the test cases for how auto translation and offering translations works - * with a variety of conditions. The - * - * Keep this table up to date with TranslationParent's maybeOfferTranslation and - * shouldAutoTranslate methods. When an entry is blank "-" it has no affect on the - * outcome. - * - * ┌────┬──────────┬───────────┬───────────────────┬───────────────────┬─────────────────────────────┐ - * │ # │ Has HTML │ Detection │ Detection Content │ Always Translate │ Outcome │ - * │ │ Tag │ Agrees │ > 200 code units │ List Contains Tag │ │ - * ├────┼──────────┼───────────┼───────────────────┼───────────────────┼─────────────────────────────┤ - * │ 1 │ TRUE │ TRUE │ - │ TRUE │ Auto Translate Matching Tag │ - * │ 2 │ TRUE │ TRUE │ - │ FALSE │ Offer Matching Tag │ - * │ 3 │ TRUE │ TRUE │ - │ TRUE │ Auto Translate Matching Tag │ - * │ 4 │ TRUE │ TRUE │ - │ FALSE │ Offer Matching Tag │ - * │ 5 │ TRUE │ FALSE │ - │ TRUE │ Show Button Only │ - * │ 6 │ TRUE │ FALSE │ - │ FALSE │ Show Button Only │ - * │ 7 │ TRUE │ FALSE │ - │ TRUE │ Show Button Only │ - * │ 8 │ TRUE │ FALSE │ - │ FALSE │ Show Button Only │ - * │ 9 │ FALSE │ - │ TRUE │ TRUE │ Auto Translate Detected Tag │ - * │ 10 │ FALSE │ - │ TRUE │ FALSE │ Offer Detected Tag │ - * │ 11 │ FALSE │ - │ FALSE │ TRUE │ Show Button Only │ - * │ 12 │ FALSE │ - │ FALSE │ FALSE │ Show Button Only │ - * └────┴──────────┴───────────┴───────────────────┴───────────────────┴─────────────────────────────┘ - */ - -/** - * Request 2x longer timeout for this test. - * There are lot of test cases in this file, but it doesn't make sense to split them up. - */ -requestLongerTimeout(2); - -/** - * Definitions for the test cases. - * - * @typedef {object} Case - * @property {string} page - The page to load. - * @property {string} message - A message for the primary assertion. - * @property {string} [alwaysTranslateLanguages] - Set the pref: browser.translations.alwaysTranslateLanguages - * @property {string} [neverTranslateLanguages] - Set the pref: browser.translations.alwaysTranslateLanguages - * - * Outcomes, use only one: - * @property {string} [translatePage] - The page is expected to be translated. - * @property {string} [offerTranslation] - The page offers a translation in this language. - * @property {boolean} [buttonShown] - The button was shown to offer a translation. - */ - -/** - * @type {Case[]} - */ -const cases = [ - // HTML tag and (confident) detection agree. - { - // Case 1 - Spanish is set to auto translate. - page: SPANISH_PAGE_URL, - alwaysTranslateLanguages: "es", - translatePage: "es", - message: - "Auto-translate since the declared language and identified language agree", - }, - { - // Case 2 - Nothing is set to auto translate. - page: SPANISH_PAGE_URL, - offerTranslation: "es", - message: - "The declared language and identified language agree, offer a translation", - }, - // HTML tag and (low-confidence) detection agree. - { - // Case 3 - Spanish is set to auto translate. - page: SPANISH_PAGE_SHORT_URL, - alwaysTranslateLanguages: "es", - translatePage: "es", - message: - "The declared language and identified language agree, offer a translation even " + - "though the page has a short amount of content.", - }, - { - // Case 4 - Nothing is set to auto translate. - page: SPANISH_PAGE_SHORT_URL, - offerTranslation: "es", - message: - "The declared language and identified language agree, offer a translation", - }, - // HTML tag and (confident) detection disagree. - { - // Case 5 - Spanish is set to auto translate. - page: SPANISH_PAGE_MISMATCH_URL, - alwaysTranslateLanguages: "es", - buttonShown: true, - message: - "The declared and (confident) detected language disagree. Only show the button, do not auto-translate.", - }, - { - // Case 6 - Nothing is set to auto translate. - page: SPANISH_PAGE_MISMATCH_URL, - buttonShown: true, - message: - "The declared and (confident) detected language disagree. Only show the button, do not offer.", - }, - // HTML tag and (low-confidence) detection disagree. - { - // Case 7 - Spanish is set to auto translate. - page: SPANISH_PAGE_MISMATCH_SHORT_URL, - alwaysTranslateLanguages: "es", - buttonShown: true, - message: - "The declared and (low-confidence) detected language disagree. Only show the button, do not auto-translate.", - }, - { - // Case 8 - Nothing is set to auto translate. - page: SPANISH_PAGE_MISMATCH_SHORT_URL, - buttonShown: true, - message: - "The declared and (low-confidence) detected language disagree. Only show the button, do not offer.", - }, - // Undeclared language and (high-confidence) detection. - { - // Case 9 - Spanish is set to auto translate. - page: SPANISH_PAGE_UNDECLARED_URL, - alwaysTranslateLanguages: "es,fr", - translatePage: "es", - message: - "There is no declared language, but there is high confidence in the detected language, so go ahead and auto-translate.", - }, - { - // Case 10 - Nothing is set to auto translate. - page: SPANISH_PAGE_UNDECLARED_URL, - offerTranslation: "es", - message: - "There is no declared language, but there is high confidence in the detected language, so go ahead and offer.", - }, - // Undeclared language and (low-confidence) detection. - { - // Case 11 - Spanish is set to auto translate. - page: SPANISH_PAGE_MISMATCH_SHORT_URL, - alwaysTranslateLanguages: "es", - buttonShown: true, - message: - "A language was detected, but it was so low confidence only show the button.", - }, - { - // Case 12 - Nothing is set to auto translate. - page: SPANISH_PAGE_UNDECLARED_SHORT_URL, - buttonShown: true, - message: - "A language was detected, but it was so low confidence only show the button.", - }, -]; - -add_task(async function test_language_identification_behavior() { - for (const [caseNo, testCase] of Object.entries(cases)) { - const { - page, - message, - alwaysTranslateLanguages, - neverTranslateLanguages, - translatePage, - offerTranslation, - buttonShown, - } = testCase; - info(`Testing Case ${Number(caseNo) + 1}`); - TranslationsParent.testAutomaticPopup = true; - - // Handle this manually instead of using FullPageTranslationsTestUtils.waitForPanelPopupEvent - // as we may not actually get a popupshown event and this leads to an error on test shutdown: - // "popupshown listener on #full-page-translations-panel not removed before the end of test" - let wasPopupShown = false; - window.FullPageTranslationsPanel.elements; // De-lazify the panel. - const { promise: popupShown, resolve } = Promise.withResolvers(); - const panel = window.document.getElementById( - "full-page-translations-panel" - ); - function handlePopupShown() { - wasPopupShown = true; - panel.removeEventListener("popupshown", handlePopupShown); - resolve(); - } - panel.addEventListener("popupshown", handlePopupShown); - - const { cleanup, runInPage, win } = await loadTestPage({ - page, - languagePairs: LANGUAGE_PAIRS, - autoDownloadFromRemoteSettings: true, - contentEagerMode: true, - prefs: [ - [ - "browser.translations.alwaysTranslateLanguages", - alwaysTranslateLanguages, - ], - [ - "browser.translations.neverTranslateLanguages", - neverTranslateLanguages, - ], - ], - }); - - let outcomes = 0; - if (buttonShown) { - outcomes++; - } - if (offerTranslation) { - outcomes++; - } - if (translatePage) { - outcomes++; - } - if (outcomes !== 1) { - throw new Error("Expected only 1 main outcome."); - } - - if (buttonShown || offerTranslation || translatePage) { - await FullPageTranslationsTestUtils.assertTranslationsButton( - { - button: true, - circleArrows: false, - locale: translatePage, - icon: true, - }, - offerTranslation ? "The translation button is visible" : message - ); - } else { - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The translations button is not visible." - ); - } - - if (translatePage) { - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: translatePage, - toLanguage: "en", - runInPage, - message, - }); - await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: - "The page's H1's title should be translated because it intersects with the viewport.", - }); - - if ( - page === SPANISH_PAGE_SHORT_URL || - page === SPANISH_PAGE_MISMATCH_SHORT_URL - ) { - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: - "The page's final paragraph's title should be translated because it intersects with the viewport.", - } - ); - } else { - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - message: - "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", - } - ); - } - } else { - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInPage, - message - ); - } - - if (offerTranslation) { - await popupShown; - ok(wasPopupShown, message); - FullPageTranslationsTestUtils.assertSelectedFromLanguage({ - win, - langTag: offerTranslation, - }); - FullPageTranslationsTestUtils.assertSelectedToLanguage({ - win, - langTag: "en", - }); - } else { - is(wasPopupShown, false, "A translation was not offered"); - } - - TranslationsParent.testAutomaticPopup = false; - panel.removeEventListener("popupshown", handlePopupShown); - await cleanup(); - } -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_move_tab_to_new_window.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_move_tab_to_new_window.js deleted file mode 100644 index cd256795be..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_move_tab_to_new_window.js +++ /dev/null @@ -1,68 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests a specific situation described in Bug 1893776 - * where the Translations panels were not initializing correctly after - * dragging a tab to become its own new window after opening the panel - * in the previous window. - */ -add_task(async function test_browser_translations_full_page_multiple_windows() { - const window1 = window; - const testPage = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible.", - window1 - ); - - info("Opening FullPageTranslationsPanel in window1"); - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - info("Moving the tab to a new window of its own"); - const window2 = await window1.gBrowser.replaceTabWithWindow(testPage.tab); - const swapDocShellPromise = BrowserTestUtils.waitForEvent( - testPage.tab.linkedBrowser, - "SwapDocShells" - ); - await swapDocShellPromise; - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible.", - window2 - ); - - info("Opening FullPageTranslationsPanel in window2"); - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - win: window2, - }); - - info("Translating the same page in window2"); - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window2, - downloadHandler: testPage.resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - "es", - "en", - window2 - ); - - await testPage.cleanup(); - await BrowserTestUtils.closeWindow(window2); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_moz_extension.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_moz_extension.js deleted file mode 100644 index 42937f2703..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_moz_extension.js +++ /dev/null @@ -1,79 +0,0 @@ -/* 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_moz_extension() { - let extension = ExtensionTestUtils.loadExtension({ - manifest: { - web_accessible_resources: ["test_page.html"], - }, - files: { - "test_page.html": ` - - - - - -

Don Quijote de La Mancha

-

— Pues, aunque mováis más brazos que los del gigante Briareo, me lo habéis de pagar.

- - `, - }, - }); - - await extension.startup(); - - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: `moz-extension://${extension.uuid}/test_page.html`, - languagePairs: LANGUAGE_PAIRS, - }); - - const { button } = - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - is(button.getAttribute("data-l10n-id"), "urlbar-translations-button-intro"); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: - "The page's H1's title should be translated because it intersects with the viewport.", - }); - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: - "The page's final paragraph's title should be translated because it intersects with the viewport.", - } - ); - - await cleanup(); - await extension.unload(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_multiple_windows.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_multiple_windows.js deleted file mode 100644 index c0693748a5..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_multiple_windows.js +++ /dev/null @@ -1,65 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Test that the full page translation panel works when multiple windows are used. - */ -add_task(async function test_browser_translations_full_page_multiple_windows() { - const window1 = window; - const testPage1 = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - const window2 = await BrowserTestUtils.openNewBrowserWindow(); - - const testPage2 = await loadTestPage({ - win: window2, - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - // Focus back to the original window first. This ensures coverage for invalid caching - // logic involving multiple windows. - await focusWindow(window1); - - info("Testing window 1"); - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: testPage1.resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage: testPage1.runInPage, - message: "Window 1 gets translated", - win: window1, - }); - - await focusWindow(window2); - - info("Testing window 2"); - await FullPageTranslationsTestUtils.openPanel({ - win: window2, - expectedFromLanguage: "es", - expectedToLanguage: "en", - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ win: window2 }); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage: testPage2.runInPage, - message: "Window 2 gets translated", - win: window2, - }); - - await testPage2.cleanup(); - await BrowserTestUtils.closeWindow(window2); - await testPage1.cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_a11y_focus.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_a11y_focus.js deleted file mode 100644 index 511e91572e..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_a11y_focus.js +++ /dev/null @@ -1,34 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests the a11y focus behavior. - */ -add_task(async function test_translations_panel_a11y_focus() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - openWithKeyboard: true, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - is( - document.activeElement.getAttribute("data-l10n-id"), - "translations-panel-settings-button", - "The settings button is focused." - ); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_bad_data.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_bad_data.js deleted file mode 100644 index 0e698a083e..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_bad_data.js +++ /dev/null @@ -1,41 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests that having an "always translate" set to your app locale doesn't break things. - */ -add_task(async function test_always_translate_with_bad_data() { - const { cleanup, runInPage } = await loadTestPage({ - page: ENGLISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.alwaysTranslateLanguages", "en,fr"]], - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "en", - expectedToLanguage: "", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - openFromAppMenu: true, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("en", { - checked: false, - disabled: true, - }); - await closeAllOpenPanelsAndMenus(); - - info("Checking that the page is not translated"); - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's H1 is not translated and in the original English.", - getH1, - '"The Wonderful Wizard of Oz" by L. Frank Baum' - ); - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_basic.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_basic.js deleted file mode 100644 index fc011e4ad8..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_basic.js +++ /dev/null @@ -1,81 +0,0 @@ -/* 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 not translated 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: "The page should be automatically translated.", - }); - - await navigate("Navigate to a different Spanish page", { - url: SPANISH_PAGE_URL_DOT_ORG, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: "The page should be automatically translated.", - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage(); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "Only the button appears" - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_manual.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_manual.js deleted file mode 100644 index 033de434b2..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_manual.js +++ /dev/null @@ -1,88 +0,0 @@ -/* 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 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage(); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage(); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "Only the button appears" - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_restore.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_restore.js deleted file mode 100644 index 9cc9ce099b..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_always_translate_language_restore.js +++ /dev/null @@ -1,109 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: "The page should be automatically translated.", - } - ); - - await navigate("Navigate to a different Spanish page", { - url: SPANISH_PAGE_URL_DOT_ORG, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: "The page should be automatically translated.", - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.clickRestoreButton(); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is reverted to have an icon." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage(); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button shows only the icon." - ); - - await navigate("Reload the page", { url: SPANISH_PAGE_URL_DOT_ORG }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button shows only the icon." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_language.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_language.js deleted file mode 100644 index fd34afbe07..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_language.js +++ /dev/null @@ -1,42 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests the effect of unchecking the never-translate-language menuitem, removing - * the language from the never-translate languages list. - * The translations button should reappear. - */ -add_task(async function test_uncheck_never_translate_language_shows_button() { - const { cleanup, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.neverTranslateLanguages", "es"]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is available" - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - openFromAppMenu: true, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_site.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_site.js deleted file mode 100644 index 9ab1f8ee8f..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_app_menu_never_translate_site.js +++ /dev/null @@ -1,151 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests the effect of unchecking the never-translate-site menuitem, - * regranting translations permissions to this page. - * The translations button should reappear. - */ -add_task(async function test_uncheck_never_translate_site_shows_button() { - const { cleanup, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - openFromAppMenu: true, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - - await cleanup(); -}); - -/** - * Tests the effect of unchecking the never-translate-site menuitem while - * the current language is in the always-translate languages list, regranting - * translations permissions to this page. - * The page should automatically translate. - */ -add_task( - async function test_uncheck_never_translate_site_with_always_translate_language() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: BLANK_PAGE, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.alwaysTranslateLanguages", "es"]], - }); - - await navigate("Navigate to a Spanish page", { - url: SPANISH_PAGE_URL, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - openFromAppMenu: true, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_error_view.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_error_view.js deleted file mode 100644 index 0e76cda526..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_error_view.js +++ /dev/null @@ -1,88 +0,0 @@ -/* 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" -); - -/** - * This tests a specific defect where the error view was not showing properly - * when navigating to an auto-translated page after visiting a page in an unsupported - * language and viewing the panel. - * - * This test case tests the case where the auto translate fails and the panel - * automatically opens the panel to show the error view. - * - * See https://bugzilla.mozilla.org/show_bug.cgi?id=1845611 for more information. - */ -add_task( - async function test_revisit_view_updates_with_auto_translate_failure() { - const { cleanup, resolveDownloads, rejectDownloads, runInPage } = - await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: [ - // Do not include French. - { fromLang: "en", toLang: "es" }, - { fromLang: "es", toLang: "en" }, - ], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await navigate("Navigate to a page in an unsupported language", { - url: FRENCH_PAGE_URL, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The translations button should be unavailable." - ); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - onOpenPanel: - FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - info("Destroy the engine process so that an error will happen."); - await EngineProcess.destroyTranslationsEngine(); - - await navigate("Navigate back to a Spanish page.", { - url: SPANISH_PAGE_URL_DOT_ORG, - downloadHandler: rejectDownloads, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewError, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_revisit_view.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_revisit_view.js deleted file mode 100644 index 63d58d4864..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_auto_translate_revisit_view.js +++ /dev/null @@ -1,92 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This tests a specific defect where the revisit view was not showing properly - * when navigating to an auto-translated page after visiting a page in an unsupported - * language and viewing the panel. - * - * This test case tests the case where the auto translate succeeds and the user - * manually opens the panel to show the revisit view. - * - * See https://bugzilla.mozilla.org/show_bug.cgi?id=1845611 for more information. - */ -add_task( - async function test_revisit_view_updates_with_auto_translate_success() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: [ - // Do not include French. - { fromLang: "en", toLang: "es" }, - { fromLang: "es", toLang: "en" }, - ], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await navigate("Navigate to a page in an unsupported language", { - url: FRENCH_PAGE_URL, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The translations button should be unavailable." - ); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - onOpenPanel: - FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await navigate("Navigate back to the Spanish page.", { - url: SPANISH_PAGE_URL_DOT_ORG, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - openFromAppMenu: true, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_basics.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_basics.js deleted file mode 100644 index c348a4c8a8..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_basics.js +++ /dev/null @@ -1,69 +0,0 @@ -/* 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 FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - is(button.getAttribute("data-l10n-id"), "urlbar-translations-button-intro"); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton(); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The icon presents the loading indicator." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewLoading, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await resolveDownloads(1); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.clickRestoreButton(); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is reverted to have an icon." - ); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_button.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_button.js deleted file mode 100644 index 209cfc18a6..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_button.js +++ /dev/null @@ -1,77 +0,0 @@ -/* 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() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button should be visible since the page can be translated from Spanish." - ); - - await navigate("Navigate to an English page.", { url: ENGLISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The button should be invisible since the page is in English." - ); - - await navigate("Navigate back to a Spanish page.", { url: SPANISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.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() { - const { cleanup, tab: spanishTab } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.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 FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The button should be invisible since the tab is in English." - ); - - await switchTab(spanishTab, "spanish tab"); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button should be visible again since the page is in Spanish." - ); - - await switchTab(englishTab, "english tab"); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "Don't show for english pages" - ); - - await removeTab(); - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_cancel.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_cancel.js deleted file mode 100644 index 5267abb17b..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_cancel.js +++ /dev/null @@ -1,29 +0,0 @@ -/* 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_change_app_locale.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_change_app_locale.js deleted file mode 100644 index ad6936991a..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_change_app_locale.js +++ /dev/null @@ -1,74 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the language display names within the FullPageTranslationsPanel - * dropdown menu lists update immediately upon the next panel open when the user's application - * locale changes. - */ -add_task( - async function test_full_page_translations_panel_change_application_locale() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - const { fromMenuList, toMenuList } = FullPageTranslationsPanel.elements; - - is( - fromMenuList.label, - "Spanish", - "The FullPageTranslationsPanel from-menu-list languages should be localized to English display names." - ); - - is( - toMenuList.label, - "English", - "The FullPageTranslationsPanel to-menu-list languages should be localized to English display names." - ); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - info("Changing the application locale from English to Spanish"); - const cleanupLocales = await mockLocales({ - appLocales: ["es"], - webLanguages: ["en"], - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - is( - fromMenuList.label, - "español", - "The FullPageTranslationsPanel from-menu-list languages should be localized to Spanish display names." - ); - - is( - toMenuList.label, - "inglés", - "The FullPageTranslationsPanel to-menu-list languages should be localized to Spanish display names." - ); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await cleanupLocales(); - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_active.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_active.js deleted file mode 100644 index 1434ab33d0..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_active.js +++ /dev/null @@ -1,159 +0,0 @@ -"use strict"; - -/** - * Tests the effect of checking the never-translate-language menuitem on a page where - * translations are active (always-translate-language is enabled). - * Checking the box on the page automatically closes/hides the translations panel. - */ -add_task( - async function test_panel_closes_on_toggle_never_translate_language_with_translations_active() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is available" - ); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: "The page should be automatically translated.", - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - async () => { - await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); - } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - await cleanup(); - } -); - -/** - * Tests the effect of checking the never-translate-language menuitem on - * a page where translations are active through always-translate-language - * and inactive on a site through never-translate-site. - * Checking the box on the page automatically closes/hides the translations panel. - */ -add_task( - async function test_panel_closes_on_toggle_never_translate_language_with_always_translate_language_and_never_translate_site_active() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is available" - ); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: "The page should be automatically translated.", - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - async () => { - await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); - } - ); - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_inactive.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_inactive.js deleted file mode 100644 index be68494809..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_language_with_translations_inactive.js +++ /dev/null @@ -1,99 +0,0 @@ -"use strict"; - -/** - * Tests the effect of checking the never-translate-language menuitem on a page where - * translations and never translate site are inactive. - * Checking the box on the page automatically closes/hides the translations panel. - */ -add_task(async function test_panel_closes_on_toggle_never_translate_language() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is available" - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - openFromAppMenu: true, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - async () => { - await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); - } - ); - await cleanup(); -}); - -/** - * Tests the effect of checking the never-translate-language menuitem on a page where - * translations are inactive (never-translate-site is enabled). - * Checking the box on the page automatically closes/hides the translations panel. - */ -add_task( - async function test_panel_closes_on_toggle_never_translate_language_with_never_translate_site_enabled() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is available" - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - openFromAppMenu: true, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - openFromAppMenu: true, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - async () => { - await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); - } - ); - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_site.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_site.js deleted file mode 100644 index 75c73f2451..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_close_panel_never_translate_site.js +++ /dev/null @@ -1,170 +0,0 @@ -"use strict"; - -/** - * Tests the effect of checking the never-translate-site menuitem on a page where - * always-translate-language and never-translate-language are inactive. - * Checking the box on the page automatically closes/hides the translations panel. - */ -add_task(async function test_panel_closes_on_toggle_never_translate_site() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is available" - ); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - async () => { - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - } - ); - - await cleanup(); -}); - -/** - * Tests the effect of checking the never-translate-site menuitem on a page where - * translations are active (always-translate-language is enabled). - * Checking the box on the page automatically restores the page and closes/hides the translations panel. - */ -add_task( - async function test_panel_closes_on_toggle_never_translate_site_with_translations_active() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is available" - ); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: "The page should be automatically translated.", - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - async () => { - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - } - ); - - await cleanup(); - } -); - -/** - * Tests the effect of checking the never-translate-site menuitem on a page where - * translations are inactive (never-translate-language is active). - * Checking the box on the page automatically closes/hides the translations panel. - */ -add_task( - async function test_panel_closes_on_toggle_never_translate_site_with_translations_inactive() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is available" - ); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - async () => { - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy.js deleted file mode 100644 index 43f1cee107..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy.js +++ /dev/null @@ -1,64 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Manually destroy the engine, and test that the page is still translated afterwards. - */ -add_task(async function test_translations_engine_destroy() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - info("Destroy the engine process"); - await EngineProcess.destroyTranslationsEngine(); - - info("Mutate the page's content to re-trigger a translation."); - const { promise: animationPromise, resolve } = Promise.withResolvers(); - requestAnimationFrame(() => { - requestAnimationFrame(resolve); - }); - - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - getH1().innerText = "New text for the H1"; - }); - - await animationPromise; - - info("The engine downloads should be requested again."); - await resolveDownloads(1); - - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The mutated content should be translated.", - getH1, - "NEW TEXT FOR THE H1 [es to en]" - ); - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy_pending.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy_pending.js deleted file mode 100644 index a4aed29131..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_destroy_pending.js +++ /dev/null @@ -1,77 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Manually destroy the engine while a page is in the background, and test that the page - * is still translated after switching back to it. - */ -add_task(async function test_translations_engine_destroy_pending() { - const { - cleanup, - resolveDownloads, - runInPage, - tab: spanishTab, - } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - const { removeTab: removeEnglishTab } = await addTab( - ENGLISH_PAGE_URL, - "Creating a new tab for a page in English." - ); - - info("Destroy the engine process"); - await EngineProcess.destroyTranslationsEngine(); - - info("Mutate the page's content to re-trigger a translation."); - const { promise: animationPromise, resolve } = Promise.withResolvers(); - requestAnimationFrame(() => { - requestAnimationFrame(resolve); - }); - - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - getH1().innerText = "New text for the H1"; - }); - - await animationPromise; - await switchTab(spanishTab, "spanish tab"); - - info("The engine downloads should be requested again."); - await resolveDownloads(1); - - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The mutated content should be translated.", - getH1, - "NEW TEXT FOR THE H1 [es to en]" - ); - }); - - await removeEnglishTab(); - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_unsupported.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_unsupported.js deleted file mode 100644 index 4eec51f65e..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_engine_unsupported.js +++ /dev/null @@ -1,59 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests that the translations button does not appear when the translations - * engine is not supported. - */ -add_task(async function test_translations_button_hidden_when_cpu_unsupported() { - const { cleanup, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.simulateUnsupportedEngine", true]], - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The button is not available." - ); - - await cleanup(); -}); - -/** - * Tests that the translate-page menuitem is not available in the app menu - * when the translations engine is not supported. - */ -add_task( - async function test_translate_page_app_menu_item_hidden_when_cpu_unsupported() { - const { cleanup, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.simulateUnsupportedEngine", true]], - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - const appMenuButton = getById("PanelUI-menu-button"); - - click(appMenuButton, "Opening the app menu"); - await BrowserTestUtils.waitForEvent(window.PanelUI.mainView, "ViewShown"); - - const translateSiteButton = document.getElementById( - "appMenu-translate-button" - ); - is( - translateSiteButton.hidden, - true, - "The app-menu translate button should be hidden because when the engine is not supported." - ); - - click(appMenuButton, "Closing the app menu"); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun.js deleted file mode 100644 index 1a33188932..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun.js +++ /dev/null @@ -1,55 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests that the first run message is displayed prior to performing a - * translation, but is no longer displayed after a translation occurs. - */ -add_task(async function test_translations_panel_firstrun() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await navigate("Load a different page on the same site", { - url: SPANISH_PAGE_URL_2, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await FullPageTranslationsTestUtils.openPanel({ - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.clickRestoreButton(); - - await FullPageTranslationsTestUtils.openPanel({ - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun_revisit.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun_revisit.js deleted file mode 100644 index aca7eaa08b..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_firstrun_revisit.js +++ /dev/null @@ -1,64 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests that the first-show intro message message is displayed - * when viewing the panel subsequent times on the same URL, - * when navigating to new URL, and when returning to the first URL - * after navigating away. - */ -add_task(async function test_translations_panel_firstrun() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await navigate("Navigate to a different website", { - url: SPANISH_PAGE_URL_DOT_ORG, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await navigate("Navigate back to the first website", { - url: SPANISH_PAGE_URL, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_flip_lexical_shortlist.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_flip_lexical_shortlist.js deleted file mode 100644 index 234ceb0e8f..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_flip_lexical_shortlist.js +++ /dev/null @@ -1,146 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests translations in the FullPageTranslationsPanel with the - * useLexicalShortlist pref initially set to false. It then toggles it to true, - * and then back to false, ensuring that the correct models are downloaded, and - * that the translations succeed with each flip of the pref. - */ -add_task( - async function test_full_page_translations_panel_lexical_shortlist_starting_false() { - const { tab, cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.useLexicalShortlist", false]], - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await waitForTranslationModelRecordsChanged(() => { - Services.prefs.setBoolPref( - "browser.translations.useLexicalShortlist", - true - ); - }); - - await openFindBar(tab); - - info( - "Awaiting new downloads since the active TranslationsEngine will be rebuilt." - ); - await resolveDownloads(1); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: - "The page's H1's title should be translated because it intersects with the viewport.", - }); - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - message: - "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", - } - ); - - await cleanup(); - } -); - -/** - * This test case tests translations in the FullPageTranslationsPanel with the - * useLexicalShortlist pref initially set to true. It then toggles it to false, - * and then back to true, ensuring that the correct models are downloaded, and - * that the translations succeed with each flip of the pref. - */ -add_task( - async function test_full_page_translations_panel_lexical_shortlist_starting_true() { - const { tab, cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.useLexicalShortlist", true]], - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await waitForTranslationModelRecordsChanged(() => { - Services.prefs.setBoolPref( - "browser.translations.useLexicalShortlist", - false - ); - }); - - await openFindBar(tab); - - info( - "Awaiting new downloads since the active TranslationsEngine will be rebuilt." - ); - await resolveDownloads(1); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: - "The page's H1's title should be translated because it intersects with the viewport.", - }); - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - message: - "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_fuzzing.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_fuzzing.js deleted file mode 100644 index 7e73eef47d..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_fuzzing.js +++ /dev/null @@ -1,243 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Manually destroy the engine while a page is in the background, and test that the page - * is still translated after switching back to it. - */ -add_task(async function test_translations_panel_fuzzing() { - const { - cleanup, - runInPage: runInSpanishPage, - tab: spanishTab, - } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - autoDownloadFromRemoteSettings: true, - }); - - /** - * @typedef {object} Tab - */ - - /** @type {Tab?} */ - let englishTab; - /** @type {Function?} */ - let removeEnglishTab; - /** @type {boolean} */ - let isSpanishPageTranslated = false; - /** @type {"spanish" | "english"} */ - let activeTab = "spanish"; - /** @type {boolean} */ - let isEngineMaybeDestroyed = true; - /** @type {boolean} */ - let isTitleMutated = false; - /** @type {boolean} */ - let hasVerifiedMutation = true; - - function reportOperation(name) { - info( - `\n\nOperation: ${name} ` + - JSON.stringify({ - activeTab, - englishTab: !!englishTab, - isSpanishPageTranslated, - isEngineMaybeDestroyed, - isTitleMutated, - }) - ); - } - - /** - * A list of fuzzing operations. They return false when they are a noop given the - * conditions. - * - * @type {object} - Record Promise> - */ - const operations = { - async addEnglishTab() { - if (!englishTab) { - reportOperation("addEnglishTab"); - const { removeTab, tab } = await addTab( - ENGLISH_PAGE_URL, - "Creating a new tab for a page in English." - ); - - englishTab = tab; - removeEnglishTab = removeTab; - activeTab = "english"; - return true; - } - return false; - }, - - async removeEnglishTab() { - if (removeEnglishTab) { - reportOperation("removeEnglishTab"); - await removeEnglishTab(); - - englishTab = null; - removeEnglishTab = null; - activeTab = "spanish"; - return true; - } - return false; - }, - - async translateSpanishPage() { - if (!isSpanishPageTranslated) { - reportOperation("translateSpanishPage"); - if (activeTab === "english") { - await switchTab(spanishTab, "spanish tab"); - } - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - await FullPageTranslationsTestUtils.openPanel({ - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton(); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: true, icon: true }, - "Translations button is fully loaded." - ); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage: runInSpanishPage, - } - ); - - isSpanishPageTranslated = true; - isEngineMaybeDestroyed = false; - activeTab = "spanish"; - return true; - } - return false; - }, - - async destroyEngineProcess() { - if ( - !isEngineMaybeDestroyed && - // Don't destroy the engine process until the mutation has been verified. - // There is an artifical race (e.g. only in tests) that happens from a new - // engine being requested, and forcefully destroyed before the it can be - // initialized. - hasVerifiedMutation - ) { - reportOperation("destroyEngineProcess"); - await EngineProcess.destroyTranslationsEngine(); - isEngineMaybeDestroyed = true; - } - return true; - }, - - async mutateSpanishPage() { - if (isSpanishPageTranslated && !isTitleMutated) { - reportOperation("mutateSpanishPage"); - - info("Mutate the page's content to re-trigger a translation."); - await runInSpanishPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - getH1().innerText = "New text for the H1"; - }); - - if (isEngineMaybeDestroyed) { - info("The engine may be recreated now."); - } - - isEngineMaybeDestroyed = false; - isTitleMutated = true; - hasVerifiedMutation = false; - return true; - } - return false; - }, - - async switchToSpanishTab() { - if (activeTab !== "spanish") { - reportOperation("switchToSpanishTab"); - await switchTab(spanishTab, "spanish tab"); - activeTab = "spanish"; - - if (isTitleMutated) { - await runInSpanishPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The mutated content should be translated.", - getH1, - "NEW TEXT FOR THE H1 [es to en]" - ); - }); - hasVerifiedMutation = true; - } - - return true; - } - return false; - }, - - async switchToEnglishTab() { - if (activeTab !== "english" && englishTab) { - reportOperation("switchToEnglishTab"); - await switchTab(englishTab, "english tab"); - activeTab = "english"; - return true; - } - return false; - }, - - async restoreSpanishPage() { - if (activeTab === "spanish" && isSpanishPageTranslated) { - reportOperation("restoreSpanishPage"); - await FullPageTranslationsTestUtils.openPanel({ - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.clickRestoreButton(); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInSpanishPage - ); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is reverted to have an icon." - ); - - isSpanishPageTranslated = false; - isTitleMutated = false; - return true; - } - return false; - }, - }; - - const fuzzSteps = 100; - info(`Starting the fuzzing with ${fuzzSteps} operations.`); - const opsArray = Object.values(operations); - - for (let i = 0; i < fuzzSteps; i++) { - // Pick a random operation and check if that it was not a noop, otherwise continue - // trying to find a valid operation. - // eslint-disable-next-line - while (true) { - const operation = opsArray[Math.floor(Math.random() * opsArray.length)]; - if (await operation()) { - break; - } - } - } - - if (removeEnglishTab) { - await removeEnglishTab(); - } - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_gear.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_gear.js deleted file mode 100644 index 574895a845..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_gear.js +++ /dev/null @@ -1,34 +0,0 @@ -/* 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, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.clickManageLanguages(); - - await 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/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_init_failure.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_init_failure.js deleted file mode 100644 index 34986726b8..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_init_failure.js +++ /dev/null @@ -1,25 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies that the proper error message is displayed in - * the FullPageTranslationsPanel if the panel tries to open, but the language - * dropdown menus fail to initialize. - */ -add_task(async function test_full_page_translations_panel_init_failure() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - TranslationsPanelShared.simulateLangListError(); - await FullPageTranslationsTestUtils.openPanel({ - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewInitFailure, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_modify_available_language_models.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_modify_available_language_models.js deleted file mode 100644 index d0f9aafd0a..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_modify_available_language_models.js +++ /dev/null @@ -1,148 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test verifies that when language models are added or removed from Remote Settings, - * then the list of available languages is immediately reflected in the FullPageTranslationsPanel's - * dropdown menu lists upon the panel's next open. - */ -add_task( - async function test_full_page_translations_panel_modify_available_language_models() { - const { runInPage, remoteClients, cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - autoDownloadFromRemoteSettings: true, - }); - - const { fromMenuList, toMenuList } = FullPageTranslationsPanel.elements; - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - ok( - !fromMenuList.querySelector('[value="ja"]'), - "The FullPageTranslationsPanel has no selection for Japanese in the from-menu-list." - ); - ok( - !toMenuList.querySelector('[value="ja"]'), - "The FullPageTranslationsPanel has no selection for Japanese in the to-menu-list." - ); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - const recordsForEnJa = createRecordsForLanguagePair("en", "ja"); - const recordsForJaEn = createRecordsForLanguagePair("ja", "en"); - - info("Publishing Japanese as a source language in Remote Settings."); - await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { - recordsToCreate: recordsForJaEn, - expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - ok( - fromMenuList.querySelector('[value="ja"]'), - "The FullPageTranslationsPanel now has an item for Japanese in the from-menu-list." - ); - ok( - !toMenuList.querySelector('[value="ja"]'), - "The FullPageTranslationsPanel still has no selection for Japanese in the to-menu-list." - ); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - info("Removing Japanese as a source language from Remote Settings."); - await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { - recordsToDelete: recordsForJaEn, - expectedDeletedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - ok( - !fromMenuList.querySelector('[value="ja"]'), - "The FullPageTranslationsPanel no longer has an item for Japanese in the from-menu-list." - ); - ok( - !toMenuList.querySelector('[value="ja"]'), - "The FullPageTranslationsPanel still has no selection for Japanese in the to-menu-list." - ); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - info("Publishing Japanese as a target language in Remote Settings."); - await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { - recordsToCreate: recordsForEnJa, - expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - ok( - !fromMenuList.querySelector('[value="ja"]'), - "The FullPageTranslationsPanel still has no selection for Japanese in the from-menu-list." - ); - ok( - toMenuList.querySelector('[value="ja"]'), - "The FullPageTranslationsPanel now has an item for Japanese in the to-menu-list." - ); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - info("Republishing Japanese as a source language in Remote Settings."); - await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { - recordsToCreate: recordsForJaEn, - expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - ok( - fromMenuList.querySelector('[value="ja"]'), - "The FullPageTranslationsPanel now has an item for Japanese in the from-menu-list." - ); - ok( - toMenuList.querySelector('[value="ja"]'), - "The FullPageTranslationsPanel still has an item for Japanese in the to-menu-list." - ); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "ja", - }); - await FullPageTranslationsTestUtils.clickTranslateButton(); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "ja", - runInPage, - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_language.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_language.js deleted file mode 100644 index 7436317fbb..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_language.js +++ /dev/null @@ -1,198 +0,0 @@ -/* 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 not translated 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate("Reload the page", { url: SPANISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate("Navigate to a different Spanish page", { - url: SPANISH_PAGE_URL_DOT_ORG, - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate("Reload the page", { url: SPANISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: false, - }); - - await FullPageTranslationsTestUtils.clickNeverTranslateLanguage(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate("Reload the page", { url: SPANISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site.js deleted file mode 100644 index 87b0bbe5f7..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site.js +++ /dev/null @@ -1,261 +0,0 @@ -/* 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 not translated 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate("Navigate to a Spanish page with the same content principal", { - url: SPANISH_PAGE_URL_2, - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate( - "Navigate to a Spanish page with a different content principal", - { url: SPANISH_PAGE_URL_DOT_ORG } - ); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button should be visible, because this content principal " + - "has not been denied translations permissions" - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate("Reload the page", { url: SPANISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate( - "Navigate to a Spanish page with the same content principal", - { url: SPANISH_PAGE_URL_2 } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate( - "Navigate to a Spanish page with a different content principal", - { url: SPANISH_PAGE_URL_DOT_ORG } - ); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button should be visible, because this content principal " + - "has not been denied translations permissions" - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate("Reload the page", { url: SPANISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate( - "Navigate to a Spanish page with the same content principal", - { url: SPANISH_PAGE_URL_2 } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate( - "Navigate to a Spanish page with a different content principal", - { - url: SPANISH_PAGE_URL_DOT_ORG, - downloadHandler: resolveDownloads, - } - ); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_auto.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_auto.js deleted file mode 100644 index cfca060f31..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_auto.js +++ /dev/null @@ -1,115 +0,0 @@ -/* 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 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate("Reload the page", { url: SPANISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate( - "Navigate to a Spanish page with the same content principal", - { url: SPANISH_PAGE_URL_2 } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate( - "Navigate to a Spanish page with a different content principal", - { - url: SPANISH_PAGE_URL_DOT_ORG, - } - ); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_basic.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_basic.js deleted file mode 100644 index a20c585224..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_basic.js +++ /dev/null @@ -1,64 +0,0 @@ -/* 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 not translated 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate("Navigate to a Spanish page with the same content principal", { - url: SPANISH_PAGE_URL_2, - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate( - "Navigate to a Spanish page with a different content principal", - { url: SPANISH_PAGE_URL_DOT_ORG } - ); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button should be visible, because this content principal " + - "has not been denied translations permissions" - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_manual.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_manual.js deleted file mode 100644 index a1a4e43527..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_never_translate_site_manual.js +++ /dev/null @@ -1,89 +0,0 @@ -/* 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 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: false } - ); - await FullPageTranslationsTestUtils.clickNeverTranslateSite(); - await FullPageTranslationsTestUtils.assertIsNeverTranslateSite( - SPANISH_PAGE_URL, - { checked: true } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate("Reload the page", { url: SPANISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate( - "Navigate to a Spanish page with the same content principal", - { url: SPANISH_PAGE_URL_2 } - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await navigate( - "Navigate to a Spanish page with a different content principal", - { url: SPANISH_PAGE_URL_DOT_ORG } - ); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button should be visible, because this content principal " + - "has not been denied translations permissions" - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_retry.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_retry.js deleted file mode 100644 index 69de13f999..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_retry.js +++ /dev/null @@ -1,59 +0,0 @@ -/* 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "fr", - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - pivotTranslation: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "fr", - runInPage, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_script_tags.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_script_tags.js deleted file mode 100644 index c4cf883f6b..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_script_tags.js +++ /dev/null @@ -1,153 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of the FullPageTranslationsPanel when the source - * language has a script tag and the target language does not have a script tag. - */ -add_task(async function test_translations_panel_source_lang_has_script_tag() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "zh-Hans", toLang: "en" }, - ], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "zh-Hans", - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "es", - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - pivotTranslation: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "zh-Hans", - toLanguage: "es", - runInPage, - }); - - await cleanup(); -}); - -/** - * This test case verifies the behavior of the FullPageTranslationsPanel when the target - * language has a script tag and the source language does not have a script tag. - */ -add_task(async function test_translations_panel_target_lang_has_script_tag() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "en", toLang: "zh-Hant" }, - ], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "zh-Hant", - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - pivotTranslation: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "zh-Hant", - runInPage, - }); - - await cleanup(); -}); - -/** - * This test case verifies the behavior of the FullPageTranslationsPanel when both the source - * language and the target language have a script tag. - */ -add_task( - async function test_translations_panel_source_and_target_langs_have_script_tags() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "zh-Hans", toLang: "en" }, - { fromLang: "en", toLang: "zh-Hans" }, - { fromLang: "zh-Hant", toLang: "en" }, - { fromLang: "en", toLang: "zh-Hant" }, - ], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "zh-Hant", - }); - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "zh-Hans", - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - pivotTranslation: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "zh-Hant", - toLanguage: "zh-Hans", - runInPage, - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_settings_unsupported_lang.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_settings_unsupported_lang.js deleted file mode 100644 index 38d29f30ab..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_settings_unsupported_lang.js +++ /dev/null @@ -1,76 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This tests a specific defect where the language checkbox states were not being - * updated correctly when visiting a web page in an unsupported language after - * previously enabling always-translate-language or never-translate-language - * on a site with a supported language. - * - * See https://bugzilla.mozilla.org/show_bug.cgi?id=1845611 for more information. - */ -add_task(async function test_unsupported_language_settings_menu_checkboxes() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: [ - // Do not include French. - { fromLang: "en", toLang: "es" }, - { fromLang: "es", toLang: "en" }, - ], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await navigate("Navigate to a page in an unsupported language.", { - url: FRENCH_PAGE_URL, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The translations button should be unavailable." - ); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - onOpenPanel: - FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("fr", { - checked: false, - disabled: true, - }); - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("fr", { - checked: false, - disabled: true, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_languages.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_languages.js deleted file mode 100644 index 4b6872aa58..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_languages.js +++ /dev/null @@ -1,79 +0,0 @@ -/* 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - const { translateButton } = FullPageTranslationsPanel.elements; - - ok(!translateButton.disabled, "The translate button starts as enabled"); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "en", - }); - - ok( - translateButton.disabled, - "The translate button is disabled when the languages are the same" - ); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "es", - }); - - ok( - !translateButton.disabled, - "When the languages are different it can be translated" - ); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "", - }); - - ok( - translateButton.disabled, - "The translate button is disabled nothing is selected." - ); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "en", - }); - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "fr", - }); - - ok(!translateButton.disabled, "The translate button can now be used"); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "en", - toLanguage: "fr", - runInPage, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_tabs_before_engine_ready.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_tabs_before_engine_ready.js deleted file mode 100644 index e974583c31..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_switch_tabs_before_engine_ready.js +++ /dev/null @@ -1,300 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the Translations URL-bar button does not become active in a tab - * where it is not currently present, when downloads complete and the TranslationsEngine - * becomes ready for translations that were requested in a different tab. - */ -add_task(async function test_button_does_not_update_when_button_is_not_shown() { - const { - tab: englishTab, - resolveDownloads, - cleanup, - } = await loadTestPage({ - page: ENGLISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The button should not be present since English is a known user language." - ); - - const { - tab: spanishTab, - runInPage: runInSpanishPage, - removeTab, - } = await addTab( - SPANISH_PAGE_URL, - "Creating a new tab for a page in Spanish." - ); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is present in the Spanish page." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInSpanishPage - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton(); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The icon presents the loading indicator." - ); - - await switchTab(englishTab, "Switch to English tab"); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The button should still not be present on the English page before resolving downloads." - ); - - await resolveDownloads(1); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The button should still not be present on the English page after resolving downloads." - ); - - await switchTab(spanishTab, "Switch back to the Spanish tab"); - - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - "es", - "en" - ); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage: runInSpanishPage, - }); - - await removeTab(); - await cleanup(); -}); - -/** - * This test case ensures that the Translations URL-bar button does not become active in a tab - * where it is present but inactive, when downloads complete and the TranslationsEngine - * becomes ready for translations that were requested in a different tab. - */ -add_task( - async function test_button_does_not_update_when_button_is_shown_but_inactive() { - const { - tab: spanishTabDotCom, - runInPage: runInSpanishDotComPage, - resolveDownloads, - cleanup, - } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is present Spanish .com tab." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInSpanishDotComPage - ); - - const { - tab: spanishTabDotOrg, - runInPage: runInSpanishDotOrgPage, - removeTab, - } = await addTab( - SPANISH_PAGE_URL_DOT_ORG, - "Creating a new tab for a page in Spanish with a .org URL." - ); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is present Spanish .org tab." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInSpanishDotOrgPage - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "fr", - }); - await FullPageTranslationsTestUtils.clickTranslateButton(); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The icon presents the loading indicator on the Spanish .org tab." - ); - - await switchTab(spanishTabDotCom, "Switch to the Spanish .com tab."); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button should be present but inactive on the Spanish .com tab." - ); - - await resolveDownloads(2); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button should be present but inactive on the Spanish .com tab, even after resolving downloads." - ); - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInSpanishDotComPage - ); - - await switchTab(spanishTabDotOrg, "Switch back to the Spanish .org tab"); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage: runInSpanishDotOrgPage, - } - ); - - await removeTab(); - await cleanup(); - } -); - -/** - * This test case ensures that the Translations URL-bar button does not change its displayed - * locale in a tab where it is present and active, when downloads complete and the TranslationsEngine - * becomes ready for translations that were requested in a different tab for a different language. - */ -add_task( - async function test_button_does_not_update_when_button_is_shown_but_inactive() { - const { - tab: spanishTabDotCom, - runInPage: runInSpanishDotComPage, - resolveDownloads, - cleanup, - } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is present Spanish .com tab." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInSpanishDotComPage - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "fr", - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage: runInSpanishDotComPage, - } - ); - - const { - tab: spanishTabDotOrg, - runInPage: runInSpanishDotOrgPage, - removeTab, - } = await addTab( - SPANISH_PAGE_URL_DOT_ORG, - "Creating a new tab for a page in Spanish with a .org URL." - ); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is present but not active in the Spanish .org tab." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInSpanishDotOrgPage - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "fr", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "uk", - }); - await FullPageTranslationsTestUtils.clickTranslateButton(); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The icon presents the loading indicator on the Spanish .org tab." - ); - - await switchTab(spanishTabDotCom, "Switch to the Spanish .com tab."); - - info("The Spanish .com page should still be translated to French."); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage: runInSpanishDotComPage, - } - ); - - await resolveDownloads(2); - - info( - "The Spanish .com page should still be translated to French, even after resolving downloads." - ); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage: runInSpanishDotComPage, - } - ); - - await switchTab(spanishTabDotOrg, "Switch back to the Spanish .org tab"); - - info("The Spanish .org page should be translated to Ukrainian."); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "uk", - runInPage: runInSpanishDotOrgPage, - } - ); - - await removeTab(); - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_target_language_persists_on_reopen.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_target_language_persists_on_reopen.js deleted file mode 100644 index c0c2795f80..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_target_language_persists_on_reopen.js +++ /dev/null @@ -1,46 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests the bug described in Bug 1838422, - * where the target language is reset if the user clicks - * outside the translations panel and reopens it. - * The user-selected target language should persist when - * the panel is reopened. - */ -add_task( - async function test_browser_translations_full_page_panel_target_language_persists_on_reopen() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "uk", - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - // Reopen the translations panel and check if the target language is still "fr". - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "uk", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_unsupported_lang.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_unsupported_lang.js deleted file mode 100644 index 87982e36ed..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_unsupported_lang.js +++ /dev/null @@ -1,33 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests how the unsupported language flow works. - */ -add_task(async function test_unsupported_lang() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - }); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - onOpenPanel: - FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await FullPageTranslationsTestUtils.clickChangeSourceLanguageButton({ - intro: true, - }); - FullPageTranslationsTestUtils.assertPanelViewIntro(); - FullPageTranslationsTestUtils.assertSelectedFromLanguage({ langTag: "" }); - FullPageTranslationsTestUtils.assertSelectedToLanguage({ langTag: "en" }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_weblanguage_differs_from_app.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_weblanguage_differs_from_app.js deleted file mode 100644 index 506b93d692..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_panel_weblanguage_differs_from_app.js +++ /dev/null @@ -1,42 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests what happens when the web languages differ from the app language. - */ -add_task(async function test_weblanguage_differs_app_locale() { - const { cleanup } = await loadTestPage({ - page: ENGLISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - systemLocales: ["en"], - appLocales: ["en"], - webLanguages: ["fr"], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The translations button is available" - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "en", - expectedToLanguage: "fr", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsNeverTranslateLanguage("en", { - checked: false, - disabled: false, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("en", { - checked: false, - disabled: false, - }); - - await closeAllOpenPanelsAndMenus(); - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_reader_mode.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_reader_mode.js deleted file mode 100644 index c8bd0b8614..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_reader_mode.js +++ /dev/null @@ -1,141 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests that the translations button becomes hidden when entering reader mode. - */ -add_task(async function test_translations_button_hidden_in_reader_mode() { - const { cleanup, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await toggleReaderMode(); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The translations button is now hidden in reader mode." - ); - - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's H1 is now the reader-mode header", - getH1, - "Translations Test" - ); - }); - - await runInPage(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's final paragraph is in Spanish.", - getFinalParagraph, - "— Pues, aunque mováis más brazos que los del gigante Briareo, me lo habéis de pagar." - ); - }); - - await toggleReaderMode(); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible again outside of reader mode." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await cleanup(); -}); - -/** - * Tests that translations persist when entering reader mode after translating. - */ -add_task(async function test_translations_persist_in_reader_mode() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - contentEagerMode: true, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertAllPageContentIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - message: - "The page's H1's title should be translated because it intersects with the viewport.", - }); - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - message: - "Attribute translations are always lazy based on intersection, so the final paragraph's title should remain untranslated.", - } - ); - - await runInPage(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's final paragraph is translated from Spanish to English.", - getFinalParagraph, - "— PUES, AUNQUE MOVÁIS MÁS BRAZOS QUE LOS DEL GIGANTE BRIAREO, ME LO HABÉIS DE PAGAR. [es to en]" - ); - }); - - await toggleReaderMode(); - - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's H1 is now the translated reader-mode header", - getH1, - "TRANSLATIONS TEST [es to en]" - ); - }); - - await runInPage(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's final paragraph is translated from Spanish to English.", - getFinalParagraph, - "— PUES, AUNQUE MOVÁIS MÁS BRAZOS QUE LOS DEL GIGANTE BRIAREO, ME LO HABÉIS DE PAGAR. [es to en]" - ); - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The translations button is now hidden in reader mode." - ); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_auto_translate.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_auto_translate.js deleted file mode 100644 index 24fd2497a4..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_auto_translate.js +++ /dev/null @@ -1,127 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests the entire flow of opening the translation settings menu and initiating - * an auto-translate requests. - */ -add_task(async function test_translations_telemetry_auto_translate() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.alwaysTranslateLanguage, - { - expectedEventCount: 1, - expectNewFlowId: false, - assertForMostRecentEvent: { - language: "es", - }, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 1, - expectNewFlowId: false, - }); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 1, - expectNewFlowId: false, - }); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 0], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - expectNewFlowId: false, - assertForMostRecentEvent: { - request_target: "full_page", - }, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.clickRestoreButton(); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 2, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "revisitView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.restorePageButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 2, - expectNewFlowId: false, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_basics.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_basics.js deleted file mode 100644 index 6d3f2f13e5..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_basics.js +++ /dev/null @@ -1,93 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests basic usage of the Translations panel, and that the telemetry events are logged accordingly - */ -add_task(async function test_translations_telemetry_basics() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 0, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.cancelButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 1, - expectNewFlowId: false, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 2, - expectNewFlowId: true, - assertForAllEvents: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.cancelButton, - { - expectedEventCount: 2, - expectNewFlowId: false, - } - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 2, - expectNewFlowId: false, - }); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_open_panel.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_open_panel.js deleted file mode 100644 index 128e7e3065..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_open_panel.js +++ /dev/null @@ -1,93 +0,0 @@ -/* 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(Glean.translationsPanel.open, { - expectedEventCount: 0, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.cancelButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 1, - expectNewFlowId: false, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 2, - expectNewFlowId: true, - assertForAllEvents: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.cancelButton, - { - expectedEventCount: 2, - expectNewFlowId: false, - } - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 2, - expectNewFlowId: false, - }); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer.js deleted file mode 100644 index 731029b9be..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer.js +++ /dev/null @@ -1,87 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests that the popup is automatically offered. - */ -add_task(async function test_translations_panel_auto_offer() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - autoOffer: true, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForAllEvents: { - auto_show: true, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.cancelButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 1, - expectNewFlowId: false, - }); - - await navigate("Navigate to another page on the same domain.", { - url: SPANISH_PAGE_URL_2, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is still shown." - ); - - await navigate("Navigate to a page on a different domain.", { - url: SPANISH_PAGE_URL_DOT_ORG, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 2, - expectNewFlowId: true, - assertForAllEvents: { - auto_show: true, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.cancelButton, - { - expectedEventCount: 2, - expectNewFlowId: false, - } - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 2, - expectNewFlowId: false, - }); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer_settings.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer_settings.js deleted file mode 100644 index 58b47e1823..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_panel_auto_offer_settings.js +++ /dev/null @@ -1,120 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests that the automatic offering of the popup can be disabled. - */ -add_task(async function test_translations_panel_auto_offer_settings() { - const { cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - // Use the auto offer mechanics, but default the pref to the off position. - autoOffer: true, - prefs: [["browser.translations.automaticallyPopup", false]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is shown." - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 0, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - await FullPageTranslationsTestUtils.assertIsAlwaysOfferTranslationsEnabled( - false - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForAllEvents: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await FullPageTranslationsTestUtils.clickAlwaysOfferTranslations(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.alwaysOfferTranslations, - { - expectedEventCount: 1, - expectNewFlowId: false, - assertForAllEvents: { - toggled_on: true, - }, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - await FullPageTranslationsTestUtils.assertIsAlwaysOfferTranslationsEnabled( - true - ); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 2, - expectNewFlowId: true, - assertForAllEvents: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.cancelButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 2, - expectNewFlowId: false, - }); - - await navigate( - "Wait for the popup to be shown when navigating to a different host.", - { - url: SPANISH_PAGE_URL_DOT_ORG, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - } - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 3, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: true, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_retranslate.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_retranslate.js deleted file mode 100644 index daf1c71a2b..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_retranslate.js +++ /dev/null @@ -1,164 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests the telemetry events for retranslating a page from the revisit view. - */ -add_task(async function test_translations_telemetry_retranslate() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "fr", - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "fr", - toLanguage: "en", - runInPage, - }); - - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 0], - ] - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectNewFlowId: true, - expectedEventCount: 1, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeFromLanguage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - language: "fr", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.translateButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 1, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - from_language: "fr", - to_language: "en", - auto_translate: false, - document_language: "es", - top_preferred_language: "en-US", - request_target: "full_page", - }, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "uk", - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "fr", - toLanguage: "uk", - runInPage, - }); - - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 2], - ["select", 0], - ] - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectNewFlowId: true, - expectedEventCount: 2, - assertForMostRecentEvent: { - auto_show: false, - view_name: "revisitView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeToLanguage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - language: "uk", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.translateButton, - { - expectedEventCount: 2, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 2, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - from_language: "fr", - to_language: "uk", - auto_translate: false, - document_language: "es", - top_preferred_language: "en", - request_target: "full_page", - }, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 2, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_switch_languages.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_switch_languages.js deleted file mode 100644 index cc4b6cd123..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_switch_languages.js +++ /dev/null @@ -1,192 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Tests the telemetry events for switching the from-language. - */ -add_task(async function test_translations_telemetry_switch_from_language() { - const { cleanup, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "en", - }); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeFromLanguage, - { - expectedEventCount: 1, - expectNewFlowId: false, - assertForMostRecentEvent: { - language: "en", - }, - } - ); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "es", - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeFromLanguage, - { - expectedEventCount: 2, - expectNewFlowId: false, - assertForMostRecentEvent: { - language: "es", - }, - } - ); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "", - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeFromLanguage, - { - expectedEventCount: 2, - } - ); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "en", - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeFromLanguage, - { - expectedEventCount: 3, - expectNewFlowId: false, - assertForMostRecentEvent: { - language: "en", - }, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); -}); - -/** - * Tests the telemetry events for switching the to-language. - */ -add_task(async function test_translations_telemetry_switch_to_language() { - const { cleanup, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "fr", - }); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeToLanguage, - { - expectedEventCount: 1, - expectNewFlowId: false, - assertForMostRecentEvent: { - language: "fr", - }, - } - ); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "en", - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeToLanguage, - { - expectedEventCount: 2, - expectNewFlowId: false, - assertForMostRecentEvent: { - language: "en", - }, - } - ); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ langTag: "" }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeToLanguage, - { - expectedEventCount: 2, - } - ); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "en", - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeToLanguage, - { - expectedEventCount: 3, - expectNewFlowId: false, - assertForMostRecentEvent: { - language: "en", - }, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_failure.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_failure.js deleted file mode 100644 index fcd809a0ec..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_failure.js +++ /dev/null @@ -1,197 +0,0 @@ -/* 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() { - const { cleanup, rejectDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 0, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: rejectDownloads, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewError, - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 2, - expectNewFlowId: false, - assertForMostRecentEvent: { - auto_show: true, - view_name: "errorView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.translateButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 1, - expectNewFlowId: false, - }); - await TestTranslationsTelemetry.assertEvent(Glean.translations.error, { - expectedEventCount: 1, - expectNewFlowId: false, - assertForMostRecentEvent: { - reason: "Error: Intentionally rejecting downloads.", - }, - }); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 0], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - expectNewFlowId: false, - assertForMostRecentEvent: { - from_language: "es", - to_language: "en", - auto_translate: false, - document_language: "es", - top_preferred_language: "en-US", - request_target: "full_page", - }, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); - } -); - -/** - * Tests the telemetry event for an automatic translation request failure. - */ -add_task(async function test_translations_telemetry_auto_translation_failure() { - const { cleanup, rejectDownloads, runInPage } = await loadTestPage({ - page: BLANK_PAGE, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.alwaysTranslateLanguages", "es"]], - }); - - await navigate("Navigate to a Spanish page", { - url: SPANISH_PAGE_URL, - downloadHandler: rejectDownloads, - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewError, - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: true, - view_name: "errorView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 0, - expectNewFlowId: false, - }); - await TestTranslationsTelemetry.assertEvent(Glean.translations.error, { - expectedEventCount: 1, - expectNewFlowId: false, - assertForMostRecentEvent: { - reason: "Error: Intentionally rejecting downloads.", - }, - }); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 0], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - expectNewFlowId: false, - assertForMostRecentEvent: { - from_language: "es", - to_language: "en", - auto_translate: true, - document_language: "es", - top_preferred_language: "en-US", - request_target: "full_page", - }, - } - ); - - await FullPageTranslationsTestUtils.clickCancelButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.cancelButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 1, - expectNewFlowId: false, - }); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_request.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_request.js deleted file mode 100644 index 07a5939b08..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_translation_request.js +++ /dev/null @@ -1,157 +0,0 @@ -/* 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, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 0, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.translateButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 1, - expectNewFlowId: false, - }); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 0], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - expectNewFlowId: false, - assertForMostRecentEvent: { - from_language: "es", - to_language: "en", - auto_translate: false, - document_language: "es", - top_preferred_language: "en-US", - request_target: "full_page", - }, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - 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: BLANK_PAGE, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.alwaysTranslateLanguages", "es"]], - }); - - await navigate("Navigate to a Spanish page", { - url: SPANISH_PAGE_URL, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "en", - runInPage, - }); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 0, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.translateButton, - { - expectedEventCount: 0, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 0, - }); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 0], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - from_language: "es", - to_language: "en", - auto_translate: true, - document_language: "es", - top_preferred_language: "en-US", - request_target: "full_page", - }, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_unsupported_lang.js b/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_unsupported_lang.js deleted file mode 100644 index aa4622a85d..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_full_page_telemetry_unsupported_lang.js +++ /dev/null @@ -1,212 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * The FullPageTranslationsPanel telemetry when transitioning from the unsupported language view. - */ -add_task(async function test_translations_telemetry_unsupported_lang() { - const { runInPage, resolveDownloads, cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - }); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - onOpenPanel: - FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "appMenu", - document_language: "es", - }, - }); - - await FullPageTranslationsTestUtils.clickChangeSourceLanguageButton({ - intro: true, - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeSourceLanguageButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 1, - expectNewFlowId: false, - }); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 2, - expectNewFlowId: false, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "appMenu", - document_language: "es", - }, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.cancelButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 2, - expectNewFlowId: false, - }); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - onOpenPanel: - FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 3, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "appMenu", - document_language: "es", - }, - }); - - await FullPageTranslationsTestUtils.clickDismissErrorButton(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.dismissErrorButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 3, - expectNewFlowId: false, - }); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - onOpenPanel: - FullPageTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 4, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "appMenu", - document_language: "es", - }, - }); - - await FullPageTranslationsTestUtils.clickChangeSourceLanguageButton({ - intro: true, - }); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeSourceLanguageButton, - { - expectedEventCount: 2, - expectNewFlowId: false, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 4, - expectNewFlowId: false, - }); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 5, - expectNewFlowId: false, - assertForMostRecentEvent: { - auto_show: false, - view_name: "defaultView", - opened_from: "appMenu", - document_language: "es", - }, - }); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: "fr", - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "fr", - toLanguage: "en", - runInPage, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.changeFromLanguage, - { - expectNewFlowId: false, - expectedEventCount: 1, - assertForMostRecentEvent: { - language: "fr", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsPanel.translateButton, - { - expectedEventCount: 1, - expectNewFlowId: false, - } - ); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.close, { - expectedEventCount: 5, - expectNewFlowId: false, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - expectNewFlowId: false, - assertForMostRecentEvent: { - from_language: "fr", - to_language: "en", - auto_translate: false, - document_language: "es", - top_preferred_language: "en-US", - request_target: "full_page", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 0], - ] - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_perf_es_en.js b/src/zen/tests/mochitests/translations/browser_translations_perf_es_en.js deleted file mode 100644 index d58904797b..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_perf_es_en.js +++ /dev/null @@ -1,109 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This metadata schema is parsed by the perftest infrastructure. - * - * The perftest runner then scrapes the logs for a JSON results matching this schema, - * which are logged by the TranslationsBencher class. - * - * @see {TranslationsBencher.Journal} - */ -const perfMetadata = { - owner: "Translations Team", - name: "Full-Page Translation (Spanish to English)", - description: - "Tests the speed of Full Page Translations using the Spanish-to-English model.", - options: { - default: { - perfherder: true, - perfherder_metrics: [ - { - name: "engine-init-time", - unit: "ms", - shouldAlert: true, - lowerIsBetter: true, - }, - { - name: "words-per-second", - unit: "WPS", - shouldAlert: true, - lowerIsBetter: false, - }, - { - name: "tokens-per-second", - unit: "TPS", - shouldAlert: true, - lowerIsBetter: false, - }, - { - name: "peak-parent-process-memory-usage", - unit: "MiB", - shouldAlert: true, - lowerIsBetter: true, - }, - { - name: "stabilized-parent-process-memory-usage", - unit: "MiB", - shouldAlert: true, - lowerIsBetter: true, - }, - { - name: "post-gc-parent-process-memory-usage", - unit: "MiB", - shouldAlert: true, - lowerIsBetter: true, - }, - { - name: "peak-inference-process-memory-usage", - unit: "MiB", - shouldAlert: true, - lowerIsBetter: true, - }, - { - name: "stabilized-inference-process-memory-usage", - unit: "MiB", - shouldAlert: true, - lowerIsBetter: true, - }, - { - name: "post-gc-inference-process-memory-usage", - unit: "MiB", - shouldAlert: true, - lowerIsBetter: true, - }, - { - name: "total-translation-time", - unit: "s", - shouldAlert: true, - lowerIsBetter: true, - }, - ], - verbose: true, - manifest: "perftest.toml", - manifest_flavor: "browser-chrome", - try_platform: ["linux", "mac", "win"], - }, - }, -}; - -/** - * Request 4x longer timeout for this test. - */ -requestLongerTimeout(4); - -/** - * Runs the translations benchmark tests from Spanish to English. - */ -add_task(async function test_translations_performance_es_en() { - await TranslationsBencher.benchmarkTranslation({ - page: SPANISH_BENCHMARK_PAGE_URL, - sourceLanguage: "es", - targetLanguage: "en", - speedBenchCount: 5, - memoryBenchCount: 5, - memorySampleInterval: 10, - }); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_auto_translate.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_auto_translate.js deleted file mode 100644 index ba624ef7ed..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_auto_translate.js +++ /dev/null @@ -1,82 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that recently translated target languages are stored, filtered, and retrieved - * properly when triggering multiple translations via auto translate. - */ -add_task(async function test_recent_language_memory_with_auto_translate() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [ - ["browser.translations.select.enable", true], - ["browser.translations.alwaysTranslateLanguages", "fr"], - ["browser.translations.mostRecentTargetLanguages", "uk"], - ], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectEnglishSection: true, - openAtEnglishSection: true, - expectedFromLanguage: "en", - expectedToLanguage: "uk", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickTranslateFullPageButton(); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "en", - toLanguage: "fr", - runInPage, - }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "es", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await FullPageTranslationsTestUtils.openTranslationsSettingsMenu(); - - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: false, - }); - await FullPageTranslationsTestUtils.clickAlwaysTranslateLanguage(); - await FullPageTranslationsTestUtils.assertIsAlwaysTranslateLanguage("es", { - checked: true, - }); - - await navigate("Navigate to a French page.", { url: FRENCH_PAGE_URL }); - await resolveDownloads(2); - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - "fr", - "es" - ); - - await navigate("Navigate to a Spanish page.", { url: SPANISH_PAGE_URL }); - await resolveDownloads(2); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated({ - fromLanguage: "es", - toLanguage: "fr", - runInPage, - }); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select.js deleted file mode 100644 index e72062d8a4..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select.js +++ /dev/null @@ -1,103 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that recently translated target languages are stored, filtered, and retrieved - * properly when triggering multiple translations between the Full-Page Translations panel and the Select - * Translations Panel in various combinations. - */ -add_task( - async function test_recent_language_memory_with_full_page_and_select_translations() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "fr", - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.clickRestoreButton(); - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "fr", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickTranslateFullPageButton(); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage, - } - ); - - await navigate("Navigate to a French page.", { url: FRENCH_PAGE_URL }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectH1: true, - openAtH1: true, - expectedFromLanguage: "fr", - expectedToLanguage: "uk", - pivotTranslation: true, - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select_multi_window.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select_multi_window.js deleted file mode 100644 index bf69a34598..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_and_select_multi_window.js +++ /dev/null @@ -1,135 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that recently translated target languages are stored, filtered, and retrieved - * properly when triggering multiple translations from the Full-Page Translations panel and the Select - * Translations panel in different windows. - */ -add_task( - async function test_recent_language_memory_with_full_page_and_select_translations_multi_window() { - const window1 = window; - const { runInPage, resolveDownloads, cleanup } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - const window2 = await BrowserTestUtils.openNewBrowserWindow(); - - const testPage2 = await loadTestPage({ - win: window2, - page: FRENCH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await focusWindow(window1); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await focusWindow(window2); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "fr", - expectedToLanguage: "uk", - win: window2, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "es", - win: window2, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window2, - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - "fr", - "es", - window2 - ); - - await focusWindow(window1); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - expectedFromLanguage: "es", - expectedToLanguage: "fr", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "es", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["en"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await focusWindow(window2); - - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - "fr", - "es", - window2 - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - win: window2, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window2, - }); - - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - "fr", - "en", - window2 - ); - - await testPage2.cleanup(); - await BrowserTestUtils.closeWindow(window2); - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window.js deleted file mode 100644 index 814fccddce..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window.js +++ /dev/null @@ -1,127 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that recently translated target languages are stored, filtered, and retrieved - * properly when triggering multiple translations from the Full-Page Translations panel in different windows. - */ -add_task( - async function test_full_page_translations_panel_recent_language_memory_with_multiple_windows() { - const window1 = window; - const { runInPage, resolveDownloads, cleanup } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - const window2 = await BrowserTestUtils.openNewBrowserWindow(); - - const testPage2 = await loadTestPage({ - win: window2, - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await focusWindow(window1); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - win: window1, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "uk", - win: window1, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window1, - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "uk", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - win: window1, - expectedToLanguage: "en", - }); - - await focusWindow(window2); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - testPage2.runInPage - ); - - await FullPageTranslationsTestUtils.openPanel({ - win: window2, - expectedFromLanguage: "es", - expectedToLanguage: "uk", - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "fr", - win: window2, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window2, - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - "es", - "fr", - window2 - ); - - await focusWindow(window1); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "uk", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - win: window1, - expectedToLanguage: "fr", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window1, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage, - } - ); - - await testPage2.cleanup(); - await BrowserTestUtils.closeWindow(window2); - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window_multi_tab.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window_multi_tab.js deleted file mode 100644 index 1928cf3956..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_multi_window_multi_tab.js +++ /dev/null @@ -1,321 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_setup(async function () { - await SpecialPowers.pushPrefEnv({ - set: [["test.wait300msAfterTabSwitch", true]], - }); -}); - -/** - * This test case open 5 tabs across 2 windows, requesting a translation to a different language in all 5 tabs before - * resolving all of the downloads at once. It then goes one by one through each open tab and ensures that they all show - * the correct locale code as well as translate the page content to the correct language. It also ensures that the language - * offered from the FullPageTranslationsPanel revisit view offers the correct language based on recent requests. - */ -add_task( - async function test_full_page_translations_panel_recent_language_memory_with_multiple_windows_and_multiple_tabs() { - const window1 = window; - const { - runInPage: runInEsEnPage, - cleanup: cleanupWindow1, - resolveBulkDownloads, - } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - }); - let expectedWasmDownloads = 0; - let expectedLanguagePairDownloads = 0; - - info("Opening a tab for es-en in window 1"); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is present and shows only the icon.", - window1 - ); - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInEsEnPage - ); - await FullPageTranslationsTestUtils.openPanel({ - win: window1, - expectedFromLanguage: "es", - expectedToLanguage: "en", - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window1, - }); - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The button presents the loading indicator", - window1 - ); - expectedWasmDownloads += 1; - expectedLanguagePairDownloads += 1; - - info("Opening a tab for es-fa in window 2"); - - const window2 = await BrowserTestUtils.openNewBrowserWindow(); - const { runInPage: runInEsFaPage, cleanup: cleanupWindow2 } = - await loadTestPage({ - win: window2, - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is present and shows only the icon.", - window2 - ); - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInEsFaPage - ); - await FullPageTranslationsTestUtils.openPanel({ - win: window2, - expectedFromLanguage: "es", - expectedToLanguage: "en", - }); - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "fa", - win: window2, - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window2, - }); - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The button presents the loading indicator", - window2 - ); - expectedWasmDownloads += 1; - expectedLanguagePairDownloads += 2; - - info("Opening a tab for es-sl in window 1"); - - await focusWindow(window1); - const { removeTab: removeEsSlTab, runInPage: runInEsSlPage } = await addTab( - SPANISH_PAGE_URL, - "Creating a new tab for es-sl", - window1 - ); - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is present and shows only the icon.", - window1 - ); - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInEsSlPage - ); - await FullPageTranslationsTestUtils.openPanel({ - win: window1, - expectedFromLanguage: "es", - expectedToLanguage: "fa", - }); - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "sl", - win: window1, - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window1, - }); - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The button presents the loading indicator", - window1 - ); - expectedWasmDownloads += 1; - expectedLanguagePairDownloads += 2; - - info("Opening a tab for es-uk in window 2"); - - await focusWindow(window2); - const { removeTab: removeEsUkTab, runInPage: runInEsUkPage } = await addTab( - SPANISH_PAGE_URL, - "Creating a new tab for es-uk", - window2 - ); - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is present and shows only the icon.", - window2 - ); - await FullPageTranslationsTestUtils.assertPageIsNotTranslated( - runInEsUkPage - ); - await FullPageTranslationsTestUtils.openPanel({ - win: window2, - expectedFromLanguage: "es", - expectedToLanguage: "sl", - }); - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "uk", - win: window2, - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window2, - }); - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The button presents the loading indicator", - window2 - ); - expectedWasmDownloads += 1; - expectedLanguagePairDownloads += 2; - - info("Opening a tab for fr-es in window 1"); - - await focusWindow(window1); - const { removeTab: removeFrEsTab, runInPage: runInFrEsPage } = await addTab( - FRENCH_PAGE_URL, - "Creating a new tab for fr-es", - window1 - ); - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is present and shows only the icon.", - window1 - ); - await runInFrEsPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The French page's H1 is translated from fr to es", - getH1, - "Cet élément d'en-tête HTML est écrit en français." - ); - }); - await FullPageTranslationsTestUtils.openPanel({ - win: window1, - expectedFromLanguage: "fr", - expectedToLanguage: "uk", - }); - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "es", - win: window1, - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - win: window1, - }); - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The button presents the loading indicator", - window1 - ); - expectedWasmDownloads += 1; - expectedLanguagePairDownloads += 2; - - info("Resolving all pending downloads for all open tabs"); - - await resolveBulkDownloads({ - expectedWasmDownloads, - expectedLanguagePairDownloads, - }); - - info("Ensuring that the fr-es tab is translated correctly"); - - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - "fr", - "es", - window1 - ); - await runInFrEsPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The French page's H1 is translated from fr to es", - getH1, - "CET ÉLÉMENT D'EN-TÊTE HTML EST ÉCRIT EN FRANÇAIS. [fr to es]" - ); - }); - await FullPageTranslationsTestUtils.openPanel({ - win: window1, - expectedToLanguage: "uk", - }); - await removeFrEsTab(); - - info("Ensuring that the es-uk tab is translated correctly"); - - await focusWindow(window2); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "uk", - runInPage: runInEsUkPage, - message: "The es-uk page should be translated to uk", - win: window2, - } - ); - await FullPageTranslationsTestUtils.openPanel({ - win: window2, - expectedToLanguage: "sl", - }); - await removeEsUkTab(); - - info("Ensuring that the es-sl tab is translated correctly"); - - await focusWindow(window1); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "sl", - runInPage: runInEsSlPage, - message: "The es-sl page should be translated to sl", - win: window1, - } - ); - await FullPageTranslationsTestUtils.openPanel({ - win: window1, - expectedToLanguage: "uk", - }); - await removeEsSlTab(); - - info("Ensuring that the es-fa tab is translated correctly"); - - await focusWindow(window2); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fa", - runInPage: runInEsFaPage, - message: "The es-fa page should be translated to fa", - win: window2, - } - ); - await FullPageTranslationsTestUtils.openPanel({ - win: window2, - expectedToLanguage: "uk", - }); - - info("Ensuring that the es-en tab is translated correctly"); - - await focusWindow(window1); - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage: runInEsEnPage, - message: "The es-en page should be translated to en", - win: window1, - } - ); - await FullPageTranslationsTestUtils.openPanel({ - win: window1, - expectedToLanguage: "uk", - }); - - await cleanupWindow2(); - await BrowserTestUtils.closeWindow(window2); - await cleanupWindow1(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_navigate.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_navigate.js deleted file mode 100644 index 9c15b6b435..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_navigate.js +++ /dev/null @@ -1,104 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that recently translated target languages are stored, filtered, and retrieved - * properly when triggering multiple translations from the Full-Page Translations panel when navigating - * between different pages in the same window. - */ -add_task( - async function test_full_page_translations_panel_recent_language_memory_when_navigating() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "fr", - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage, - } - ); - - await navigate("Navigate to a French page.", { url: FRENCH_PAGE_URL }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "fr", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "es", - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - "fr", - "es" - ); - - await navigate("Navigate to a Spanish page.", { url: SPANISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "fr", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - - await FullPageTranslationsTestUtils.clickCancelButton(); - - await navigate("Navigate to an English page.", { url: ENGLISH_PAGE_URL }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: false }, - "The button is not available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - openFromAppMenu: true, - expectedFromLanguage: "en", - expectedToLanguage: "es", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - "en", - "es" - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_retranslate.js b/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_retranslate.js deleted file mode 100644 index 03db62efd1..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_recent_language_memory_full_page_retranslate.js +++ /dev/null @@ -1,85 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that recently translated target languages are stored, filtered, and retrieved - * properly when triggering multiple translations from the Full-Page Translations panel on the same page. - */ -add_task( - async function test_full_page_translations_panel_recent_language_memory_on_retranslate() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SPANISH_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "uk", - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "uk", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: "fr", - }); - await FullPageTranslationsTestUtils.clickTranslateButton({ - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "uk", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.clickRestoreButton(); - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "fr", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewDefault, - }); - await FullPageTranslationsTestUtils.clickCancelButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_engine_unsupported.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_engine_unsupported.js deleted file mode 100644 index b5fe9de0ef..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_engine_unsupported.js +++ /dev/null @@ -1,35 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test checks the availability of the translate-selection menu item in the context menu, - * ensuring it is not visible when the hardware does not support Translations. In this case - * we simulate this scenario by setting "browser.translations.simulateUnsupportedEngine" to true. - */ -add_task( - async function test_translate_selection_menuitem_is_unavailable_when_engine_is_unsupported() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [ - ["browser.translations.enable", true], - ["browser.translations.select.enable", true], - ["browser.translations.simulateUnsupportedEngine", true], - ], - }); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectMenuItemVisible: false, - }, - "The translate-selection context menu item should be unavailable the translations engine is unsupported." - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_feature_disabled.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_feature_disabled.js deleted file mode 100644 index 8d6e4772da..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_feature_disabled.js +++ /dev/null @@ -1,114 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// This file ensures that the translate selection menu item is unavailable when the translation feature is disabled, -// This file will be removed when the feature is released, as the pref will no longer exist. -// -// https://bugzilla.mozilla.org/show_bug.cgi?id=1870366 -// -// However, for the time being, I like having these tests to ensure there is no regression when the pref -// is set to false. - -/** - * This test checks the availability of the translate-selection menu item in the context menu, - * ensuring it is not visible when the "browser.translations.select.enable" preference is set to false - * and no text is selected when the context menu is invoked. - */ -add_task( - async function test_translate_selection_menuitem_is_unavailable_with_feature_disabled_and_no_text_selected() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", false]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: false, - openAtSpanishSentence: true, - expectMenuItemVisible: false, - }, - "The translate-selection context menu item should be unavailable when the feature is disabled." - ); - - await cleanup(); - } -); - -/** - * This test case verifies the functionality of the translate-selection context menu item - * when the selected text is not in the user's preferred language. The menu item should be - * localized to translate to the target language matching the user's top preferred language - * when the selected text is detected to be in a different language. - */ -add_task( - async function test_translate_selection_menuitem_is_unavailable_with_feature_disabled_and_text_selected() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", false]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectMenuItemVisible: false, - }, - "The translate-selection context menu item should be unavailable when the feature is disabled." - ); - - await cleanup(); - } -); - -/** - * This test checks the availability of the translate-selection menu item in the context menu, - * ensuring it is not visible when the "browser.translations.select.enable" preference is set to false - * and the context menu is invoked on a hyperlink. This would result in the menu item being available - * if the pref were set to true. - */ -add_task( - async function test_translate_selection_menuitem_is_unavailable_with_feature_disabled_and_clicking_a_hyperlink() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", false]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: false, - openAtSpanishHyperlink: true, - expectMenuItemVisible: false, - }, - "The translate-selection context menu item should be unavailable when the feature is disabled." - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_app_locales.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_app_locales.js deleted file mode 100644 index 60f9ec0dff..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_app_locales.js +++ /dev/null @@ -1,106 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests various fallback edge cases regarding which language to - * offer for translations based on the user's application locale settings. - */ -add_task( - async function test_translate_selection_menuitem_preferred_app_locales() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "en", toLang: "es" }, - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "pl" }, - { fromLang: "pl", toLang: "en" }, - // Only supported as a source language - { fromLang: "fi", toLang: "en" }, - // Only supported as a target language - { fromLang: "en", toLang: "sl" }, - // Languages with script tags - { fromLang: "zh-Hans", toLang: "en" }, - { fromLang: "en", toLang: "zh-Hans" }, - { fromLang: "zh-Hant", toLang: "en" }, - { fromLang: "en", toLang: "zh-Hant" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["es", "fr", "fi", "ja", "sl"], - // The page language tag is "es", so expect the next language in the list. - expectedTargetLanguage: "fr", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["fr", "fi", "ja", "sl", "es"], - expectedTargetLanguage: "fr", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["fi", "ja", "sl", "es", "fr"], - // "fi" is not supported as a target language, so fall back - expectedTargetLanguage: "sl", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["ja", "sl", "es", "fr", "fi"], - expectedTargetLanguage: "sl", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["sl", "es", "fr", "fi", "ja"], - expectedTargetLanguage: "sl", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["zh-CN", "zh", "es", "fr", "fi", "ja"], - expectedTargetLanguage: "zh-Hans", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["zh-SG", "zh", "es", "fr", "fi", "ja"], - expectedTargetLanguage: "zh-Hans", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["zh-MY", "zh", "es", "fr", "fi", "ja"], - expectedTargetLanguage: "zh-Hans", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["zh-HK", "zh", "es", "fr", "fi", "ja"], - expectedTargetLanguage: "zh-Hant", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["zh-MO", "zh", "es", "fr", "fi", "ja"], - expectedTargetLanguage: "zh-Hant", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["zh-TW", "zh", "es", "fr", "fi", "ja"], - expectedTargetLanguage: "zh-Hant", - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_language_edge_cases.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_language_edge_cases.js deleted file mode 100644 index 1bee976a06..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_language_edge_cases.js +++ /dev/null @@ -1,74 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests various fallback edge cases regarding which language to - * offer for translations based on user settings and supported translations languages. - */ -add_task( - async function test_translate_selection_menuitem_preferred_language_edge_cases() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "en", toLang: "es" }, - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "pl" }, - { fromLang: "pl", toLang: "en" }, - // Only supported as a source language - { fromLang: "fi", toLang: "en" }, - // Only supported as a target language - { fromLang: "en", toLang: "sl" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - systemLocales: [], - appLocales: [], - webLanguages: [], - // No locales are specified, so fall back to "en". - expectedTargetLanguage: "en", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["fi", "fr", "en-US"], - webLanguages: ["zh"], - expectedTargetLanguage: "fr", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["zh", "uk", "fr", "en-US"], - webLanguages: ["fi"], - // Fall back to the first to-language compatible tag. - expectedTargetLanguage: "fr", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - appLocales: ["zh", "fi", "sl", "fr", "en-US"], - webLanguages: ["fi", "zh"], - // Fall back to the first to-language compatible tag. - expectedTargetLanguage: "sl", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - systemLocales: ["zh-TW", "zh-CN", "de"], - appLocales: ["pt-BR", "ja"], - webLanguages: ["cs", "hu"], - // None of these locales are supported, so default to "en". - expectedTargetLanguage: "en", - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_web_languages.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_web_languages.js deleted file mode 100644 index 41eb4acd38..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_preferred_web_languages.js +++ /dev/null @@ -1,65 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests various fallback edge cases regarding which language to - * offer for translations based on the user's web content language settings. - */ -add_task( - async function test_translate_selection_menuitem_preferred_web_languages() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "en", toLang: "es" }, - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "pl" }, - { fromLang: "pl", toLang: "en" }, - // Only supported as a source language - { fromLang: "fi", toLang: "en" }, - // Only supported as a target language - { fromLang: "en", toLang: "sl" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - webLanguages: ["es", "fr", "fi", "zh", "sl"], - // The page language tag is "es", so expect the next language in the list. - expectedTargetLanguage: "fr", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - webLanguages: ["fr", "fi", "zh", "sl", "es"], - expectedTargetLanguage: "fr", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - webLanguages: ["fi", "zh", "sl", "es", "fr"], - // "fi" is not supported as a target language, so fall back - expectedTargetLanguage: "sl", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - webLanguages: ["zh", "sl", "es", "fr", "fi"], - expectedTargetLanguage: "sl", - }); - - await SelectTranslationsTestUtils.testContextMenuItemWithLocales({ - runInPage, - webLanguages: ["sl", "es", "fr", "fi", "zh"], - expectedTargetLanguage: "sl", - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_full_page_translations_active.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_full_page_translations_active.js deleted file mode 100644 index e47180c733..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_full_page_translations_active.js +++ /dev/null @@ -1,174 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case checks the behavior of the translate-selection menu item in the context menu - * when full-page translations is active or inactive. The menu item should be available under - * the correct selected-text conditions while full-page translations is inactive, and it should - * never be available while full-page translations is active. - */ -add_task( - async function test_translate_selection_menuitem_with_text_selected_and_full_page_translations_active() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should be available while full-page translations is inactive." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should be available even while full-page translations is active." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.clickRestoreButton(); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should be available while full-page translations is inactive." - ); - - await cleanup(); - } -); - -/** - * This test case checks the behavior of the translate-selection menu item in the context menu - * when full-page translations is active or inactive. The menu item should be available under - * the correct link-clicked conditions while full-page translations is inactive, and it should - * never be available while full-page translations is active. - */ -add_task( - async function test_translate_selection_menuitem_with_link_clicked_and_full_page_translations_active() { - const { cleanup, resolveDownloads, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: false, - openAtSpanishHyperlink: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should be available while full-page translations is inactive." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - }); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: false, - openAtSpanishHyperlink: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should be available even while full-page translations is active." - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - - await FullPageTranslationsTestUtils.clickRestoreButton(); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: false, - openAtSpanishHyperlink: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should be available while full-page translations is inactive." - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_hyperlink.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_hyperlink.js deleted file mode 100644 index acd1960051..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_hyperlink.js +++ /dev/null @@ -1,139 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the functionality of the translate-selection context menu item - * when a hyperlink is right-clicked. The menu item should offer to translate the link text - * to a target language when the detected language of the link text does not match the preferred - * language. - */ -add_task( - async function test_translate_selection_menuitem_translate_link_text_to_target_language() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: false, - openAtSpanishHyperlink: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should be localized to translate the link text" + - "to the target language." - ); - - await cleanup(); - } -); - -/** - * This test case verifies the functionality of the translate-selection context menu item - * when a hyperlink is right-clicked, and the link text is in the top preferred language. - * The menu item should still offer to translate the link text to the top preferred language, - * since the Select Translations Panel should pass through the text for same-language translation. - */ -add_task( - async function test_translate_selection_menuitem_translate_link_text_in_preferred_language() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: false, - openAtEnglishHyperlink: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should be localized to translate the link text" + - "to the target language." - ); - - await cleanup(); - } -); - -/** - * This test case ensures that the translate-selection context menu item functions correctly - * when text is actively selected but the context menu is invoked on an unselected hyperlink. - * The selected text content should take precedence over the link text, and the menu item should - * be localized to translate the selected text to the target language, rather than the hyperlink text. - */ -add_task( - async function test_translate_selection_menuitem_selected_text_takes_precedence_over_link_text() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: true, - openAtEnglishHyperlink: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should be localized to translate the selection" + - "even though the hyperlink is the element on which the context menu was invoked." - ); - - await cleanup(); - } -); - -/** - * This test case verifies that the translate-selection context menu item is unavailable - * when the underlying hyperlink text is a URL, rather than plain text. - */ -add_task( - async function test_translate_selection_menuitem_with_raw_url_hyperlink() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - openAtURLHyperlink: true, - expectMenuItemVisible: false, - }, - "The translate-selection context menu item should be unavailable when the hyperlink text is a URL." - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_no_text_selected.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_no_text_selected.js deleted file mode 100644 index 71fd372e7d..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_no_text_selected.js +++ /dev/null @@ -1,37 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies that the translate-selection context menu item is unavailable - * when no text is selected. - */ -add_task( - async function test_translate_selection_menuitem_is_unavailable_when_no_text_is_selected() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: false, - openAtSpanishSentence: true, - expectMenuItemVisible: false, - }, - "The translate-selection context menu item should be unavailable when no text is selected." - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_text_selected.js b/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_text_selected.js deleted file mode 100644 index ce29a33795..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_context_menu_with_text_selected.js +++ /dev/null @@ -1,76 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the functionality of the translate-selection context menu item - * when the selected text is not in the user's preferred language. The menu item should be - * localized to translate to the target language matching the user's top preferred language - * when the selected text is detected to be in a different language. - */ -add_task( - async function test_translate_selection_menuitem_when_selected_text_is_not_preferred_language() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.assertPageIsNotTranslated(runInPage); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should display a target language " + - "when the selected text is not the preferred language." - ); - - await cleanup(); - } -); - -/** - * This test case verifies the functionality of the translate-selection context menu item - * when the selected text is detected to be in the user's preferred language. The menu item - * still be localized to the user's preferred language as a target, since the Select Translations - * Panel allows passing through the text for same-language translation. - */ -add_task( - async function test_translate_selection_menuitem_when_selected_text_is_preferred_language() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectEnglishSentence: true, - openAtEnglishSentence: true, - expectMenuItemVisible: true, - expectedTargetLanguage: "en", - }, - "The translate-selection context menu item should still display a target language " + - "when the selected text is in the preferred language." - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_a11y_utils.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_a11y_utils.js deleted file mode 100644 index 4e50faa783..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_a11y_utils.js +++ /dev/null @@ -1,87 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that A11yUtils.announce is called to announce to assistive technology - * whenever the translation completes, and that no call is made if the translation fails, - * since that is handled by aria-describedby when the error message occurs. - */ -add_task( - async function test_select_translations_panel_a11y_announce_translation_complete() { - const { cleanup, runInPage, resolveDownloads, rejectDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - is( - MockedA11yUtils.announceCalls.length, - 0, - "There should be no A11yUtils announce calls." - ); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - MockedA11yUtils.assertMostRecentAnnounceCall({ - expectedCallNumber: 1, - expectedArgs: { - id: "select-translations-panel-translation-complete-announcement", - }, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - MockedA11yUtils.assertMostRecentAnnounceCall({ - expectedCallNumber: 2, - expectedArgs: { - id: "select-translations-panel-translation-complete-announcement", - }, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - pivotTranslation: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - MockedA11yUtils.assertMostRecentAnnounceCall({ - expectedCallNumber: 3, - expectedArgs: { - id: "select-translations-panel-translation-complete-announcement", - }, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { - openDropdownMenu: false, - downloadHandler: rejectDownloads, - pivotTranslation: true, - onChangeLanguage: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - is( - MockedA11yUtils.announceCalls.length, - 3, - "A failed translation should not announce that the translation is complete." - ); - - await SelectTranslationsTestUtils.clickCancelButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_change_app_locale.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_change_app_locale.js deleted file mode 100644 index 12f336803e..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_change_app_locale.js +++ /dev/null @@ -1,74 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the language display names within the SelectTranslationsPanel - * dropdown menu lists update immediately upon the next panel open when the user's application - * locale changes. - */ -add_task( - async function test_select_translations_panel_change_application_locale() { - const { runInPage, resolveDownloads, cleanup } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - const { fromMenuList, toMenuList } = SelectTranslationsPanel.elements; - - is( - fromMenuList.label, - "French", - "The SelectTranslationsPanel from-menu-list languages should be localized to English display names." - ); - - is( - toMenuList.label, - "English", - "The SelectTranslationsPanel to-menu-list languages should be localized to English display names." - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - - info("Changing the application locale from English to Spanish"); - const cleanupLocales = await mockLocales({ - appLocales: ["es"], - webLanguages: ["en"], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - is( - fromMenuList.label, - "francés", - "The SelectTranslationsPanel from-menu-list languages should be localized to Spanish display names." - ); - - is( - toMenuList.label, - "inglés", - "The SelectTranslationsPanel to-menu-list languages should be localized to Spanish display names." - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanupLocales(); - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_close_on_new_tab.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_close_on_new_tab.js deleted file mode 100644 index 86e563b157..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_close_on_new_tab.js +++ /dev/null @@ -1,46 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests the scenario where the SelectTranslationsPanel is open - * and the user opens a new tab while the panel is still open. The panel should - * close appropriately, as the content relevant to the selection is no longer - * in the active tab. - */ -add_task( - async function test_select_translations_panel_translate_sentence_on_open() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - let tab; - - await SelectTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - async () => { - tab = await BrowserTestUtils.openNewForegroundTab( - gBrowser, - SPANISH_PAGE_URL, - true // waitForLoad - ); - } - ); - - BrowserTestUtils.removeTab(tab); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_copy_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_copy_button.js deleted file mode 100644 index 29eafb980d..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_copy_button.js +++ /dev/null @@ -1,95 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests functionality of the SelectTranslationsPanel copy button - * when retranslating by closing the panel and re-opening the panel to new links - * or selections of text. - */ -add_task(async function test_select_translations_panel_copy_button_on_reopen() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtSpanishHyperlink: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickCopyButton(); - await SelectTranslationsTestUtils.clickDoneButton(); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectEnglishSection: true, - openAtEnglishSection: true, - expectedFromLanguage: "en", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickCopyButton(); - await SelectTranslationsTestUtils.clickDoneButton(); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickCopyButton(); - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); -}); - -/** - * This test case tests functionality of the SelectTranslationsPanel copy button - * when retranslating by changing the from-language and to-language values for - * the same selection of source text. - */ -add_task( - async function test_select_translations_panel_copy_button_on_retranslate() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickCopyButton(); - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickCopyButton(); - await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { - openDropdownMenu: false, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickCopyButton(); - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_engine_cache.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_engine_cache.js deleted file mode 100644 index a0ef58c694..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_engine_cache.js +++ /dev/null @@ -1,59 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests that the SelectTranslationsPanel successfully - * caches the engine within the Translator for the given language pair, - * and if that engine is destroyed, the Translator will correctly reinitialize - * the engine, even for the same language pair. - */ -add_task( - async function test_select_translations_panel_translate_sentence_on_open() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - expectedDownloads: 1, - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - // No downloads because the engine is cached for this language pair. - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - info("Explicitly destroying the Translations Engine."); - await destroyTranslationsEngine(); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtFrenchHyperlink: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - // Expect downloads again since the engine was destroyed. - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_fallback_to_doc_language.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_fallback_to_doc_language.js deleted file mode 100644 index 9cf9e5d2f4..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_fallback_to_doc_language.js +++ /dev/null @@ -1,89 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests the case of opening the SelectTranslationsPanel when the - * detected language is unsupported, but the page language is known to be a supported - * language. The panel should automatically fall back to the page language in an - * effort to combat falsely identified selections. - */ -add_task( - async function test_select_translations_panel_translate_sentence_on_open() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include French. - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - // French is not supported, but the page is in Spanish, so expect Spanish. - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * Bug 1899354 - * - * This test case tests a specific defect in which the languageInfo cache within the - * SelectTranslationsPanel was not properly cleared between panel opens on different - * pages, causing the panel to think that the page's document language tag is that of - * the previously opened page, rather than the currently opened page. - */ -add_task( - async function test_select_translations_panel_translate_sentence_on_open() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: FRENCH_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectH1: true, - openAtH1: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await navigate("Navigate to the Select Translations test page.", { - url: SELECT_TEST_PAGE_URL, - }); - - // With the defect described by Bug 1899354 this would incorrectly translate to French, - // because it would fall back to the previously loaded page's language tag. - // - // However, since the SELECT_TEST_PAGE_URL is in Spanish, and the detected text is Spanish, - // we should have nothing to fall back to, and it should show the unsupported language view. - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_flip_lexical_shortlist.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_flip_lexical_shortlist.js deleted file mode 100644 index 020049442d..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_flip_lexical_shortlist.js +++ /dev/null @@ -1,104 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests translations in the SelectTranslationsPanel with the - * useLexicalShortlist pref initially set to false. It then toggles it to true, - * and then back to false, ensuring that the correct models are downloaded, and - * that the translations succeed with each flip of the pref. - */ -add_task( - async function test_select_translations_panel_lexical_shortlist_starting_false() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [ - ["browser.translations.select.enable", true], - ["browser.translations.useLexicalShortlist", false], - ], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await waitForTranslationModelRecordsChanged(() => { - Services.prefs.setBoolPref( - "browser.translations.useLexicalShortlist", - true - ); - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case tests translations in the SelectTranslationsPanel with the - * useLexicalShortlist pref initially set to true. It then toggles it to false, - * and then back to true, ensuring that the correct models are downloaded, and - * that the translations succeed with each flip of the pref. - */ -add_task( - async function test_select_translations_panel_lexical_shortlist_starting_true() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [ - ["browser.translations.select.enable", true], - ["browser.translations.useLexicalShortlist", true], - ], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await waitForTranslationModelRecordsChanged(() => { - Services.prefs.setBoolPref( - "browser.translations.useLexicalShortlist", - false - ); - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_init_failure.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_init_failure.js deleted file mode 100644 index 9e17b0705f..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_init_failure.js +++ /dev/null @@ -1,119 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the scenario of clicking the cancel button to close - * the SelectTranslationsPanel after the language lists fail to initialize upon - * opening the panel, and the proper error message is displayed. - */ -add_task(async function test_select_translations_panel_init_failure_cancel() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, - }); - - await SelectTranslationsTestUtils.clickCancelButton(); - - await cleanup(); -}); - -/** - * This test case verifies the scenario of opening the SelectTranslationsPanel to a valid - * language pair, but having the language lists fail to initialize, then clicking the try-again - * button multiple times until both initialization and translation succeed. - */ -add_task( - async function test_select_translations_panel_init_failure_try_again_into_translation() { - const { cleanup, runInPage, resolveDownloads, rejectDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - SelectTranslationsTestUtils.clickTryAgainButton, - SelectTranslationsTestUtils.assertPanelViewInitFailure - ); - - await SelectTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - async () => - SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: rejectDownloads, - }), - SelectTranslationsTestUtils.assertPanelViewTranslationFailure - ); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: resolveDownloads, - viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case verifies the scenario of opening the SelectTranslationsPanel to an unsupported - * language, but having the language lists fail to initialize, then clicking the try-again - * button multiple times until the unsupported-language view is shown. - */ -add_task( - async function test_select_translations_panel_init_failure_try_again_into_unsupported() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - SelectTranslationsTestUtils.clickTryAgainButton, - SelectTranslationsTestUtils.assertPanelViewInitFailure - ); - - await SelectTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - SelectTranslationsTestUtils.clickTryAgainButton, - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_modify_available_language_models.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_modify_available_language_models.js deleted file mode 100644 index d9121f6aad..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_modify_available_language_models.js +++ /dev/null @@ -1,163 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test verifies that when language models are added or removed from Remote Settings, - * then the list of available languages is immediately reflected in the SelectTranslationsPanel's - * dropdown menu lists upon the panel's next open. - */ -add_task( - async function test_select_translations_panel_modify_available_language_models() { - const { runInPage, remoteClients, resolveDownloads, cleanup } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - }); - - const { fromMenuList, toMenuList } = SelectTranslationsPanel.elements; - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - ok( - !fromMenuList.querySelector('[value="ja"]'), - "The SelectTranslationsPanel has no selection for Japanese in the from-menu-list." - ); - ok( - !toMenuList.querySelector('[value="ja"]'), - "The SelectTranslationsPanel has no selection for Japanese in the to-menu-list." - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - - const recordsForEnJa = createRecordsForLanguagePair("en", "ja"); - const recordsForJaEn = createRecordsForLanguagePair("ja", "en"); - - info("Publishing Japanese as a source language in Remote Settings."); - await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { - recordsToCreate: recordsForJaEn, - expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - ok( - fromMenuList.querySelector('[value="ja"]'), - "The SelectTranslationsPanel now has a selection for Japanese in the from-menu-list." - ); - ok( - !toMenuList.querySelector('[value="ja"]'), - "The SelectTranslationsPanel still has no selection for Japanese in the to-menu-list." - ); - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["ja"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - info("Removing Japanese as a source language from Remote Settings."); - await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { - recordsToDelete: recordsForJaEn, - expectedDeletedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - ok( - !fromMenuList.querySelector('[value="ja"]'), - "The SelectTranslationsPanel no longer has a selection for Japanese in the from-menu-list." - ); - ok( - !toMenuList.querySelector('[value="ja"]'), - "The SelectTranslationsPanel still has no selection for Japanese in the to-menu-list." - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - - info("Publishing Japanese as a target language in Remote Settings."); - await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { - recordsToCreate: recordsForEnJa, - expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - ok( - !fromMenuList.querySelector('[value="ja"]'), - "The SelectTranslationsPanel still has no selection for Japanese in the from-menu-list." - ); - ok( - toMenuList.querySelector('[value="ja"]'), - "The SelectTranslationsPanel now has a selection for Japanese in the to-menu-list." - ); - await SelectTranslationsTestUtils.changeSelectedToLanguage(["ja"], { - openDropdownMenu: false, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - info("Republishing Japanese as a source language in Remote Settings."); - await modifyRemoteSettingsRecords(remoteClients.translationModels.client, { - recordsToCreate: recordsForJaEn, - expectedCreatedRecordsCount: RECORDS_PER_LANGUAGE_PAIR_SHARED_VOCAB, - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "ja", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - ok( - fromMenuList.querySelector('[value="ja"]'), - "The SelectTranslationsPanel now has a selection for Japanese in the from-menu-list." - ); - ok( - toMenuList.querySelector('[value="ja"]'), - "The SelectTranslationsPanel still has a selection for Japanese in the to-menu-list." - ); - await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["ja"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_pdf.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_pdf.js deleted file mode 100644 index fd675e9cea..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_pdf.js +++ /dev/null @@ -1,42 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies that the Select Translations Panel functionality - * is available and works within PDF files. - */ -add_task(async function test_the_select_translations_panel_in_pdf_files() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: PDF_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectPdfSpan: true, - openAtPdfSpan: true, - expectedFromLanguage: "en", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { - openDropdownMenu: true, - pivotTranslation: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: false, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_reader_mode.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_reader_mode.js deleted file mode 100644 index 5f05b1a878..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_reader_mode.js +++ /dev/null @@ -1,44 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies that the Select Translations Panel functionality - * is available and works within reader mode. - */ -add_task(async function test_the_select_translations_panel_in_reader_mode() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await toggleReaderMode(); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectH1: true, - openAtH1: true, - expectedFromLanguage: "en", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { - openDropdownMenu: true, - pivotTranslation: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: false, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); -}); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_directly.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_directly.js deleted file mode 100644 index fff0326f75..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_directly.js +++ /dev/null @@ -1,70 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of triggering a translation by directly switching - * the from-language when the panel is already in the "translated" state from a previous - * language pair. - */ -add_task( - async function test_select_translations_panel_retranslate_on_change_from_language_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { - openDropdownMenu: false, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of triggering a translation by directly switching - * the to-language when the panel is already in the "translated" state from a previous - * language pair. - */ -add_task( - async function test_select_translations_panel_retranslate_on_change_to_language_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { - openDropdownMenu: false, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js deleted file mode 100644 index 16f2cb39f7..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_retranslate_on_change_language_from_dropdown_menu.js +++ /dev/null @@ -1,68 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of triggering a translation by switching the - * from-language by opening the language dropdown menu when the panel is already in - * the "translated" state from a previous language pair. - */ -add_task( - async function test_select_translations_panel_retranslate_on_change_from_language_via_popup() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtSpanishHyperlink: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of triggering a translation by switching the - * to-language by opening the language dropdown menu when the panel is already in - * the "translated" state from a previous language pair. - */ -add_task( - async function test_select_translations_panel_retranslate_on_change_to_language_via_popup() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtSpanishHyperlink: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_script_tags.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_script_tags.js deleted file mode 100644 index 1a2e229626..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_script_tags.js +++ /dev/null @@ -1,126 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of the SelectTranslationsPanel when the source - * language has a script tag and the target language does not have a script tag. - */ -add_task( - async function test_select_translations_panel_source_lang_has_script_tag() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "zh-Hant", toLang: "en" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["zh-Hant"], { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of the SelectTranslationsPanel when the target - * language has a script tag and the source language does not have a script tag. - */ -add_task( - async function test_select_translations_panel_target_lang_has_script_tag() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "en", toLang: "zh-Hans" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["zh-Hans"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - pivotTranslation: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of the SelectTranslationsPanel when both the source - * language and the target language have a script tag. - */ -add_task( - async function test_select_translations_panel_source_and_target_langs_have_script_tags() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "zh-Hans", toLang: "en" }, - { fromLang: "en", toLang: "zh-Hans" }, - { fromLang: "zh-Hant", toLang: "en" }, - { fromLang: "en", toLang: "zh-Hant" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["zh-Hant"], { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["zh-Hans"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - pivotTranslation: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_directly.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_directly.js deleted file mode 100644 index f45326800f..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_directly.js +++ /dev/null @@ -1,71 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of directly switching the from-language to the same - * from-language that is already selected, ensuring no change occurs to the translation state, - * and that no re-translation is triggered. - */ -add_task( - async function test_select_translations_panel_select_current_from_language_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { - openDropdownMenu: false, - // No downloads are resolved, because no re-translation is triggered. - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of directly switching the to-language to the same - * to-language that is already selected, ensuring no change occurs to the translation state, - * and that no re-translation is triggered. - */ -add_task( - async function test_select_translations_panel_select_current_from_language_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtFrenchHyperlink: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["en"], { - openDropdownMenu: false, - // No downloads are resolved, because no re-translation is triggered. - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_from_dropdown_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_from_dropdown_menu.js deleted file mode 100644 index 04aa731cf2..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_current_language_from_dropdown_menu.js +++ /dev/null @@ -1,71 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of directly switching the from-language to the same - * from-language that is already selected by opening the language dropdown menu, - * ensuring no change occurs to the translation state, and that no re-translation is triggered. - */ -add_task( - async function test_select_translations_panel_select_current_from_language_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { - openDropdownMenu: true, - // No downloads are resolved, because no re-translation is triggered. - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of directly switching the to-language to the same - * to-language that is already selected by opening the language dropdown menu, - * ensuring no change occurs to the translation state, and that no re-translation is triggered. - */ -add_task( - async function test_select_translations_panel_select_current_from_language_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtFrenchHyperlink: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["en"], { - openDropdownMenu: true, - // No downloads are resolved, because no re-translation is triggered. - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_directly.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_directly.js deleted file mode 100644 index 673faee796..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_directly.js +++ /dev/null @@ -1,66 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of switching the from-language to the same value - * that is currently selected in the to-language, effectively stealing the to-language's - * value, leaving it unselected and focused. - */ -add_task( - async function test_select_translations_panel_select_same_from_language_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["en"], { - openDropdownMenu: false, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of switching the to-language to the same value - * that is currently selected in the from-language, creating a passthrough translation - * of the source text directly into the text area. - */ -add_task( - async function test_select_translations_panel_select_same_to_language_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: false, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_from_dropdown_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_from_dropdown_menu.js deleted file mode 100644 index eea7a76bf2..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_select_same_from_and_to_languages_from_dropdown_menu.js +++ /dev/null @@ -1,66 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of switching the from-language to the same value - * that is currently selected in the to-language by opening the language dropdown menu, - * effectively stealing the to-language's value, leaving it unselected and focused. - */ -add_task( - async function test_select_translations_panel_select_same_from_language_via_popup() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["en"], { - openDropdownMenu: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of switching the to-language to the same value - * that is currently selected in the from-language by opening the language dropdown menu, - * creating a passthrough translation of the source text directly into the text area. - */ -add_task( - async function test_select_translations_panel_select_same_to_language_via_popup() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_settings_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_settings_menu.js deleted file mode 100644 index b6263325d5..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_settings_menu.js +++ /dev/null @@ -1,70 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests the scenario of clicking the settings menu item - * that leads to the translations section of the about:preferences settings - * page in Firefox. - */ -add_task(async function test_select_translations_panel_open_settings_page() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.openPanelSettingsMenu(); - SelectTranslationsTestUtils.clickTranslationsSettingsPageMenuItem(); - - await waitForCondition( - () => gBrowser.currentURI.spec === "about:preferences#general", - "Waiting for about:preferences to be opened." - ); - - info("Remove the about:preferences tab"); - gBrowser.removeCurrentTab(); - - await cleanup(); -}); - -/** - * This test case tests the scenario of opening the SelectTranslationsPanel - * settings menu from the unsupported-language panel state. - */ -add_task( - async function test_select_translations_panel_open_settings_menu_from_unsupported_language() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await SelectTranslationsTestUtils.openPanelSettingsMenu(); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_full_page_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_full_page_button.js deleted file mode 100644 index 0d4fa1090c..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_full_page_button.js +++ /dev/null @@ -1,87 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * Simulates clicking the translate-full-page button with a from-language that - * matches the language of the given document. - */ -add_task( - async function test_select_translations_panel_translat_full_page_button_matching_doc_lang() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtSpanishHyperlink: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickTranslateFullPageButton(); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await cleanup(); - } -); - -/** - * Simulates clicking the translate-full-page button after changing the from-language - * and to-language values to values that don't match the document language or the - * user's app locale, ensuring that the current selection is respected. - */ -add_task( - async function test_select_translations_panel_translat_full_page_button_matching_doc_lang() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["fr"], { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - pivotTranslation: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickTranslateFullPageButton(); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "fr", - toLanguage: "uk", - runInPage, - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_directly.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_directly.js deleted file mode 100644 index 7ea721fb0f..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_directly.js +++ /dev/null @@ -1,67 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of triggering a translation by directly switching - * the from-language to a valid selection when the panel is in the "idle" state without - * valid language pair. - */ -add_task( - async function test_select_translations_panel_translate_on_change_from_language_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["fr"], { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of triggering a translation by directly switching - * the to-language to a valid selection when the panel is in the "idle" state without - * valid language pair. - */ -add_task( - async function test_select_translations_panel_translate_on_change_to_language_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectEnglishSection: true, - openAtEnglishSection: true, - expectedFromLanguage: "en", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_from_dropdown_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_from_dropdown_menu.js deleted file mode 100644 index c0ba02f6db..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_from_dropdown_menu.js +++ /dev/null @@ -1,67 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of triggering a translation by switching the - * from-language to a valid selection by opening the language dropdown when the panel - * is in the "idle" state without valid language pair. - */ -add_task( - async function test_select_translations_panel_translate_on_change_from_language() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["fr"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of triggering a translation by switching the - * to-language to a valid selection by opening the language dropdown when the panel - * is in the "idle" state without valid language pair. - */ -add_task( - async function test_select_translations_panel_translate_on_change_to_language() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectEnglishSection: true, - openAtEnglishSection: true, - expectedFromLanguage: "en", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_directly.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_directly.js deleted file mode 100644 index cd60f73e6c..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_directly.js +++ /dev/null @@ -1,98 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of directly changing the from-language in rapid succession, - * ensuring that any triggered translations are resolved/dropped in order, and that the final translated - * state matches the final selected language. - */ -add_task( - async function test_select_translations_panel_translate_on_change_from_language_multiple_times_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "fi", toLang: "en" }, - { fromLang: "en", toLang: "fi" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage( - ["fa", "fi", "fr", "sl", "uk"], - { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - } - ); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of directly changing the to-language in rapid succession, - * ensuring that any triggered translations are resolved/dropped in order, and that the final translated - * state matches the final selected language. - */ -add_task( - async function test_select_translations_panel_translate_on_change_to_language_multiple_times_directly() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "fi", toLang: "en" }, - { fromLang: "en", toLang: "fi" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtEnglishHyperlink: true, - expectedFromLanguage: "en", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage( - ["es", "fa", "fi", "fr", "sl", "uk", "fa"], - { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_from_dropdown_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_from_dropdown_menu.js deleted file mode 100644 index 1b2044ef97..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_change_language_multiple_times_from_dropdown_menu.js +++ /dev/null @@ -1,99 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of directly changing the from-language in rapid succession - * by opening the language dropdown menu, ensuring that any triggered translations are resolved/dropped - * in order, and that the final translated state matches the final selected language. - */ -add_task( - async function test_select_translations_panel_translate_on_change_from_language_multiple_times_via_popup() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "fi", toLang: "en" }, - { fromLang: "en", toLang: "fi" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage( - ["fa", "fi", "fr", "sl", "uk"], - { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - } - ); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of directly changing the to-language in rapid succession - * by opening the language dropdown menu, ensuring that any triggered translations are resolved/dropped - * in order, and that the final translated state matches the final selected language. - */ -add_task( - async function test_select_translations_panel_translate_on_change_to_language_multiple_times_via_popup() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "fi", toLang: "en" }, - { fromLang: "en", toLang: "fi" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectEnglishSentence: true, - openAtEnglishSentence: true, - expectedFromLanguage: "en", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage( - ["es", "fa", "fi", "fr", "sl", "uk"], - { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - } - ); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_open.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_open.js deleted file mode 100644 index 7c7d6d88c9..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translate_on_open.js +++ /dev/null @@ -1,86 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests the case of opening the SelectTranslationsPanel to a valid - * language pair from a short selection of text, which should trigger a translation - * on panel open. - */ -add_task( - async function test_select_translations_panel_translate_sentence_on_open() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case tests the case of opening the SelectTranslationsPanel to a valid - * language pair from hyperlink text, which should trigger a translation on panel open. - */ -add_task( - async function test_select_translations_panel_translate_link_text_on_open() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtSpanishHyperlink: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case tests the case of opening the SelectTranslationsPanel to a valid - * language pair from a long selection of text, which should trigger a translation - * on panel open. - */ -add_task( - async function test_select_translations_panel_translate_long_text_on_open() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_after_unsupported_language.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_after_unsupported_language.js deleted file mode 100644 index 79ce46b7dc..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_after_unsupported_language.js +++ /dev/null @@ -1,55 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests the scenario of encountering the translation failure message - * as a result of changing the source language from the unsupported-language state. - */ -add_task( - async function test_select_translations_panel_failure_after_unsupported_language() { - const { cleanup, runInPage, resolveDownloads, rejectDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( - "fr" - ); - - await SelectTranslationsTestUtils.clickTranslateButton({ - downloadHandler: rejectDownloads, - viewAssertion: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: rejectDownloads, - viewAssertion: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: resolveDownloads, - viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_open.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_open.js deleted file mode 100644 index 0fc133f269..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_open.js +++ /dev/null @@ -1,92 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests the scenario of opening the SelectTranslationsPanel to a translation - * attempt that fails, followed by closing the panel via the cancel button, and then re-attempting - * the translation by re-opening the panel and having it succeed. - */ -add_task( - async function test_select_translations_panel_translation_failure_on_open_then_cancel_and_reopen() { - const { cleanup, runInPage, rejectDownloads, resolveDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: rejectDownloads, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.clickCancelButton(); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case tests the scenario of opening the SelectTranslationsPanel to a translation - * attempt that fails, followed by clicking the try-again button multiple times to retry the - * translation until it finally succeeds. - */ -add_task( - async function test_select_translations_panel_translation_failure_on_open_then_try_again() { - const { cleanup, runInPage, rejectDownloads, resolveDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: rejectDownloads, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: rejectDownloads, - viewAssertion: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: rejectDownloads, - viewAssertion: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: resolveDownloads, - viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_retranslate.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_retranslate.js deleted file mode 100644 index d19439c6a4..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_translation_failure_on_retranslate.js +++ /dev/null @@ -1,128 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests the scenario of encountering the translation failure message - * as a result of changing the selected from-language, along with moving from the failure - * state to a successful translation also by changing the selected from-language. - */ -add_task( - async function test_select_translations_panel_translation_failure_on_change_from_language() { - const { cleanup, runInPage, rejectDownloads, resolveDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { - openDropdownMenu: false, - downloadHandler: rejectDownloads, - onChangeLanguage: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk"], { - openDropdownMenu: true, - downloadHandler: rejectDownloads, - onChangeLanguage: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["es"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk"], { - openDropdownMenu: false, - downloadHandler: rejectDownloads, - onChangeLanguage: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: resolveDownloads, - viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case tests the scenario of encountering the translation failure message - * as a result of changing the selected to-language, along with moving from the failure - * state to a successful translation also by changing the selected to-language. - */ -add_task( - async function test_select_translations_panel_translation_failure_on_change_to_language() { - const { cleanup, runInPage, rejectDownloads, resolveDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { - openDropdownMenu: false, - downloadHandler: rejectDownloads, - onChangeLanguage: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { - openDropdownMenu: true, - downloadHandler: rejectDownloads, - onChangeLanguage: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["es"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - pivotTranslation: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { - openDropdownMenu: false, - downloadHandler: rejectDownloads, - onChangeLanguage: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: resolveDownloads, - pivotTranslation: true, - viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_panel_unsupported_language.js b/src/zen/tests/mochitests/translations/browser_translations_select_panel_unsupported_language.js deleted file mode 100644 index 0898bd125b..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_panel_unsupported_language.js +++ /dev/null @@ -1,163 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the behavior of opening the SelectTranslationsPanel to an unsupported language - * and then clicking the done button to close the panel. - */ -add_task( - async function test_select_translations_panel_unsupported_click_done_button() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of opening the SelectTranslationsPanel to an unsupported language - * then changing the source language to the same language as the app locale, triggering a same-language - * translation, then changing the from-language and to-language multiple times. - */ -add_task( - async function test_select_translations_panel_unsupported_then_to_same_language_translation() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "fi", toLang: "en" }, - { fromLang: "en", toLang: "fi" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( - "en" - ); - - await SelectTranslationsTestUtils.clickTranslateButton({ - viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk", "fi"], { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["sl", "fr"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - pivotTranslation: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); - -/** - * This test case verifies the behavior of opening the SelectTranslationsPanel to an unsupported language - * then changing the source language to a valid language, followed by changing the from-language and to-language - * multiple times. - */ -add_task( - async function test_select_translations_panel_unsupported_into_different_language_translation() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "fi", toLang: "en" }, - { fromLang: "en", toLang: "fi" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( - "fr" - ); - - await SelectTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk", "fi"], { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - pivotTranslation: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["sl", "uk"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - pivotTranslation: true, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk"], { - openDropdownMenu: false, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - await SelectTranslationsTestUtils.clickDoneButton(); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_both_languages_together.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_both_languages_together.js deleted file mode 100644 index 0b72f93f71..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_both_languages_together.js +++ /dev/null @@ -1,333 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case tests the edge-case scenario where, through keyboard navigation, a user is technically - * able to change both the from-language and the to-language value before triggering a re-translation. - * We want to make sure in this situation that both telemetry events for a changed from-language and - * for a changed to-language fire. - * - * The test covers all three methods of triggering the translation: - * - Pressing the Enter key with the from-menulist focused. - * - Pressing the Enter key with the to-menulist focused. - * - Tabbing to focus the textarea after a language has been changed. - */ -add_task( - async function test_select_translations_panel_change_from_and_to_languages_before_retranslation() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "fi", toLang: "en" }, - { fromLang: "en", toLang: "fi" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 165, - source_text_word_count: 28, - }, - } - ); - - const { fromMenuList, toMenuList } = SelectTranslationsPanel.elements; - - info( - "Changing both the from-language and to-language before triggering translation." - ); - fromMenuList.value = "fr"; - toMenuList.value = "uk"; - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 0, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 0, - } - ); - - { - info( - "Triggering a single translation with both updated languages via Enter key on from-menulist." - ); - const translatablePhasePromise = - SelectTranslationsTestUtils.waitForPanelState("translatable"); - focusElementAndSynthesizeKey(fromMenuList, "KEY_Enter"); - await translatablePhasePromise; - - await SelectTranslationsTestUtils.handleDownloads({ - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - await SelectTranslationsTestUtils.assertPanelViewTranslated(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - language: "fr", - previous_language: "es", - document_language: "es", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - language: "uk", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fr", - to_language: "uk", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - }, - } - ); - } - - { - info( - "Changing both the from-language and to-language before triggering translation." - ); - fromMenuList.value = "fa"; - toMenuList.value = "en"; - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 1, - } - ); - - info( - "Triggering a single translation with both updated languages via Enter key on to-menulist." - ); - const translatablePhasePromise = - SelectTranslationsTestUtils.waitForPanelState("translatable"); - focusElementAndSynthesizeKey(toMenuList, "KEY_Enter"); - await translatablePhasePromise; - - await SelectTranslationsTestUtils.handleDownloads({ - downloadHandler: resolveDownloads, - }); - await SelectTranslationsTestUtils.assertPanelViewTranslated(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - language: "fa", - previous_language: "fr", - document_language: "es", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - language: "en", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 3], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 3, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fa", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - }, - } - ); - } - - { - info( - "Changing both the from-language and to-language before triggering translation." - ); - fromMenuList.value = "sl"; - toMenuList.value = "fi"; - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 2, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 2, - } - ); - - info( - "Triggering a single translation with both updated languages via Tab key on to-menulist." - ); - const translatablePhasePromise = - SelectTranslationsTestUtils.waitForPanelState("translatable"); - focusElementAndSynthesizeKey(toMenuList, "KEY_Tab"); - await translatablePhasePromise; - - await SelectTranslationsTestUtils.handleDownloads({ - pivotTranslation: true, - downloadHandler: resolveDownloads, - }); - await SelectTranslationsTestUtils.assertPanelViewTranslated(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 3, - assertForMostRecentEvent: { - language: "sl", - previous_language: "fa", - document_language: "es", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 3, - assertForMostRecentEvent: { - language: "fi", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 4], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 4, - assertForMostRecentEvent: { - document_language: "es", - from_language: "sl", - to_language: "fi", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - }, - } - ); - } - - await SelectTranslationsTestUtils.clickDoneButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 4, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_languages_multiple_times.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_languages_multiple_times.js deleted file mode 100644 index 942c828ed5..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_change_languages_multiple_times.js +++ /dev/null @@ -1,374 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the data associated the change-from-language and change-to-language - * telemetry events when changing selected the from-language menu item multiple times in different ways. - */ -add_task( - async function test_select_translations_panel_change_from_language_multiple_times() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "fi", toLang: "en" }, - { fromLang: "en", toLang: "fi" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 165, - source_text_word_count: 28, - }, - } - ); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage( - ["fi", "fr", "sl"], - { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - language: "sl", - previous_language: "es", - document_language: "es", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 0, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - document_language: "es", - from_language: "sl", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - }, - } - ); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["uk", "fa"], { - openDropdownMenu: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 3, - assertForMostRecentEvent: { - language: "fa", - previous_language: "uk", - document_language: "es", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 0, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 4], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 4, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fa", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - }, - } - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 4, - }); - - await cleanup(); - } -); - -/** - * This test case verifies the data associated the change-from-language and change-to-language - * telemetry events when changing the selected to-language menu item multiple times in different ways. - */ -add_task( - async function test_select_translations_panel_change_to_language_multiple_times() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "fi", toLang: "en" }, - { fromLang: "en", toLang: "fi" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 165, - source_text_word_count: 28, - }, - } - ); - - await SelectTranslationsTestUtils.changeSelectedToLanguage( - ["sl", "fi", "fa"], - { - openDropdownMenu: false, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 0, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - language: "fa", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "fa", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 165, - source_text_word_count: 28, - }, - } - ); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr", "uk"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 0, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 3, - assertForMostRecentEvent: { - language: "uk", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 4], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 4, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "uk", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 165, - source_text_word_count: 28, - }, - } - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 4, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_cancel.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_cancel.js deleted file mode 100644 index 7503f11074..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_cancel.js +++ /dev/null @@ -1,102 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the counts and extra data sent from telemetry events when interacting - * with the SelectTranslationsPanel's initialization-failure UI and the user cancels after retrying. - */ -add_task( - async function test_select_translations_panel_telemetry_init_failure_then_cancel() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.initializationFailureMessage, - { - expectedEventCount: 1, - } - ); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.clickTryAgainButton({ - viewAssertion: SelectTranslationsTestUtils.assertPanelViewInitFailure, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.tryAgainButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 2, - expectNewFlowId: false, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.initializationFailureMessage, - { - expectedEventCount: 2, - } - ); - - await SelectTranslationsTestUtils.clickCancelButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.cancelButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 2, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_succeed.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_succeed.js deleted file mode 100644 index f6d4797725..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_init_failure_ui_then_succeed.js +++ /dev/null @@ -1,122 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the counts and extra data sent from telemetry events when interacting - * with the SelectTranslationsPanel's initialization-failure UI and retrying is successful. - */ -add_task( - async function test_select_translations_panel_telemetry_init_failure_then_succeed() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.initializationFailureMessage, - { - expectedEventCount: 1, - } - ); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: resolveDownloads, - viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.tryAgainButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 2, - expectNewFlowId: false, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: - AppConstants.platform === "win" - ? 2064 // With carriage returns - : 2041, // No carriage returns - source_text_word_count: 358, - }, - } - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 2, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_cancel_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_cancel_button.js deleted file mode 100644 index 5ad1c4a816..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_cancel_button.js +++ /dev/null @@ -1,174 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the SelectTranslationsPanel cancel button can be invoked with the Enter key - * from the initialization-failure panel view. - */ -add_task( - async function test_select_translations_panel_invoke_init_failure_cancel_button_with_enter_key() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.cancelButton, - "KEY_Enter" - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.cancelButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel cancel button can be invoked with the space bar - * from the initialization-failure panel view. - */ -add_task( - async function test_select_translations_panel_invoke_init_failure_cancel_button_with_space_bar() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.cancelButton, - " " - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.cancelButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel cancel button can be invoked with the Enter key - * from the translation-failure panel view. - */ -add_task( - async function test_select_translations_panel_invoke_translation_failure_cancel_button_with_enter_key() { - const { cleanup, runInPage, rejectDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: rejectDownloads, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.cancelButton, - "KEY_Enter" - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.cancelButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel cancel button can be invoked with the space bar - * from the translation-failure panel view. - */ -add_task( - async function test_select_translations_panel_invoke_translation_failure_cancel_button_with_space_bar() { - const { cleanup, runInPage, rejectDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: rejectDownloads, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.cancelButton, - " " - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.cancelButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_copy_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_copy_button.js deleted file mode 100644 index 7536befdfd..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_copy_button.js +++ /dev/null @@ -1,88 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the SelectTranslationsPanel copy button can be invoked with the Enter key. - */ -add_task( - async function test_select_translations_panel_invoke_copy_button_with_enter_key() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.copyButton, - "KEY_Enter" - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.copyButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel copy button can be invoked with the space bar. - */ -add_task( - async function test_select_translations_panel_invoke_copy_button_with_space_bar() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.copyButton, - " " - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.copyButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_done_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_done_button.js deleted file mode 100644 index 945742b045..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_done_button.js +++ /dev/null @@ -1,180 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the SelectTranslationsPanel done button can be invoked with the Enter key - * from the primary-UI panel view. - */ -add_task( - async function test_select_translations_panel_invoke_primary_done_button_with_enter_key() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.doneButtonPrimary, - "KEY_Enter" - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel done button can be invoked with the space bar - * from the primary-UI panel view. - */ -add_task( - async function test_select_translations_panel_invoke_primary_done_button_with_space_bar() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.doneButtonPrimary, - " " - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel done button can be invoked with the Enter key - * from the unsupported-language panel view. - */ -add_task( - async function test_select_translations_panel_invoke_secondary_done_button_with_enter_key() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include French. - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.doneButtonSecondary, - "KEY_Enter" - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel done button can be invoked with the space bar - * from the unsupported-language panel view. - */ -add_task( - async function test_select_translations_panel_invoke_secondary_done_button_with_space_bar() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.doneButtonSecondary, - " " - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_settings_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_settings_button.js deleted file mode 100644 index 8377ed2c7c..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_settings_button.js +++ /dev/null @@ -1,87 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the SelectTranslationsPanel settings button can be invoked with the Enter key. - */ -add_task( - async function test_select_translations_panel_open_settings_menu_with_enter_key() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.settingsButton, - "KEY_Enter" - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.openSettingsMenu, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel settings button can be invoked with the space bar. - */ -add_task( - async function test_select_translations_panel_open_settings_menu_with_space_bar() { - const { cleanup, runInPage } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectEnglishSection: true, - openAtEnglishSection: true, - expectedFromLanguage: "en", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.settingsButton, - " " - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.openSettingsMenu, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_button.js deleted file mode 100644 index 0a095297e6..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_button.js +++ /dev/null @@ -1,121 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the SelectTranslationsPanel translate button can be invoked with the Enter key. - */ -add_task( - async function test_select_translations_panel_invoke_translate_button_with_enter_key() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include French. - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( - "uk" - ); - - const translatablePhasePromise = - SelectTranslationsTestUtils.waitForPanelState("translatable"); - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.translateButton, - "KEY_Enter" - ); - await translatablePhasePromise; - - await SelectTranslationsTestUtils.handleDownloads({ - downloadHandler: resolveDownloads, - }); - await SelectTranslationsTestUtils.assertPanelViewTranslated(); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translateButton, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - detected_language: "fr", - from_language: "uk", - to_language: "en", - }, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel translate button can be invoked with the space bar. - */ -add_task( - async function test_select_translations_panel_invoke_translate_button_with_space_bar() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - - await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( - "fr" - ); - - const translatablePhasePromise = - SelectTranslationsTestUtils.waitForPanelState("translatable"); - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.translateButton, - " " - ); - await translatablePhasePromise; - - await SelectTranslationsTestUtils.handleDownloads({ - downloadHandler: resolveDownloads, - }); - await SelectTranslationsTestUtils.assertPanelViewTranslated(); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translateButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_full_page_button.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_full_page_button.js deleted file mode 100644 index 712ae1db47..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_translate_full_page_button.js +++ /dev/null @@ -1,118 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the SelectTranslationsPanel translate-full-page button can be invoked with the Enter key. - */ -add_task( - async function test_select_translations_panel_invoke_translate_full_page_button_with_enter_key() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - const fullPageTranslationCompletePromise = - FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: true, icon: true }, - "The icon presents the locale." - ); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.translateFullPageButton, - "KEY_Enter" - ); - - await fullPageTranslationCompletePromise; - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "en", - runInPage, - } - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translateFullPageButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel translate-full-page button can be invoked with the space bar. - */ -add_task( - async function test_select_translations_panel_invoke_translate_full_page_button_with_space_bar() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSentence: true, - openAtFrenchSentence: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - - const fullPageTranslationCompletePromise = - FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: true, icon: true }, - "The icon presents the locale." - ); - - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.translateFullPageButton, - " " - ); - - await fullPageTranslationCompletePromise; - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "fr", - toLanguage: "en", - runInPage, - } - ); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translateFullPageButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_init_failure.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_init_failure.js deleted file mode 100644 index 02727fe220..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_init_failure.js +++ /dev/null @@ -1,106 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the SelectTranslationsPanel try-again button can be invoked with the Enter key. - * from the initialization-failure panel view. - */ -add_task( - async function test_select_translations_panel_invoke_init_failure_try_again_button_with_enter_key() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, - }); - - const translatablePhasePromise = - SelectTranslationsTestUtils.waitForPanelState("translatable"); - await SelectTranslationsTestUtils.waitForPanelPopupEvent("popupshown", () => - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.tryAgainButton, - "KEY_Enter" - ) - ); - await translatablePhasePromise; - - await SelectTranslationsTestUtils.handleDownloads({ - downloadHandler: resolveDownloads, - }); - await SelectTranslationsTestUtils.assertPanelViewTranslated(); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.tryAgainButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel try-again button can be invoked with the space bar. - * from the initialization-failure panel view. - */ -add_task( - async function test_select_translations_panel_invoke_init_failure_try_again_button_with_space_bar() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - TranslationsPanelShared.simulateLangListError(); - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewInitFailure, - }); - - const translatablePhasePromise = - SelectTranslationsTestUtils.waitForPanelState("translatable"); - await SelectTranslationsTestUtils.waitForPanelPopupEvent("popupshown", () => - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.tryAgainButton, - "KEY_Enter" - ) - ); - await translatablePhasePromise; - - await SelectTranslationsTestUtils.handleDownloads({ - downloadHandler: resolveDownloads, - }); - await SelectTranslationsTestUtils.assertPanelViewTranslated(); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.tryAgainButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_translation_failure.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_translation_failure.js deleted file mode 100644 index 4509cbdb7e..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_keypresses_try_again_button_translation_failure.js +++ /dev/null @@ -1,110 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that the SelectTranslationsPanel try-again button can be invoked with the Enter key. - * from the translation-failure panel view. - */ -add_task( - async function test_select_translations_panel_invoke_translation_failure_try_again_button_with_enter_key() { - const { cleanup, runInPage, resolveDownloads, rejectDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: rejectDownloads, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - const translatablePhasePromise = - SelectTranslationsTestUtils.waitForPanelState("translatable"); - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.tryAgainButton, - "KEY_Enter" - ); - await translatablePhasePromise; - - await SelectTranslationsTestUtils.handleDownloads({ - downloadHandler: resolveDownloads, - }); - await SelectTranslationsTestUtils.assertPanelViewTranslated(); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.tryAgainButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); - -/** - * This test case ensures that the SelectTranslationsPanel try-again button can be invoked with the space bar. - * from the translation-failure panel view. - */ -add_task( - async function test_select_translations_panel_invoke_translation_failure_try_again_button_with_space_bar() { - const { cleanup, runInPage, resolveDownloads, rejectDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: rejectDownloads, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - - const translatablePhasePromise = - SelectTranslationsTestUtils.waitForPanelState("translatable"); - focusElementAndSynthesizeKey( - SelectTranslationsPanel.elements.tryAgainButton, - " " - ); - await translatablePhasePromise; - - await SelectTranslationsTestUtils.handleDownloads({ - downloadHandler: resolveDownloads, - }); - await SelectTranslationsTestUtils.assertPanelViewTranslated(); - - await closeAllOpenPanelsAndMenus(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.tryAgainButton, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_multi_page.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_multi_page.js deleted file mode 100644 index 7e253d7a72..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_multi_page.js +++ /dev/null @@ -1,138 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case ensures that all of the telemetry metadata is correct - * when translating multiple pages from different languages, ensuring that - * any cached information about the page's language etc. is properly updated. - */ -add_task( - async function test_select_translations_panel_telemetry_multiple_pages() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtSpanishHyperlink: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "hyperlink", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 23, - source_text_word_count: 4, - }, - } - ); - - await navigate("Navigate to a French page.", { url: FRENCH_PAGE_URL }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectH1: true, - openAtH1: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 2, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "fr", - from_language: "fr", - to_language: "en", - top_preferred_language: "en", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - document_language: "fr", - from_language: "fr", - to_language: "en", - top_preferred_language: "en", - request_target: "select", - auto_translate: false, - source_text_code_units: 49, - source_text_word_count: 9, - }, - } - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 2, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 2, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_primary_ui.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_primary_ui.js deleted file mode 100644 index 2d972d385f..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_primary_ui.js +++ /dev/null @@ -1,306 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the counts and extra data sent from telemetry events when interacting - * with the SelectTranslationsPanel's primary happy-path UI states. - */ -add_task( - async function test_select_translations_panel_telemetry_primary_ui_components() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - { fromLang: "es", toLang: "en" }, - { fromLang: "en", toLang: "es" }, - { fromLang: "fa", toLang: "en" }, - { fromLang: "en", toLang: "fa" }, - { fromLang: "fi", toLang: "en" }, - { fromLang: "en", toLang: "fi" }, - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - { fromLang: "sl", toLang: "en" }, - { fromLang: "en", toLang: "sl" }, - { fromLang: "uk", toLang: "en" }, - { fromLang: "en", toLang: "uk" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 165, - source_text_word_count: 28, - }, - } - ); - - await SelectTranslationsTestUtils.clickCopyButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.copyButton, - { - expectedEventCount: 1, - } - ); - - await SelectTranslationsTestUtils.changeSelectedFromLanguage(["fi"], { - openDropdownMenu: false, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - language: "fi", - previous_language: "es", - document_language: "es", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 0, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fi", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 165, - source_text_word_count: 28, - }, - } - ); - - await SelectTranslationsTestUtils.clickCopyButton(); - await SelectTranslationsTestUtils.clickCopyButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.copyButton, - { - expectedEventCount: 3, - } - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 2, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 3], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 3, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en", - request_target: "select", - auto_translate: false, - source_text_code_units: 165, - source_text_word_count: 28, - }, - } - ); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fa"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeFromLanguage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - language: "fi", - previous_language: "es", - document_language: "es", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - language: "fa", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 4], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 4, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "fa", - top_preferred_language: "en", - request_target: "select", - auto_translate: false, - source_text_code_units: 165, - source_text_word_count: 28, - }, - } - ); - - await SelectTranslationsTestUtils.clickCopyButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.copyButton, - { - expectedEventCount: 4, - } - ); - - await SelectTranslationsTestUtils.clickTranslateFullPageButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translateFullPageButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 2, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 4], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 5, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "fa", - top_preferred_language: "fa", - request_target: "full_page", - auto_translate: false, - }, - } - ); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fa", - runInPage, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 3, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_settings_menu.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_settings_menu.js deleted file mode 100644 index 8229d6017b..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_settings_menu.js +++ /dev/null @@ -1,98 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the counts and extra data sent from telemetry events when interacting - * with the SelectTranslationsPanel's settings menu. - */ -add_task( - async function test_select_translations_panel_telemetry_settings_menu() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtFrenchHyperlink: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fr", - to_language: "en", - top_preferred_language: "en-US", - text_source: "hyperlink", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fr", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 27, - source_text_word_count: 5, - }, - } - ); - - await SelectTranslationsTestUtils.openPanelSettingsMenu(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.openSettingsMenu, - { - expectedEventCount: 1, - } - ); - - SelectTranslationsTestUtils.clickTranslationsSettingsPageMenuItem(); - await waitForCondition( - () => gBrowser.currentURI.spec === "about:preferences#general", - "Waiting for about:preferences to be opened." - ); - info("Remove the about:preferences tab"); - gBrowser.removeCurrentTab(); - - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translationSettings, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_cancel.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_cancel.js deleted file mode 100644 index e12720c1e9..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_cancel.js +++ /dev/null @@ -1,146 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the counts and extra data sent from telemetry events when interacting - * with the SelectTranslationsPanel's translation-failure UI and the user cancels after retrying. - */ -add_task( - async function test_select_translations_panel_telemetry_translation_failure_then_cancel() { - const { cleanup, runInPage, rejectDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: rejectDownloads, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fr", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fr", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: - AppConstants.platform === "win" - ? 1616 // With carriage returns - : 1607, // No carriage returns - source_text_word_count: 257, - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translationFailureMessage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - from_language: "fr", - to_language: "en", - }, - } - ); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: rejectDownloads, - viewAssertion: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.tryAgainButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fr", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: - AppConstants.platform === "win" - ? 1616 // With carriage returns - : 1607, // No carriage returns - source_text_word_count: 257, - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translationFailureMessage, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - from_language: "fr", - to_language: "en", - }, - } - ); - - await SelectTranslationsTestUtils.clickCancelButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.cancelButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 0, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_succeed.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_succeed.js deleted file mode 100644 index 35c9250b63..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_ui_then_succeed.js +++ /dev/null @@ -1,136 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the counts and extra data sent from telemetry events when interacting - * with the SelectTranslationsPanel's translation-failure UI and retrying is successful. - */ -add_task( - async function test_select_translations_panel_telemetry_translation_failure_then_succeed() { - const { cleanup, runInPage, rejectDownloads, resolveDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: rejectDownloads, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fr", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fr", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: - AppConstants.platform === "win" - ? 1616 // With carriage returns - : 1607, // No carriage returns - source_text_word_count: 257, - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translationFailureMessage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - from_language: "fr", - to_language: "en", - }, - } - ); - - await SelectTranslationsTestUtils.clickTryAgainButton({ - downloadHandler: resolveDownloads, - viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.tryAgainButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fr", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: - AppConstants.platform === "win" - ? 1616 // With carriage returns - : 1607, // No carriage returns - source_text_word_count: 257, - }, - } - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_with_full_page_translations_active.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_with_full_page_translations_active.js deleted file mode 100644 index f36d5e6b91..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_failure_with_full_page_translations_active.js +++ /dev/null @@ -1,212 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_task( - async function test_select_translations_panel_translation_failure_with_full_page_translations_active() { - const { cleanup, runInPage, resolveDownloads, rejectDownloads } = - await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtSpanishHyperlink: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "hyperlink", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 23, - source_text_word_count: 4, - }, - } - ); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "fr", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 23, - source_text_word_count: 4, - }, - } - ); - - await SelectTranslationsTestUtils.clickTranslateFullPageButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translateFullPageButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 3, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "fr", - top_preferred_language: "fr", - request_target: "full_page", - auto_translate: false, - }, - } - ); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage, - } - ); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: rejectDownloads, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewTranslationFailure, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 2, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "fr", - from_language: "fr", - to_language: "en", - top_preferred_language: "fr", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 3], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 4, - assertForMostRecentEvent: { - document_language: "fr", - from_language: "fr", - to_language: "en", - top_preferred_language: "fr", - request_target: "select", - auto_translate: false, - source_text_code_units: - AppConstants.platform === "win" - ? 1616 // With carriage returns - : 1607, // No carriage returns - source_text_word_count: 257, - }, - } - ); - - await SelectTranslationsTestUtils.clickCancelButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.cancelButton, - { - expectedEventCount: 1, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "en", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "revisitView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 2, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_success_with_full_page_translations_active.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_success_with_full_page_translations_active.js deleted file mode 100644 index 7069a855e8..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_translation_success_with_full_page_translations_active.js +++ /dev/null @@ -1,249 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -add_task( - async function test_select_translations_panel_translation_success_with_full_page_translations_active() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: LANGUAGE_PAIRS, - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtSpanishHyperlink: true, - expectedFromLanguage: "es", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "hyperlink", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 23, - source_text_word_count: 4, - }, - } - ); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["fr"], { - openDropdownMenu: true, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "fr", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: 23, - source_text_word_count: 4, - }, - } - ); - - await SelectTranslationsTestUtils.clickTranslateFullPageButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translateFullPageButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 2], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 3, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "fr", - top_preferred_language: "fr", - request_target: "full_page", - auto_translate: false, - }, - } - ); - - await FullPageTranslationsTestUtils.assertOnlyIntersectingNodesAreTranslated( - { - fromLanguage: "es", - toLanguage: "fr", - runInPage, - } - ); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectFrenchSection: true, - openAtFrenchSection: true, - expectedFromLanguage: "fr", - expectedToLanguage: "en", - downloadHandler: resolveDownloads, - onOpenPanel: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 2, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "fr", - from_language: "fr", - to_language: "en", - top_preferred_language: "fr", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 3], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 4, - assertForMostRecentEvent: { - document_language: "fr", - from_language: "fr", - to_language: "en", - top_preferred_language: "fr", - request_target: "select", - auto_translate: false, - source_text_code_units: - AppConstants.platform === "win" - ? 1616 // With carriage returns - : 1607, // No carriage returns - source_text_word_count: 257, - }, - } - ); - - await SelectTranslationsTestUtils.changeSelectedToLanguage(["uk"], { - openDropdownMenu: false, - pivotTranslation: true, - downloadHandler: resolveDownloads, - onChangeLanguage: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.changeToLanguage, - { - expectedEventCount: 2, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 1], - ["select", 4], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 5, - assertForMostRecentEvent: { - document_language: "fr", - from_language: "fr", - to_language: "uk", - top_preferred_language: "fr", - request_target: "select", - auto_translate: false, - source_text_code_units: - AppConstants.platform === "win" - ? 1616 // With carriage returns - : 1607, // No carriage returns - source_text_word_count: 257, - }, - } - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - - await FullPageTranslationsTestUtils.openPanel({ - expectedToLanguage: "uk", - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewRevisit, - }); - await TestTranslationsTelemetry.assertEvent(Glean.translationsPanel.open, { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - auto_show: false, - view_name: "revisitView", - opened_from: "translationsButton", - document_language: "es", - }, - }); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 4, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_unsupported_language_ui.js b/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_unsupported_language_ui.js deleted file mode 100644 index b68f23eacc..0000000000 --- a/src/zen/tests/mochitests/translations/browser_translations_select_telemetry_unsupported_language_ui.js +++ /dev/null @@ -1,162 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -/** - * This test case verifies the counts and extra data sent from telemetry events when interacting - * with the SelectTranslationsPanel's unsupported-language UI states. - */ -add_task( - async function test_select_translations_panel_telemetry_unsupported_language_ui() { - const { cleanup, runInPage, resolveDownloads } = await loadTestPage({ - page: SELECT_TEST_PAGE_URL, - languagePairs: [ - // Do not include Spanish. - { fromLang: "fr", toLang: "en" }, - { fromLang: "en", toLang: "fr" }, - ], - prefs: [["browser.translations.select.enable", true]], - }); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - selectSpanishSection: true, - openAtSpanishSection: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 1, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.unsupportedLanguageMessage, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - detected_language: "es", - }, - } - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 1, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 1, - } - ); - - await SelectTranslationsTestUtils.openPanel(runInPage, { - openAtFrenchHyperlink: true, - onOpenPanel: - SelectTranslationsTestUtils.assertPanelViewUnsupportedLanguage, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.open, - { - expectedEventCount: 2, - expectNewFlowId: true, - assertForMostRecentEvent: { - document_language: "es", - from_language: "es", - to_language: "en", - top_preferred_language: "en-US", - text_source: "selection", - }, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.unsupportedLanguageMessage, - { - expectedEventCount: 2, - assertForMostRecentEvent: { - document_language: "es", - detected_language: "es", - }, - } - ); - - await SelectTranslationsTestUtils.changeSelectedTryAnotherSourceLanguage( - "fr" - ); - await SelectTranslationsTestUtils.clickTranslateButton({ - downloadHandler: resolveDownloads, - viewAssertion: SelectTranslationsTestUtils.assertPanelViewTranslated, - }); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.translateButton, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - detected_language: "es", - from_language: "fr", - to_language: "en", - }, - } - ); - await TestTranslationsTelemetry.assertLabeledCounter( - Glean.translations.requestCount, - [ - ["full_page", 0], - ["select", 1], - ] - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translations.translationRequest, - { - expectedEventCount: 1, - assertForMostRecentEvent: { - document_language: "es", - from_language: "fr", - to_language: "en", - top_preferred_language: "en-US", - request_target: "select", - auto_translate: false, - source_text_code_units: - AppConstants.platform === "win" - ? 2064 // With carriage returns - : 2041, // No carriage returns - source_text_word_count: 358, - }, - } - ); - - await SelectTranslationsTestUtils.clickDoneButton(); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.doneButton, - { - expectedEventCount: 2, - } - ); - await TestTranslationsTelemetry.assertEvent( - Glean.translationsSelectTranslationsPanel.close, - { - expectedEventCount: 2, - } - ); - - await TestTranslationsTelemetry.assertTranslationsEnginePerformance({ - expectedEventCount: 1, - }); - - await cleanup(); - } -); diff --git a/src/zen/tests/mochitests/translations/head.js b/src/zen/tests/mochitests/translations/head.js deleted file mode 100644 index 80456375c1..0000000000 --- a/src/zen/tests/mochitests/translations/head.js +++ /dev/null @@ -1,4291 +0,0 @@ -/* 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 -); - -/** - * Converts milliseconds to seconds. - * - * @param {number} ms - The duration in milliseconds. - * @returns {number} The duration in seconds. - */ -function millisecondsToSeconds(ms) { - return ms / 1000; -} - -/** - * Converts bytes to mebibytes. - * - * @param {number} bytes - The size in bytes. - * @returns {number} The size in mebibytes. - */ -function bytesToMebibytes(bytes) { - return bytes / (1024 * 1024); -} - -/** - * Calculates the median of a list of numbers. - * - * @param {number[]} numbers - An array of numbers to find the median of. - * @returns {number} The median of the provided numbers. - */ -function median(numbers) { - numbers = numbers.sort((lhs, rhs) => lhs - rhs); - const midIndex = Math.floor(numbers.length / 2); - - if (numbers.length & 1) { - return numbers[midIndex]; - } - - return (numbers[midIndex - 1] + numbers[midIndex]) / 2; -} - -/** - * Opens a new tab in the foreground. - * - * @param {string} url - */ -async function addTab(url, message, win = window) { - logAction(url); - info(message); - const tab = await BrowserTestUtils.openNewForegroundTab( - win.gBrowser, - url, - true // Wait for load - ); - return { - tab, - removeTab() { - BrowserTestUtils.removeTab(tab); - }, - /** - * Runs a callback in the content page. The function's contents are serialized as - * a string, and run in the page. The `translations-test.mjs` module is made - * available to the page. - * - * @param {(TranslationsTest: import("./translations-test.mjs")) => any} callback - * @returns {Promise} - */ - runInPage(callback, data = {}) { - return ContentTask.spawn( - tab.linkedBrowser, - { contentData: data, callbackSource: callback.toString() }, // Data to inject. - function ({ contentData, callbackSource }) { - const TranslationsTest = ChromeUtils.importESModule( - "chrome://mochitests/content/browser/toolkit/components/translations/tests/browser/translations-test.mjs" - ); - - // Pass in the values that get injected by the task runner. - TranslationsTest.setup({ Assert, ContentTaskUtils, content }); - - // eslint-disable-next-line no-eval - let contentCallback = eval(`(${callbackSource})`); - return contentCallback(TranslationsTest, contentData); - } - ); - }, - }; -} - -/** - * Simulates clicking an element with the mouse. - * - * @param {element} element - The element to click. - * @param {string} [message] - A message to log to info. - */ -function click(element, message) { - logAction(message); - return new Promise(resolve => { - element.addEventListener( - "click", - function () { - resolve(); - }, - { once: true } - ); - - EventUtils.synthesizeMouseAtCenter(element, { - type: "mousedown", - isSynthesized: false, - }); - EventUtils.synthesizeMouseAtCenter(element, { - type: "mouseup", - isSynthesized: false, - }); - }); -} - -function focusElementAndSynthesizeKey(element, key) { - assertVisibility({ visible: { element } }); - element.focus(); - EventUtils.synthesizeKey(key); -} - -/** - * Focuses the given window object, moving it to the top of all open windows. - * - * @param {Window} win - */ -async function focusWindow(win) { - const windowFocusPromise = BrowserTestUtils.waitForEvent(win, "focus"); - win.focus(); - await windowFocusPromise; -} - -/** - * 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; -} - -/** - * Retrieves an element by its Id. - * - * @param {string} id - * @param {Document} [doc] - * @returns {Element} - * @throws Throws if the element is not visible in the DOM. - */ -function getById(id, doc = document) { - const element = maybeGetById(id, /* ensureIsVisible */ true, doc); - if (!element) { - throw new Error("The element is not visible in the DOM: #" + id); - } - return element; -} - -/** - * 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 (BrowserTestUtils.isVisible(element)) { - return element; - } - } - throw new Error("The element is not visible in the DOM: " + l10nId); -} - -/** - * Returns the intl display name of a given language tag. - * - * @param {string} langTag - A BCP-47 language tag. - */ -const getIntlDisplayName = (() => { - let languageDisplayNames = null; - - return langTag => { - if (!languageDisplayNames) { - languageDisplayNames = TranslationsParent.createLanguageDisplayNames({ - fallback: "none", - }); - } - return languageDisplayNames.of(langTag); - }; -})(); - -/** - * Attempts to retrieve an element by its Id. - * - * @param {string} id - The Id of the element to retrieve. - * @param {boolean} [ensureIsVisible=true] - If set to true, the function will return null when the element is not visible. - * @param {Document} [doc=document] - The document from which to retrieve the element. - * @returns {Element | null} - The retrieved element. - * @throws Throws if no element was found by the given Id. - */ -function maybeGetById(id, ensureIsVisible = true, doc = document) { - const element = doc.getElementById(id); - if (!element) { - throw new Error("Could not find the element by id: #" + id); - } - - if (!ensureIsVisible) { - return element; - } - - if (BrowserTestUtils.isVisible(element)) { - return element; - } - - return null; -} - -/** - * 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 (BrowserTestUtils.isVisible(element)) { - return element; - } - } - return null; -} - -/** - * Provide a uniform way to log actions. This abuses the Error stack to get the callers - * of the action. This should help in test debugging. - */ -function logAction(...params) { - const error = new Error(); - const stackLines = error.stack.split("\n"); - const actionName = stackLines[1]?.split("@")[0] ?? ""; - const taskFileLocation = stackLines[2]?.split("@")[1] ?? ""; - if (taskFileLocation.includes("head.js")) { - // Only log actions that were done at the test level. - return; - } - - info(`Action: ${actionName}(${params.join(", ")})`); - info( - `Source: ${taskFileLocation.replace( - "chrome://mochitests/content/browser/", - "" - )}` - ); -} - -/** - * Returns true if Full-Page Translations is currently active, otherwise false. - * - * @returns {boolean} - */ -function isFullPageTranslationsActive() { - try { - const { requestedLanguagePair } = TranslationsParent.getTranslationsActor( - gBrowser.selectedBrowser - ).languageState; - return !!requestedLanguagePair; - } catch { - // Translations actor unavailable, continue on. - } - return false; -} - -/** - * Navigate to a URL and indicate a message as to why. - */ -async function navigate( - message, - { url, onOpenPanel = null, downloadHandler = null, pivotTranslation = false } -) { - logAction(); - // When the translations panel is open from the app menu, - // it doesn't close on navigate the way that it does when it's - // open from the translations button, so ensure that we always - // close it when we navigate to a new page. - await closeAllOpenPanelsAndMenus(); - - info(message + " - " + url); - - // 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. - await loadBlankPage(); - const loadTargetPage = async () => { - await loadNewPage(gBrowser.selectedBrowser, url); - - if (downloadHandler) { - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The icon presents the loading indicator." - ); - await downloadHandler(pivotTranslation ? 2 : 1); - } - }; - - info(`Loading url: "${url}"`); - if (onOpenPanel) { - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - loadTargetPage, - onOpenPanel - ); - } else { - await loadTargetPage(); - } -} - -/** - * Switches to a given tab. - * - * @param {object} tab - The tab to switch to - * @param {string} name - */ -async function switchTab(tab, name) { - logAction("tab", name); - gBrowser.selectedTab = tab; - await new Promise(resolve => setTimeout(resolve, 0)); -} - -/** - * Click the reader-mode button if the reader-mode button is available. - * Fails if the reader-mode button is hidden. - */ -async function toggleReaderMode() { - logAction(); - const readerButton = document.getElementById("reader-mode-button"); - await waitForCondition(() => readerButton.hidden === false); - - readerButton.getAttribute("readeractive") - ? info("Exiting reader mode") - : info("Entering reader mode"); - - const readyPromise = readerButton.getAttribute("readeractive") - ? waitForCondition(() => !readerButton.getAttribute("readeractive")) - : BrowserTestUtils.waitForContentEvent( - gBrowser.selectedBrowser, - "AboutReaderContentReady" - ); - - click(readerButton, "Clicking the reader-mode button"); - await readyPromise; -} - -/** - * Scrolls to the top of the content page. - * - * @param {Function} runInPage - Runs a closure within the content context of the content page. - * - * @returns {Promise} Resolves once the scroll position has been updated and a paint has occurred. - */ -async function scrollToTopOfPage(runInPage) { - logAction(); - await runInPage(async ({ waitForCondition }) => { - content.scrollTo({ top: 0, behavior: "smooth" }); - - await waitForCondition( - () => content.scrollY <= 10, - "Waiting for scroll animation to complete." - ); - - // Wait for the new position to be painted. - await new Promise(resolve => { - content.requestAnimationFrame(() => - content.requestAnimationFrame(resolve) - ); - }); - }); -} - -/** - * Scrolls the content page to the very bottom. - * - * @param {Function} runInPage - Runs a closure within the content context of the content page. - * - * @returns {Promise} Resolves once the scroll position has been updated and a paint has occurred. - */ -async function scrollToBottomOfPage(runInPage) { - logAction(); - await runInPage(async ({ waitForCondition }) => { - const scrollHeight = content.document.documentElement.scrollHeight; - content.scrollTo({ top: scrollHeight, behavior: "smooth" }); - - await waitForCondition(() => { - return content.scrollY >= scrollHeight - content.innerHeight - 10; - }, "Waiting for scroll animation to complete."); - - // Wait for the new position to be painted. - await new Promise(resolve => { - content.requestAnimationFrame(() => - content.requestAnimationFrame(resolve) - ); - }); - }); -} - -/** - * A class for benchmarking translation performance and reporting - * metrics to our perftest infrastructure. - */ -class TranslationsBencher { - /** - * The metric base name for the engine initialization time. - * - * @type {string} - */ - static METRIC_ENGINE_INIT_TIME = "engine-init-time"; - - /** - * The metric base name for words translated per second. - * - * @type {string} - */ - static METRIC_WORDS_PER_SECOND = "words-per-second"; - - /** - * The metric base name for tokens translated per second. - * - * @type {string} - */ - static METRIC_TOKENS_PER_SECOND = "tokens-per-second"; - - /** - * The metric base name for peak memory usage in the parent process. - * The TranslationsBencher records this at a sampled interval reporting - * the maximum recorded memory recorded during the benchmark. - * - * @type {string} - */ - static METRIC_PEAK_PARENT_PROCESS_MEMORY_USAGE = - "peak-parent-process-memory-usage"; - - /** - * The metric base name for stabilized memory usage in the parent process. - * The TranslationsBencher records this just after finishing the final translation, - * but before destroying the engine and running GC. - * - * @type {string} - */ - static METRIC_STABILIZED_PARENT_PROCESS_MEMORY_USAGE = - "stabilized-parent-process-memory-usage"; - - /** - * The metric base name for the memory usage in the parent process after - * translation has completed, and after running cycle collection and - * garbage collection. - * - * @type {string} - */ - static METRIC_POST_GC_PARENT_PROCESS_MEMORY_USAGE = - "post-gc-parent-process-memory-usage"; - - /** - * The metric base name for peak memory usage in the inference process. - * The TranslationsBencher records this at a sampled interval reporting - * the maximum recorded memory recorded during the benchmark. - * - * @type {string} - */ - static METRIC_PEAK_INFERENCE_PROCESS_MEMORY_USAGE = - "peak-inference-process-memory-usage"; - - /** - * The metric base name for stabilized memory usage in the inference process, - * The TranslationsBencher records this just after finishing the final translation, - * but before running GC. - * - * @type {string} - */ - static METRIC_STABILIZED_INFERENCE_PROCESS_MEMORY_USAGE = - "stabilized-inference-process-memory-usage"; - - /** - * The metric base name for the memory usage in the inference process after - * translation has completed, and after running cycle collection and garbage - * garbage collection. - * - * @type {string} - */ - static METRIC_POST_GC_INFERENCE_PROCESS_MEMORY_USAGE = - "post-gc-inference-process-memory-usage"; - - /** - * The metric base name for total translation time. - * - * @type {string} - */ - static METRIC_TOTAL_TRANSLATION_TIME = "total-translation-time"; - - /** - * Data required to ensure that peftest metrics are validated and calculated correctly for the - * given test file. This data can be generated for a test file by running the script located at: - * - * toolkit/components/translations/tests/scripts/translations-perf-data.py - * - * @type {Record} - */ - static #PAGE_DATA = { - [SPANISH_BENCHMARK_PAGE_URL]: { - pageLanguage: "es", - tokenCount: 10966, - wordCount: 6944, - }, - }; - - /** - * A class that gathers and reports metrics to perftest. - */ - static Journal = class { - /** - * A map of collected metrics, where the key is the metric name - * and the value is an array of all recorded values. - * - * @type {Record} - */ - #metrics = {}; - - /** - * Pushes a metric value into the journal. - * - * @param {string} metricName - The metric name. - * @param {number} value - The metric value to record. - */ - pushMetric(metricName, value) { - if (!this.#metrics[metricName]) { - this.#metrics[metricName] = []; - } - - this.#metrics[metricName].push(Number(value.toFixed(3))); - } - - /** - * Pushes multiple metric values into the journal. - * - * @param {Array<[string, number]>} metrics - An array of [metricName, value] pairs. - */ - pushMetrics(metrics) { - for (const [metricName, value] of metrics) { - this.pushMetric(metricName, value); - } - } - - /** - * Logs the median value along with the individual values from all - * test runs for each collected metric to the console. - * The log is then picked up by the perftest infrastructure. - * The logged data must match the schema defined in the test file. - */ - reportMetrics() { - const reportedMetrics = []; - for (const [name, values] of Object.entries(this.#metrics)) { - reportedMetrics.push({ - name, - values, - value: median(values), - }); - } - info(`perfMetrics | ${JSON.stringify(reportedMetrics)}`); - } - }; - - /** - * A class to track peak memory usage during translation via sampled intervals. - */ - static PeakMemorySampler = class { - /** - * The peak recorded memory in mebibytes (MiB) for the parent process. - * - * @type {number} - */ - #peakParentMemoryMiB = 0; - - /** - * The peak recorded memory in mebibytes (MiB) for the inference process. - * - * @type {number} - */ - #peakInferenceMemoryMiB = 0; - - /** - * The interval id for the memory sample timer. - * - * @type {number|null} - */ - #intervalId = null; - - /** - * The interval at which memory usage is sampled in milliseconds. - * - * @type {number} - */ - #interval; - - /** - * Constructs a PeakMemorySampler. - * - * @param {number} interval - The interval in milliseconds between memory samples. - */ - constructor(interval) { - this.#interval = interval; - } - - /** - * Collects the current memory usage for both the parent and inference processes - * and updates the peak memory measurements if the current usage exceeds the - * previously recorded peaks. - * - * @returns {Promise} - */ - async #collectMemorySample() { - const { parentMemoryMiB, inferenceMemoryMiB } = - await TranslationsBencher.#getTotalMemoryUsageByProcess(); - - if (parentMemoryMiB > this.#peakParentMemoryMiB) { - this.#peakParentMemoryMiB = parentMemoryMiB; - } - if (inferenceMemoryMiB > this.#peakInferenceMemoryMiB) { - this.#peakInferenceMemoryMiB = inferenceMemoryMiB; - } - } - - /** - * Starts the interval timer to begin sampling new peak memory usage values. - */ - start() { - if (this.#intervalId !== null) { - throw new Error( - "Attempt to start a PeakMemorySampler that was already running." - ); - } - - this.#peakParentMemoryMiB = 0; - this.#peakInferenceMemoryMiB = 0; - this.#intervalId = setInterval(() => { - this.#collectMemorySample().catch(console.error); - }, this.#interval); - } - - /** - * Stops the interval timer from continuing to sample peak memory usage. - */ - stop() { - if (this.#intervalId === null) { - throw new Error( - "Attempt to stop a PeakMemorySampler that was not running." - ); - } - - clearInterval(this.#intervalId); - this.#intervalId = null; - this.#collectMemorySample(); - } - - /** - * Returns the peak recorded memory usage in mebibytes (MiB). - * - * @returns {{ peakParentMemoryMiB: number, peakInferenceMemoryMiB: number }} - */ - getPeakRecordedMemoryUsage() { - if (this.#intervalId) { - throw new Error( - "Attempt to retrieve peak recorded memory usage while the memory sampler is running." - ); - } - - return { - peakParentMemoryMiB: this.#peakParentMemoryMiB, - peakInferenceMemoryMiB: this.#peakInferenceMemoryMiB, - }; - } - }; - - /** - * Benchmarks the translation process (both memory usage and speed) - * and reports metrics to perftest. It runs one full translation for - * each memory sample, and then one full translation for each speed sample. - * - * @param {object} options - The benchmark options. - * @param {string} options.page - The URL of the page to test. - * @param {string} options.sourceLanguage - The BCP-47 language tag for the source language. - * @param {string} options.targetLanguage - The BCP-47 language tag for the target language. - * @param {number} options.speedBenchCount - The number of speed-sampling runs to perform. - * @param {number} options.memoryBenchCount - The number of memory-sampling runs to perform. - * @param {number} [options.memorySampleInterval] - The interval in milliseconds between memory usage samples. - * - * @returns {Promise} Resolves when benchmarking is complete. - */ - static async benchmarkTranslation({ - page, - sourceLanguage, - targetLanguage, - speedBenchCount, - memoryBenchCount, - memorySampleInterval = 10, - }) { - const { wordCount, tokenCount, pageLanguage } = - TranslationsBencher.#PAGE_DATA[page] ?? {}; - - if (!wordCount || !tokenCount || !pageLanguage) { - const testPageName = page.match(/[^\\/]+$/)[0]; - const testPagePath = page.substring( - "https://example.com/browser/".length - ); - const sourceLangName = getIntlDisplayName(sourceLanguage); - throw new Error(` - - 🚨 Perf test data is not properly defined for ${testPageName} 🚨 - - To enable ${testPageName} for Translations perf tests, please follow these steps: - - 1) Ensure ${testPageName} has a proper HTML lang attribute in the markup: - - - - 2) Download the ${sourceLanguage}-${PIVOT_LANGUAGE}.vocab.spm model from a ${sourceLangName} row on the following site: - - https://gregtatum.github.io/taskcluster-tools/src/models/ - - 3) Run the following command to extract the perf metadata from ${testPageName}: - - ❯ python3 toolkit/components/translations/tests/scripts/translations-perf-data.py \\ - --page_path="${testPagePath}" \\ - --model_path="..." - - 4) Include the resulting metadata for ${testPageName} in the TranslationsBencher.#PAGE_DATA object. - `); - } - - if (sourceLanguage !== pageLanguage) { - throw new Error( - `Perf test source language '${sourceLanguage}' did not match the expected page language '${pageLanguage}'.` - ); - } - - const journal = new TranslationsBencher.Journal(); - - await TranslationsBencher.#benchmarkTranslationMemory({ - page, - journal, - sourceLanguage, - targetLanguage, - memoryBenchCount, - memorySampleInterval, - }); - - await TranslationsBencher.#benchmarkTranslationSpeed({ - page, - journal, - sourceLanguage, - targetLanguage, - wordCount, - tokenCount, - speedBenchCount, - }); - - journal.reportMetrics(); - } - - /** - * Benchmarks memory usage by measuring peak and stabilized memory usage - * across multiple runs of the translation process. - * - * @param {object} options - The benchmark options. - * @param {string} options.page - The URL of the page to test. - * @param {TranslationsBencher.Journal} options.journal - The shared metrics journal. - * @param {string} options.sourceLanguage - The BCP-47 language tag for the source language. - * @param {string} options.targetLanguage - The BCP-47 language tag for the target language. - * @param {number} options.memoryBenchCount - The number of runs to perform for memory sampling. - * @param {number} options.memorySampleInterval - The interval in milliseconds between memory samples. - * - * @returns {Promise} Resolves when memory benchmarking is complete. - */ - static async #benchmarkTranslationMemory({ - page, - journal, - sourceLanguage, - targetLanguage, - memoryBenchCount, - memorySampleInterval, - }) { - for (let runNumber = 0; runNumber < memoryBenchCount; ++runNumber) { - const { cleanup, runInPage } = await loadTestPage({ - page, - endToEndTest: true, - languagePairs: [ - { fromLang: sourceLanguage, toLang: "en" }, - { fromLang: "en", toLang: targetLanguage }, - ], - prefs: [["browser.translations.logLevel", "Error"]], - contentEagerMode: true, - }); - - // Create a new PeakMemorySampler using the provided interval. - const peakMemorySampler = new TranslationsBencher.PeakMemorySampler( - memorySampleInterval - ); - - await TranslationsBencher.#injectFinalParagraphTranslatedObserver( - runInPage - ); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: sourceLanguage, - }); - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: targetLanguage, - }); - - const translationCompleteTimestampPromise = - TranslationsBencher.#getTranslationCompleteTimestampPromise(runInPage); - - peakMemorySampler.start(); - - await FullPageTranslationsTestUtils.clickTranslateButton(); - await translationCompleteTimestampPromise; - - peakMemorySampler.stop(); - - const { peakParentMemoryMiB, peakInferenceMemoryMiB } = - peakMemorySampler.getPeakRecordedMemoryUsage(); - - const { parentMemoryMiB, inferenceMemoryMiB } = - await TranslationsBencher.#getTotalMemoryUsageByProcess(); - - // Force cycle collection and garbage collection. - Services.obs.notifyObservers(null, "child-cc-request"); - Services.obs.notifyObservers(null, "child-gc-request"); - window.windowUtils.cycleCollect(); - Cu.forceGC(); - - const { inferenceMemoryMiB: postGCInferenceMiB } = - await TranslationsBencher.#getTotalMemoryUsageByProcess(); - - // Destroy the TranslationsEngine, then force cycle collection and garbage collection again. - await EngineProcess.destroyTranslationsEngine(); - Services.obs.notifyObservers(null, "child-cc-request"); - Services.obs.notifyObservers(null, "child-gc-request"); - window.windowUtils.cycleCollect(); - Cu.forceGC(); - - const { parentMemoryMiB: postGCParentMiB } = - await TranslationsBencher.#getTotalMemoryUsageByProcess(); - - journal.pushMetrics([ - [ - TranslationsBencher.METRIC_PEAK_PARENT_PROCESS_MEMORY_USAGE, - peakParentMemoryMiB, - ], - [ - TranslationsBencher.METRIC_STABILIZED_PARENT_PROCESS_MEMORY_USAGE, - parentMemoryMiB, - ], - [ - TranslationsBencher.METRIC_POST_GC_PARENT_PROCESS_MEMORY_USAGE, - postGCParentMiB, - ], - [ - TranslationsBencher.METRIC_PEAK_INFERENCE_PROCESS_MEMORY_USAGE, - peakInferenceMemoryMiB, - ], - [ - TranslationsBencher.METRIC_STABILIZED_INFERENCE_PROCESS_MEMORY_USAGE, - inferenceMemoryMiB, - ], - [ - TranslationsBencher.METRIC_POST_GC_INFERENCE_PROCESS_MEMORY_USAGE, - postGCInferenceMiB, - ], - ]); - - await cleanup(); - } - } - - /** - * Benchmarks speed by measuring engine init time, words per second, tokens per second, - * and total translation time across multiple runs. - * - * @param {object} options - The benchmark options. - * @param {string} options.page - The URL of the page to test. - * @param {TranslationsBencher.Journal} options.journal - The shared metrics journal. - * @param {string} options.sourceLanguage - The BCP-47 language tag for the source language. - * @param {string} options.targetLanguage - The BCP-47 language tag for the target language. - * @param {number} options.wordCount - The total word count of the page. - * @param {number} options.tokenCount - The total token count of the page. - * @param {number} options.speedBenchCount - The number of runs to perform for speed sampling. - * - * @returns {Promise} Resolves when speed benchmarking is complete. - */ - static async #benchmarkTranslationSpeed({ - page, - journal, - sourceLanguage, - targetLanguage, - wordCount, - tokenCount, - speedBenchCount, - }) { - for (let runNumber = 0; runNumber < speedBenchCount; ++runNumber) { - const { tab, cleanup, runInPage } = await loadTestPage({ - page, - endToEndTest: true, - languagePairs: [ - { fromLang: sourceLanguage, toLang: "en" }, - { fromLang: "en", toLang: targetLanguage }, - ], - prefs: [["browser.translations.logLevel", "Error"]], - contentEagerMode: true, - }); - - await TranslationsBencher.#injectFinalParagraphTranslatedObserver( - runInPage - ); - - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: false, icon: true }, - "The button is available." - ); - - await FullPageTranslationsTestUtils.openPanel({ - onOpenPanel: FullPageTranslationsTestUtils.assertPanelViewIntro, - }); - - await FullPageTranslationsTestUtils.changeSelectedFromLanguage({ - langTag: sourceLanguage, - }); - await FullPageTranslationsTestUtils.changeSelectedToLanguage({ - langTag: targetLanguage, - }); - - const engineReadyTimestampPromise = - TranslationsBencher.#getEngineReadyTimestampPromise(tab.linkedBrowser); - const translationCompleteTimestampPromise = - TranslationsBencher.#getTranslationCompleteTimestampPromise(runInPage); - - const translateButtonClickedTime = performance.now(); - await FullPageTranslationsTestUtils.clickTranslateButton(); - - const [engineReadyTime, translationCompleteTime] = await Promise.all([ - engineReadyTimestampPromise, - translationCompleteTimestampPromise, - ]); - - const initTimeMilliseconds = engineReadyTime - translateButtonClickedTime; - const translationTimeSeconds = millisecondsToSeconds( - translationCompleteTime - engineReadyTime - ); - const wordsPerSecond = wordCount / translationTimeSeconds; - const tokensPerSecond = tokenCount / translationTimeSeconds; - - journal.pushMetrics([ - [TranslationsBencher.METRIC_ENGINE_INIT_TIME, initTimeMilliseconds], - [TranslationsBencher.METRIC_WORDS_PER_SECOND, wordsPerSecond], - [TranslationsBencher.METRIC_TOKENS_PER_SECOND, tokensPerSecond], - [ - TranslationsBencher.METRIC_TOTAL_TRANSLATION_TIME, - translationTimeSeconds, - ], - ]); - - await cleanup(); - } - } - - /** - * Injects a mutation observer into the test page to detect when the final paragraph - * has been translated, and dispatch an event when that happens. This is a signal that - * we are nearing the end of translating, at which point we can wait for the pending - * request count to reduce to zero. - * - * @param {Function} runInPage - Runs a closure within the content context of the page. - * @returns {Promise} Resolves when the observer is injected. - */ - static async #injectFinalParagraphTranslatedObserver(runInPage) { - await runInPage(TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - const lastParagraph = getFinalParagraph(); - - if (!lastParagraph) { - throw new Error("Unable to find the final paragraph for observation."); - } - - const observer = new content.MutationObserver( - (_mutationsList, _observer) => { - content.document.dispatchEvent( - new CustomEvent("FinalParagraphTranslated") - ); - } - ); - - observer.observe(lastParagraph, { - childList: true, - }); - }); - } - - /** - * Returns a Promise that resolves with the timestamp when the Translations engine becomes ready. - * - * @param {Browser} browser - The browser hosting the translation. - * @returns {Promise} The timestamp when the engine is ready. - */ - static async #getEngineReadyTimestampPromise(browser) { - const { promise, resolve } = Promise.withResolvers(); - - function maybeGetTranslationStartTime(event) { - if ( - event.detail.reason === "isEngineReady" && - event.detail.actor.languageState.isEngineReady - ) { - browser.removeEventListener( - "TranslationsParent:LanguageState", - maybeGetTranslationStartTime - ); - resolve(performance.now()); - } - } - - browser.addEventListener( - "TranslationsParent:LanguageState", - maybeGetTranslationStartTime - ); - - return promise; - } - - /** - * Returns a Promise that resolves with the timestamp after the translation is complete. - * - * @param {Function} runInPage - A helper to run code on the test page. - * @returns {Promise} The timestamp when the translation is complete. - */ - static async #getTranslationCompleteTimestampPromise(runInPage) { - await runInPage(async ({ waitForCondition }) => { - // First, wait for the final paragraph to be translated. - await new Promise(resolve => { - content.document.addEventListener("FinalParagraphTranslated", resolve, { - once: true, - }); - }); - - const translationsChild = - content.windowGlobalChild.getActor("Translations"); - - if ( - translationsChild.translatedDoc?.hasPendingCallbackOnEventLoop() || - translationsChild.translatedDoc?.hasPendingTranslationRequests() || - translationsChild.translatedDoc?.isObservingAnyElementForContentIntersection() - ) { - // The final paragraph was translated, but it wasn't the final request, - // so we must still wait for every translation request to complete. - await waitForCondition( - () => - !translationsChild.translatedDoc?.hasPendingCallbackOnEventLoop() && - !translationsChild.translatedDoc?.hasPendingTranslationRequests() && - !translationsChild.translatedDoc?.isObservingAnyElementForContentIntersection(), - "Waiting for all pending translation requests to complete." - ); - } - }); - - return performance.now(); - } - - /** - * Returns the total memory used by both the parent process and the inference - * process in mebibytes (MiB). - * - * @returns {Promise<{ parentMemoryMiB: number, inferenceMemoryMiB: number }>} - * The total memory usage for each process in mebibytes. - */ - static async #getTotalMemoryUsageByProcess() { - const { parentInfo, inferenceInfo } = - await TranslationsBencher.#fetchProcessesInfo(); - return { - parentMemoryMiB: bytesToMebibytes(parentInfo.memory), - inferenceMemoryMiB: bytesToMebibytes(inferenceInfo.memory), - }; - } - - /** - * Returns the process info for both the parent process and inference process. - * - * @returns {Promise<{ parentInfo: { pid: number, memory: number, cpuTime: number, cpuCycleCount: number }, - * inferenceInfo: { pid: number, memory: number, cpuTime: number, cpuCycleCount: number } }>} - */ - static async #fetchProcessesInfo() { - let info = await ChromeUtils.requestProcInfo(); - - const parentInfo = { - pid: info.pid, - memory: info.memory, - cpuTime: info.cpuTime, - cpuCycleCount: info.cpuCycleCount, - }; - - let inferenceInfo = {}; - for (const child of info.children) { - // At the time of writing, there is only a single inference process. - // If we one day spawn multiple inference processes, this code will - // need to be revised. - if (child.type === "inference") { - inferenceInfo = { - pid: child.pid, - memory: child.memory, - cpuTime: child.cpuTime, - cpuCycleCount: child.cpuCycleCount, - }; - break; - } - } - - return { - parentInfo, - inferenceInfo, - }; - } -} - -/** - * A collection of shared functionality utilized by - * FullPageTranslationsTestUtils and SelectTranslationsTestUtils. - * - * Using functions from the aforementioned classes is preferred over - * using functions from this class directly. - */ -class SharedTranslationsTestUtils { - /** - * Asserts that the specified element currently has focus. - * - * @param {Element} element - The element to check for focus. - */ - static _assertHasFocus(element) { - is( - document.activeElement, - element, - `The element '${element.id}' should have focus.` - ); - } - - /** - * 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 - * @param {string} expectedId - The expected id that mainViewId is set to. - */ - static _assertPanelMainViewId(panel, expectedId) { - const mainViewId = panel.elements.multiview.getAttribute("mainViewId"); - is( - mainViewId, - expectedId, - "The mainViewId should match its expected value" - ); - } - - /** - * Asserts that the selected language in the menu matches the langTag or l10nId. - * - * @param {Element} menuList - The menu list element to check. - * @param {object} options - Options containing 'langTag' and 'l10nId' to assert against. - * @param {string} [options.langTag] - The BCP-47 language tag to match. - * @param {string} [options.l10nId] - The localization Id to match. - */ - static _assertSelectedLanguage(menuList, { langTag, l10nId }) { - ok( - menuList.label, - `The label for the menulist ${menuList.id} should not be empty.` - ); - if (langTag !== undefined) { - is( - menuList.value, - langTag, - `Expected ${menuList.id} selection to match '${langTag}'` - ); - } - if (l10nId !== undefined) { - is( - menuList.getAttribute("data-l10n-id"), - l10nId, - `Expected ${menuList.id} l10nId to match '${l10nId}'` - ); - } - } - - /** - * Asserts the visibility of the given elements based on the given expectations. - * - * @param {object} elements - An object containing the elements to be checked for visibility. - * @param {object} expectations - An object where each property corresponds to a property in elements, - * and its value is a boolean indicating whether the element should - * be visible (true) or hidden (false). - * @throws Throws if elements does not contain a property for each property in expectations. - */ - static _assertPanelElementVisibility(elements, expectations) { - const hidden = {}; - const visible = {}; - - for (const propertyName in expectations) { - ok( - elements.hasOwnProperty(propertyName), - `Expected panel elements to have property ${propertyName}` - ); - if (expectations[propertyName]) { - visible[propertyName] = elements[propertyName]; - } else { - hidden[propertyName] = elements[propertyName]; - } - } - - assertVisibility({ hidden, visible }); - } - - /** - * 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. - * - * Optionally executes a postEventAssertion function once the event occurs. - * - * @param {string} elementId - The Id of the element to wait for the event on. - * @param {string} eventName - The name of the event to wait for. - * @param {Function} callback - A callback function to execute immediately before waiting for the event. - * This is often used to trigger the event on the expected element. - * @param {Function|null} [postEventAssertion=null] - An optional callback function to execute after - * the event has occurred. - * @param {ChromeWindow} [win] - * @throws Throws if the element with the specified `elementId` does not exist. - * @returns {Promise} - */ - static async _waitForPopupEvent( - elementId, - eventName, - callback, - postEventAssertion = null, - win = window - ) { - const element = win.document.getElementById(elementId); - if (!element) { - throw new Error( - `Unable to find the ${elementId} element in the document.` - ); - } - const promise = BrowserTestUtils.waitForEvent(element, eventName); - await callback(); - info(`Waiting for the ${elementId} ${eventName} event`); - await promise; - if (postEventAssertion) { - await postEventAssertion(); - } - // Wait a single tick on the event loop. - await new Promise(resolve => setTimeout(resolve, 0)); - } -} - -/** - * A class containing test utility functions specific to testing full-page translations. - */ -class FullPageTranslationsTestUtils { - /** - * A collection of element visibility expectations for the default panel view. - */ - static #defaultViewVisibilityExpectations = { - cancelButton: true, - fromMenuList: true, - fromLabel: true, - header: true, - langSelection: true, - toMenuList: true, - toLabel: true, - translateButton: true, - }; - - /** - * 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 {object} expectations - * @param {string} expectations.langTag - A BCP-47 language tag. - * @param {boolean} expectations.checked - Whether the checkbox is expected to be checked. - * @param {boolean} expectations.disabled - Whether the menuitem is expected to be disabled. - */ - static async #assertCheckboxState( - dataL10nId, - { langTag = null, checked = true, disabled = false } - ) { - const menuItems = getAllByL10nId(dataL10nId); - for (const menuItem of menuItems) { - if (langTag) { - const { - args: { language }, - } = document.l10n.getAttributes(menuItem); - is( - language, - getIntlDisplayName(langTag), - `Should match expected language display name for ${dataL10nId}` - ); - } - is( - menuItem.disabled, - disabled, - `Should match expected disabled state for ${dataL10nId}` - ); - await waitForCondition( - () => menuItem.getAttribute("checked") === (checked ? "true" : "false"), - "Waiting for checkbox state" - ); - is( - menuItem.getAttribute("checked"), - checked ? "true" : "false", - `Should match expected checkbox state for ${dataL10nId}` - ); - } - } - - /** - * Asserts that the always-offer-translations checkbox matches the expected checked state. - * - * @param {boolean} checked - */ - static async assertIsAlwaysOfferTranslationsEnabled(checked) { - info( - `Checking that always-offer-translations is ${ - checked ? "enabled" : "disabled" - }` - ); - await FullPageTranslationsTestUtils.#assertCheckboxState( - "translations-panel-settings-always-offer-translation", - { checked } - ); - } - - /** - * Asserts that the always-translate-language checkbox matches the expected checked state. - * - * @param {string} langTag - A BCP-47 language tag - * @param {object} expectations - * @param {boolean} expectations.checked - Whether the checkbox is expected to be checked. - * @param {boolean} expectations.disabled - Whether the menuitem is expected to be disabled. - */ - static async assertIsAlwaysTranslateLanguage( - langTag, - { checked = true, disabled = false } - ) { - info( - `Checking that always-translate is ${ - checked ? "enabled" : "disabled" - } for "${langTag}"` - ); - await FullPageTranslationsTestUtils.#assertCheckboxState( - "translations-panel-settings-always-translate-language", - { langTag, checked, disabled } - ); - } - - /** - * Asserts that the never-translate-language checkbox matches the expected checked state. - * - * @param {string} langTag - A BCP-47 language tag - * @param {object} expectations - * @param {boolean} expectations.checked - Whether the checkbox is expected to be checked. - * @param {boolean} expectations.disabled - Whether the menuitem is expected to be disabled. - */ - static async assertIsNeverTranslateLanguage( - langTag, - { checked = true, disabled = false } - ) { - info( - `Checking that never-translate is ${ - checked ? "enabled" : "disabled" - } for "${langTag}"` - ); - await FullPageTranslationsTestUtils.#assertCheckboxState( - "translations-panel-settings-never-translate-language", - { langTag, checked, disabled } - ); - } - - /** - * Asserts that the never-translate-site checkbox matches the expected checked state. - * - * @param {string} url - The url of a website - * @param {object} expectations - * @param {boolean} expectations.checked - Whether the checkbox is expected to be checked. - * @param {boolean} expectations.disabled - Whether the menuitem is expected to be disabled. - */ - static async assertIsNeverTranslateSite( - url, - { checked = true, disabled = false } - ) { - info( - `Checking that never-translate is ${ - checked ? "enabled" : "disabled" - } for "${url}"` - ); - await FullPageTranslationsTestUtils.#assertCheckboxState( - "translations-panel-settings-never-translate-site", - { checked, disabled } - ); - } - - /** - * Asserts that the proper language tags are shown on the translations button. - * - * @param {string} fromLanguage - The BCP-47 language tag being translated from. - * @param {string} toLanguage - The BCP-47 language tag being translated into. - * @param {ChromeWindow} win - */ - static async assertLangTagIsShownOnTranslationsButton( - fromLanguage, - toLanguage, - win = window - ) { - info( - `Ensuring that the translations button displays the language tag "${toLanguage}"` - ); - const { button, locale } = - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: false, locale: true, icon: true }, - "The icon presents the locale.", - win - ); - is( - locale.innerText, - toLanguage.split("-")[0], - `The expected language tag "${toLanguage}" is shown.` - ); - is( - button.getAttribute("data-l10n-id"), - "urlbar-translations-button-translated" - ); - const fromLangDisplay = getIntlDisplayName(fromLanguage); - const toLangDisplay = getIntlDisplayName(toLanguage); - is( - button.getAttribute("data-l10n-args"), - `{"fromLanguage":"${fromLangDisplay}","toLanguage":"${toLangDisplay}"}` - ); - } - - /** - * Waits for all pending translation requests in the TranslationsDocument to complete. - * - * @param {Function} runInPage - A function run a closure in the content page. - */ - static async waitForAllPendingTranslationsToComplete(runInPage) { - await runInPage(async ({ waitForCondition }) => { - const translationsChild = - content.windowGlobalChild.getActor("Translations"); - - while ( - translationsChild.translatedDoc?.hasPendingTranslationRequests() || - translationsChild.translatedDoc?.hasPendingCallbackOnEventLoop() - ) { - await waitForCondition( - () => - !translationsChild.translatedDoc?.hasPendingTranslationRequests(), - "Waiting for all pending translation requests to complete." - ); - - await waitForCondition( - () => - !translationsChild.translatedDoc?.hasPendingCallbackOnEventLoop(), - "Waiting for pending event-loop callbacks to resolve in the TranslationsDocument." - ); - } - }); - } - - /** - * Waits until no elements are being observed for content intersection, - * indicating that every content-translation request has completed - * (barring future DOM mutations). - * - * @param {Function} runInPage – Executes an async closure in the content page. - */ - static async assertNoElementsAreObservedForContentIntersection(runInPage) { - await runInPage(async ({ waitForCondition }) => { - const translationsChild = - content.windowGlobalChild.getActor("Translations"); - - await waitForCondition( - () => - !translationsChild.translatedDoc?.isObservingAnyElementForContentIntersection(), - "Waiting until no elements are observed for content intersection." - ); - }); - } - - /** - * Waits until no elements are being observed for attribute intersection, - * indicating that every attribute-translation request has completed - * (barring future DOM mutations). - * - * @param {Function} runInPage – Executes an async closure in the content page. - */ - static async assertNoElementsAreObservedForAttributeIntersection(runInPage) { - await runInPage(async ({ waitForCondition }) => { - const translationsChild = - content.windowGlobalChild.getActor("Translations"); - - await waitForCondition( - () => - !translationsChild.translatedDoc?.isObservingAnyElementForAttributeIntersection(), - "Waiting until no elements are observed for attribute intersection." - ); - }); - } - - /** - * Waits until at least one element is being observed for content - * intersection. - * - * @param {Function} runInPage – Executes an async closure in the content page. - */ - static async assertAnyElementIsObservedForContentIntersection(runInPage) { - await runInPage(async ({ waitForCondition }) => { - const translationsChild = - content.windowGlobalChild.getActor("Translations"); - - await waitForCondition( - () => - translationsChild.translatedDoc?.isObservingAnyElementForContentIntersection(), - "Waiting until an element is observed for content intersection." - ); - }); - } - - /** - * Waits until at least one element is being observed for attribute - * intersection. - * - * @param {Function} runInPage – Executes an async closure in the content page. - */ - static async assertAnyElementIsObservedForAttributeIntersection(runInPage) { - await runInPage(async ({ waitForCondition }) => { - const translationsChild = - content.windowGlobalChild.getActor("Translations"); - - await waitForCondition( - () => - translationsChild.translatedDoc?.isObservingAnyElementForAttributeIntersection(), - "Waiting until an element is observed for attribute intersection." - ); - }); - } - - /** - * Waits for any translation request to initialize and become pending within the TranslationsDocument. - * - * @param {Function} runInPage - A function run a closure in the content page. - */ - static async waitForAnyRequestToInitialize(runInPage) { - await runInPage(async ({ waitForCondition }) => { - const translationsChild = - content.windowGlobalChild.getActor("Translations"); - - await waitForCondition( - () => translationsChild.translatedDoc?.hasPendingTranslationRequests(), - "Waiting for any translation request to initialize." - ); - }); - } - - /** - * Asserts that the Spanish test page H1 element's content has been translated into the target language. - * - * @param {object} options - The options for the assertion. - * - * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. - * @param {string} options.toLanguage - The BCP-47 language tag being translated into. - * @param {Function} options.runInPage - Allows running a closure in the content page. - * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. - * @param {string} [options.message] - An optional message to log to info. - */ - static async assertPageH1ContentIsTranslated({ - fromLanguage, - toLanguage, - runInPage, - endToEndTest = false, - message = null, - }) { - if (message) { - info(message); - } - info("Checking that the page header is translated"); - let callback; - if (endToEndTest) { - callback = async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's H1 is translated.", - getH1, - "Don Quixote de La Mancha" - ); - }; - } else { - callback = async (TranslationsTest, { fromLang, toLang }) => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's H1 is translated.", - getH1, - `DON QUIJOTE DE LA MANCHA [${fromLang} to ${toLang}]` - ); - }; - } - - await runInPage(callback, { fromLang: fromLanguage, toLang: toLanguage }); - } - - /** - * Asserts that the Spanish test page H1 element's content is not translated into the target language. - * - * @param {object} options - The options for the assertion. - * - * @param {Function} options.runInPage - Allows running a closure in the content page. - * @param {string} [options.message] - An optional message to log to info. - */ - static async assertPageH1ContentIsNotTranslated({ - runInPage, - message = null, - }) { - if (message) { - info(message); - } - - info("Checking that the page header is not translated"); - await runInPage(async TranslationsTest => { - const { getH1 } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's H1 is not translated and is in the original Spanish.", - getH1, - "Don Quijote de La Mancha" - ); - }); - } - - /** - * Asserts that the Spanish test page H1 element's title has been translated into the target language. - * - * @param {object} options - The options for the assertion. - * - * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. - * @param {string} options.toLanguage - The BCP-47 language tag being translated into. - * @param {Function} options.runInPage - Allows running a closure in the content page. - * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. - * @param {string} [options.message] - An optional message to log to info. - */ - static async assertPageH1TitleIsTranslated({ - fromLanguage, - toLanguage, - runInPage, - endToEndTest = false, - message = null, - }) { - if (message) { - info(message); - } - info("Checking that the page header's title attribute is translated"); - let callback; - if (endToEndTest) { - callback = async TranslationsTest => { - const { getH1Title } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's H1's title attribute is translated.", - getH1Title, - "This is the title of the page header" - ); - }; - } else { - callback = async (TranslationsTest, { fromLang, toLang }) => { - const { getH1Title } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's H1's title attribute is translated.", - getH1Title, - `ESTE ES EL TÍTULO DEL ENCABEZADO DE PÁGINA [${fromLang} to ${toLang}]` - ); - }; - } - - await runInPage(callback, { fromLang: fromLanguage, toLang: toLanguage }); - } - - /** - * Asserts that the Spanish test page H1 element's title attribute is not translated into the target language. - * - * @param {object} options - The options for the assertion. - * - * @param {Function} options.runInPage - Allows running a closure in the content page. - * @param {string} [options.message] - An optional message to log to info. - */ - static async assertPageH1TitleIsNotTranslated({ runInPage, message = null }) { - if (message) { - info(message); - } - - info("Checking that the page header's title is not translated"); - await runInPage(async TranslationsTest => { - const { getH1Title } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's H1's title is not translated and is in the original Spanish.", - getH1Title, - "Este es el título del encabezado de página" - ); - }); - } - - /** - * Asserts that the Spanish test page final

element has been translated into the target language. - * - * @param {object} options - The options for the assertion. - * - * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. - * @param {string} options.toLanguage - The BCP-47 language tag being translated into. - * @param {Function} options.runInPage - Allows running a closure in the content page. - * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. - * @param {string} [options.message] - An optional message to log to info. - */ - static async assertPageFinalParagraphContentIsTranslated({ - fromLanguage, - toLanguage, - runInPage, - endToEndTest = false, - message = null, - }) { - if (message) { - info(message); - } - info("Checking that the page's final paragraph is translated"); - let callback; - if (endToEndTest) { - callback = async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's final paragraph is translated.", - getFinalParagraph, - [ - // TODO (Bug 1967764) We need to investigate why some machines may produce - // a different translated output, given the same models and the same WASM binary. - "Well, even if you're more arms than those of the giant Briareo, you'll pay me.", - "For, though you're more arms than those of the giant Briareo, you'll pay me.", - ] - ); - }; - } else { - callback = async (TranslationsTest, { fromLang, toLang }) => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's final paragraph is translated.", - getFinalParagraph, - `— PUES, AUNQUE MOVÁIS MÁS BRAZOS QUE LOS DEL GIGANTE BRIAREO, ME LO HABÉIS DE PAGAR. [${fromLang} to ${toLang}]` - ); - }; - } - - await runInPage(callback, { fromLang: fromLanguage, toLang: toLanguage }); - } - - /** - * Asserts that the Spanish test page final

element is still in its original form. - * - * @param {object} options - The options for the assertion. - * - * @param {Function} options.runInPage - Allows running a closure in the content page. - * @param {string} [options.message] - An optional message to log to info. - */ - static async assertPageFinalParagraphContentIsNotTranslated({ - runInPage, - message = null, - }) { - if (message) { - info(message); - } - - info("Checking that the page's final paragraph is not translated"); - await runInPage(async TranslationsTest => { - const { getFinalParagraph } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The page's final paragraph is not translated and is in the original Spanish.", - getFinalParagraph, - "— Pues, aunque mováis más brazos que los del gigante Briareo, me lo habéis de pagar." - ); - }); - } - - /** - * Asserts that the Spanish test page final

element's title attribute has been translated into the target language. - * - * @param {object} options - The options for the assertion. - * - * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. - * @param {string} options.toLanguage - The BCP-47 language tag being translated into. - * @param {Function} options.runInPage - Allows running a closure in the content page. - * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. - * @param {string} [options.message] - An optional message to log to info. - */ - static async assertPageFinalParagraphTitleIsTranslated({ - fromLanguage, - toLanguage, - runInPage, - endToEndTest = false, - message = null, - }) { - if (message) { - info(message); - } - info("Checking that the final paragraph's title attribute is translated"); - let callback; - if (endToEndTest) { - callback = async TranslationsTest => { - const { getFinalParagraphTitle } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The final paragraph's title attribute is translated.", - getFinalParagraphTitle, - "This is the title of the final paragraph" - ); - }; - } else { - callback = async (TranslationsTest, { fromLang, toLang }) => { - const { getFinalParagraphTitle } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The final paragraph's title attribute is translated.", - getFinalParagraphTitle, - `ESTE ES EL TÍTULO DEL ÚLTIMO PÁRRAFO [${fromLang} to ${toLang}]` - ); - }; - } - - await runInPage(callback, { fromLang: fromLanguage, toLang: toLanguage }); - } - - /** - * Asserts that the Spanish test page final

element's title attribute is not translated into the target language. - * - * @param {object} options - The options for the assertion. - * - * @param {Function} options.runInPage - Allows running a closure in the content page. - * @param {string} [options.message] - An optional message to log to info. - */ - static async assertPageFinalParagraphTitleIsNotTranslated({ - runInPage, - message = null, - }) { - if (message) { - info(message); - } - - info( - "Checking that the final paragraph's title attribute is not translated" - ); - await runInPage(async TranslationsTest => { - const { getFinalParagraphTitle } = TranslationsTest.getSelectors(); - await TranslationsTest.assertTranslationResult( - "The final paragraph's title attribute is not translated and is in the original Spanish.", - getFinalParagraphTitle, - "Este es el título del último párrafo" - ); - }); - } - - /** - * - * @param {object} options - The options for the assertion. - * - * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. - * @param {string} options.toLanguage - The BCP-47 language tag being translated into. - * @param {Function} options.runInPage - Allows running a closure in the content page. - * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. - * @param {string} [options.message] - An optional message to log to info. - * @param {ChromeWindow} [options.win=window] - The window in which to perform the check (defaults to the current window). - */ - static async assertAllPageContentIsTranslated(options) { - await FullPageTranslationsTestUtils.assertPageH1ContentIsTranslated( - options - ); - await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsTranslated( - options - ); - - const { win, fromLanguage, toLanguage, runInPage } = options; - - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - fromLanguage, - toLanguage, - win - ); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - await FullPageTranslationsTestUtils.assertNoElementsAreObservedForContentIntersection( - runInPage - ); - } - - /** - * - * @param {object} options - The options for the assertion. - * - * @param {string} options.fromLanguage - The BCP-47 language tag being translated from. - * @param {string} options.toLanguage - The BCP-47 language tag being translated into. - * @param {Function} options.runInPage - Allows running a closure in the content page. - * @param {boolean} [options.endToEndTest=false] - Whether this assertion is for an end-to-end test. - * @param {string} [options.message] - An optional message to log to info. - * @param {ChromeWindow} [options.win=window] - The window in which to perform the check (defaults to the current window). - */ - static async assertOnlyIntersectingNodesAreTranslated(options) { - await FullPageTranslationsTestUtils.assertPageH1ContentIsTranslated( - options - ); - await FullPageTranslationsTestUtils.assertPageH1TitleIsTranslated(options); - - const { win, fromLanguage, toLanguage, runInPage } = options; - - await FullPageTranslationsTestUtils.assertLangTagIsShownOnTranslationsButton( - fromLanguage, - toLanguage, - win - ); - - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsNotTranslated( - options - ); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - options - ); - - await FullPageTranslationsTestUtils.assertAnyElementIsObservedForContentIntersection( - runInPage - ); - - await FullPageTranslationsTestUtils.assertAnyElementIsObservedForAttributeIntersection( - runInPage - ); - } - - /** - * Asserts that the Spanish test page is not translated by checking - * that the H1 element is still in its original Spanish form. - * - * @param {Function} runInPage - Allows running a closure in the content page. - * @param {string} message - An optional message to log to info. - */ - static async assertPageIsNotTranslated(runInPage, message = null) { - if (message) { - info(message); - } - - info("Ensuring that no translation requests are pending."); - await FullPageTranslationsTestUtils.waitForAllPendingTranslationsToComplete( - runInPage - ); - - info("Checking that the page is not translated"); - - await FullPageTranslationsTestUtils.assertPageH1ContentIsNotTranslated({ - runInPage, - message, - }); - - await FullPageTranslationsTestUtils.assertPageH1TitleIsNotTranslated({ - runInPage, - message, - }); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphContentIsNotTranslated( - { - runInPage, - message, - } - ); - - await FullPageTranslationsTestUtils.assertPageFinalParagraphTitleIsNotTranslated( - { - runInPage, - message, - } - ); - } - - /** - * Asserts that for each provided expectation, the visible state of the corresponding - * element in FullPageTranslationsPanel.elements both exists and matches the visibility expectation. - * - * @param {object} expectations - * A list of expectations for the visibility of any subset of FullPageTranslationsPanel.elements - */ - static #assertPanelElementVisibility(expectations = {}) { - SharedTranslationsTestUtils._assertPanelElementVisibility( - FullPageTranslationsPanel.elements, - { - cancelButton: false, - changeSourceLanguageButton: false, - dismissErrorButton: false, - error: false, - errorMessage: false, - errorMessageHint: false, - errorHintAction: false, - fromLabel: false, - fromMenuList: false, - fromMenuPopup: false, - header: false, - intro: false, - introLearnMoreLink: false, - langSelection: false, - restoreButton: false, - toLabel: false, - toMenuList: false, - toMenuPopup: false, - translateButton: false, - unsupportedHeader: false, - unsupportedHint: false, - unsupportedLearnMoreLink: false, - // Overwrite any of the above defaults with the passed in expectations. - ...expectations, - } - ); - } - - /** - * Asserts that the FullPageTranslationsPanel header has the expected l10nId. - * - * @param {string} l10nId - The expected data-l10n-id of the header. - */ - static #assertPanelHeaderL10nId(l10nId) { - const { header } = FullPageTranslationsPanel.elements; - SharedTranslationsTestUtils._assertL10nId(header, l10nId); - } - - /** - * Asserts that the FullPageTranslationsPanel error has the expected l10nId. - * - * @param {string} l10nId - The expected data-l10n-id of the error. - */ - static #assertPanelErrorL10nId(l10nId) { - const { errorMessage } = FullPageTranslationsPanel.elements; - SharedTranslationsTestUtils._assertL10nId(errorMessage, l10nId); - } - - /** - * Asserts that the mainViewId of the panel matches the given string. - * - * @param {string} expectedId - */ - static #assertPanelMainViewId(expectedId) { - SharedTranslationsTestUtils._assertPanelMainViewId( - FullPageTranslationsPanel, - expectedId - ); - - const panelView = document.getElementById(expectedId); - const label = document.getElementById( - panelView.getAttribute("aria-labelledby") - ); - ok(label, "The a11y label for the panel view can be found."); - assertVisibility({ visible: { label } }); - } - - /** - * Asserts that panel element visibility matches the default panel view. - */ - static assertPanelViewDefault() { - info("Checking that the panel shows the default view"); - FullPageTranslationsTestUtils.#assertPanelMainViewId( - "full-page-translations-panel-view-default" - ); - FullPageTranslationsTestUtils.#assertPanelElementVisibility({ - ...FullPageTranslationsTestUtils.#defaultViewVisibilityExpectations, - }); - FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( - "translations-panel-header" - ); - } - - /** - * Asserts that panel element visibility matches the initialization-failure view. - */ - static assertPanelViewInitFailure() { - info("Checking that the panel shows the default view"); - const { translateButton } = FullPageTranslationsPanel.elements; - FullPageTranslationsTestUtils.#assertPanelMainViewId( - "full-page-translations-panel-view-default" - ); - FullPageTranslationsTestUtils.#assertPanelElementVisibility({ - cancelButton: true, - error: true, - errorMessage: true, - errorMessageHint: true, - errorHintAction: true, - header: true, - translateButton: true, - }); - is( - translateButton.disabled, - true, - "The translate button should be disabled." - ); - FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( - "translations-panel-header" - ); - } - - /** - * Asserts that panel element visibility matches the panel error view. - */ - static assertPanelViewError() { - info("Checking that the panel shows the error view"); - FullPageTranslationsTestUtils.#assertPanelMainViewId( - "full-page-translations-panel-view-default" - ); - FullPageTranslationsTestUtils.#assertPanelElementVisibility({ - error: true, - errorMessage: true, - ...FullPageTranslationsTestUtils.#defaultViewVisibilityExpectations, - }); - FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( - "translations-panel-header" - ); - FullPageTranslationsTestUtils.#assertPanelErrorL10nId( - "translations-panel-error-translating" - ); - } - - /** - * Asserts that the panel element visibility matches the panel loading view. - */ - static assertPanelViewLoading() { - info("Checking that the panel shows the loading view"); - FullPageTranslationsTestUtils.assertPanelViewDefault(); - const loadingButton = getByL10nId( - "translations-panel-translate-button-loading" - ); - ok(loadingButton, "The loading button is present"); - ok(loadingButton.disabled, "The loading button is disabled"); - } - - /** - * Asserts that panel element visibility matches the panel intro view. - */ - static assertPanelViewIntro() { - info("Checking that the panel shows the intro view"); - FullPageTranslationsTestUtils.#assertPanelMainViewId( - "full-page-translations-panel-view-default" - ); - FullPageTranslationsTestUtils.#assertPanelElementVisibility({ - intro: true, - introLearnMoreLink: true, - ...FullPageTranslationsTestUtils.#defaultViewVisibilityExpectations, - }); - FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( - "translations-panel-intro-header" - ); - } - - /** - * Asserts that panel element visibility matches the panel intro error view. - */ - static assertPanelViewIntroError() { - info("Checking that the panel shows the intro error view"); - FullPageTranslationsTestUtils.#assertPanelMainViewId( - "full-page-translations-panel-view-default" - ); - FullPageTranslationsTestUtils.#assertPanelElementVisibility({ - error: true, - intro: true, - introLearnMoreLink: true, - ...FullPageTranslationsTestUtils.#defaultViewVisibilityExpectations, - }); - FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( - "translations-panel-intro-header" - ); - } - - /** - * Asserts that panel element visibility matches the panel revisit view. - */ - static assertPanelViewRevisit() { - info("Checking that the panel shows the revisit view"); - FullPageTranslationsTestUtils.#assertPanelMainViewId( - "full-page-translations-panel-view-default" - ); - FullPageTranslationsTestUtils.#assertPanelElementVisibility({ - header: true, - langSelection: true, - restoreButton: true, - toLabel: true, - toMenuList: true, - translateButton: true, - }); - FullPageTranslationsTestUtils.#assertPanelHeaderL10nId( - "translations-panel-revisit-header" - ); - } - - /** - * Asserts that panel element visibility matches the panel unsupported language view. - */ - static assertPanelViewUnsupportedLanguage() { - info("Checking that the panel shows the unsupported-language view"); - FullPageTranslationsTestUtils.#assertPanelMainViewId( - "full-page-translations-panel-view-unsupported-language" - ); - FullPageTranslationsTestUtils.#assertPanelElementVisibility({ - changeSourceLanguageButton: true, - dismissErrorButton: true, - unsupportedHeader: true, - unsupportedHint: true, - unsupportedLearnMoreLink: true, - }); - } - - /** - * Asserts that the selected from-language matches the provided language tag. - * - * @param {object} options - Options containing 'langTag' and 'l10nId' to assert against. - * @param {string} [options.langTag] - The BCP-47 language tag to match. - * @param {string} [options.l10nId] - The localization Id to match. - * @param {ChromeWindow} [options.win] - * - An optional ChromeWindow, for multi-window tests. - */ - static assertSelectedFromLanguage({ langTag, l10nId, win = window }) { - const { fromMenuList } = win.FullPageTranslationsPanel.elements; - SharedTranslationsTestUtils._assertSelectedLanguage(fromMenuList, { - langTag, - l10nId, - }); - } - - /** - * Asserts that the selected to-language matches the provided language tag. - * - * @param {object} options - Options containing 'langTag' and 'l10nId' to assert against. - * @param {string} [options.langTag] - The BCP-47 language tag to match. - * @param {string} [options.l10nId] - The localization Id to match. - * @param {ChromeWindow} [options.win] - * - An optional ChromeWindow, for multi-window tests. - */ - static assertSelectedToLanguage({ langTag, l10nId, win = window }) { - const { toMenuList } = win.FullPageTranslationsPanel.elements; - SharedTranslationsTestUtils._assertSelectedLanguage(toMenuList, { - langTag, - l10nId, - }); - } - - /** - * Assert some property about the translations button. - * - * @param {Record} visibleAssertions - * @param {string} message The message for the assertion. - * @param {ChromeWindow} [win] - * @returns {HTMLElement} - */ - static async assertTranslationsButton( - visibleAssertions, - message, - win = window - ) { - const elements = { - button: win.document.getElementById("translations-button"), - icon: win.document.getElementById("translations-button-icon"), - circleArrows: win.document.getElementById( - "translations-button-circle-arrows" - ), - locale: win.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 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; - } - - /** - * Simulates the effect of clicking the always-offer-translations menuitem. - * Requires that the settings menu of the translations panel is open, - * otherwise the test will fail. - */ - static async clickAlwaysOfferTranslations() { - logAction(); - await FullPageTranslationsTestUtils.#clickSettingsMenuItemByL10nId( - "translations-panel-settings-always-offer-translation" - ); - } - - /** - * 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. - */ - static async clickAlwaysTranslateLanguage({ - downloadHandler = null, - pivotTranslation = false, - } = {}) { - logAction(); - await FullPageTranslationsTestUtils.#clickSettingsMenuItemByL10nId( - "translations-panel-settings-always-translate-language" - ); - if (downloadHandler) { - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The icon presents the loading indicator." - ); - await downloadHandler(pivotTranslation ? 2 : 1); - } - } - - /** - * Simulates clicking the cancel button. - */ - static async clickCancelButton() { - logAction(); - const { cancelButton } = FullPageTranslationsPanel.elements; - assertVisibility({ visible: { cancelButton } }); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - () => { - click(cancelButton, "Clicking the cancel button"); - } - ); - } - - /** - * Simulates clicking the change-source-language button. - * - * @param {object} config - * @param {boolean} config.intro - * - True if the intro view should be expected - * False if the default view should be expected - */ - static async clickChangeSourceLanguageButton({ intro = false } = {}) { - logAction(); - const { changeSourceLanguageButton } = FullPageTranslationsPanel.elements; - assertVisibility({ visible: { changeSourceLanguageButton } }); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - () => { - click( - changeSourceLanguageButton, - "Click the change-source-language button" - ); - }, - intro - ? FullPageTranslationsTestUtils.assertPanelViewIntro - : FullPageTranslationsTestUtils.assertPanelViewDefault - ); - } - - /** - * Simulates clicking the dismiss-error button. - */ - static async clickDismissErrorButton() { - logAction(); - const { dismissErrorButton } = FullPageTranslationsPanel.elements; - assertVisibility({ visible: { dismissErrorButton } }); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - () => { - click(dismissErrorButton, "Click the dismiss-error button"); - } - ); - } - - /** - * Simulates the effect of clicking the manage-languages menuitem. - * Requires that the settings menu of the translations panel is open, - * otherwise the test will fail. - */ - static async clickManageLanguages() { - logAction(); - await FullPageTranslationsTestUtils.#clickSettingsMenuItemByL10nId( - "translations-panel-settings-manage-languages" - ); - } - - /** - * 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. - */ - static async clickNeverTranslateLanguage() { - logAction(); - await FullPageTranslationsTestUtils.#clickSettingsMenuItemByL10nId( - "translations-panel-settings-never-translate-language" - ); - } - - /** - * 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. - */ - static async clickNeverTranslateSite() { - logAction(); - await FullPageTranslationsTestUtils.#clickSettingsMenuItemByL10nId( - "translations-panel-settings-never-translate-site" - ); - } - - /** - * Simulates clicking the restore-page button. - * - * @param {ChromeWindow} [win] - * - An optional ChromeWindow, for multi-window tests. - */ - static async clickRestoreButton(win = window) { - logAction(); - const { restoreButton } = win.FullPageTranslationsPanel.elements; - assertVisibility({ visible: { restoreButton } }); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - () => { - click(restoreButton, "Click the restore-page button"); - } - ); - } - - /* - * Simulates the effect of toggling a menu item in the translations panel - * settings menu. Requires that the settings menu is currently open, - * otherwise the test will fail. - */ - static async #clickSettingsMenuItemByL10nId(l10nId) { - info(`Toggling the "${l10nId}" settings menu item.`); - click(getByL10nId(l10nId), `Clicking the "${l10nId}" settings menu item.`); - await closeFullPagePanelSettingsMenuIfOpen(); - } - - /** - * Simulates clicking the translate 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.onOpenPanel - * - A function to run as soon as the panel opens. - * @param {ChromeWindow} [config.win] - * - An optional ChromeWindow, for multi-window tests. - */ - static async clickTranslateButton({ - downloadHandler = null, - pivotTranslation = false, - onOpenPanel = null, - win = window, - } = {}) { - logAction(); - const { translateButton } = win.FullPageTranslationsPanel.elements; - assertVisibility({ visible: { translateButton } }); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - () => { - click(translateButton); - }, - null /* postEventAssertion */, - win - ); - - let panelOpenCallbackPromise; - if (onOpenPanel) { - panelOpenCallbackPromise = - FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - () => {}, - onOpenPanel - ); - } - - if (downloadHandler) { - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true, circleArrows: true, locale: false, icon: true }, - "The icon presents the loading indicator.", - win - ); - await downloadHandler(pivotTranslation ? 2 : 1); - } - - await panelOpenCallbackPromise; - } - - /** - * Opens the translations panel. - * - * @param {object} config - * @param {Function} config.onOpenPanel - * - A function to run as soon as the panel opens. - * @param {boolean} config.openFromAppMenu - * - Open the panel from the app menu. If false, uses the translations button. - * @param {boolean} config.openWithKeyboard - * - Open the panel by synthesizing the keyboard. If false, synthesizes the mouse. - * @param {string} [config.expectedFromLanguage] - The expected from-language tag. - * @param {string} [config.expectedToLanguage] - The expected to-language tag. - * @param {ChromeWindow} [config.win] - * - An optional window for multi-window tests. - */ - static async openPanel({ - onOpenPanel = null, - openFromAppMenu = false, - openWithKeyboard = false, - expectedFromLanguage = undefined, - expectedToLanguage = undefined, - win = window, - }) { - logAction(); - await closeAllOpenPanelsAndMenus(win); - if (openFromAppMenu) { - await FullPageTranslationsTestUtils.#openPanelViaAppMenu({ - win, - onOpenPanel, - openWithKeyboard, - }); - } else { - await FullPageTranslationsTestUtils.#openPanelViaTranslationsButton({ - win, - onOpenPanel, - openWithKeyboard, - }); - } - if (expectedFromLanguage !== undefined) { - FullPageTranslationsTestUtils.assertSelectedFromLanguage({ - win, - langTag: expectedFromLanguage, - }); - } - if (expectedToLanguage !== undefined) { - FullPageTranslationsTestUtils.assertSelectedToLanguage({ - win, - langTag: expectedToLanguage, - }); - } - } - - /** - * Opens the translations panel via the app menu. - * - * @param {object} config - * @param {Function} config.onOpenPanel - * - A function to run as soon as the panel opens. - * @param {boolean} config.openWithKeyboard - * - Open the panel by synthesizing the keyboard. If false, synthesizes the mouse. - * @param {ChromeWindow} [config.win] - */ - static async #openPanelViaAppMenu({ - onOpenPanel = null, - openWithKeyboard = false, - win = window, - }) { - logAction(); - const appMenuButton = getById("PanelUI-menu-button", win.document); - if (openWithKeyboard) { - hitEnterKey(appMenuButton, "Opening the app-menu button with keyboard"); - } else { - click(appMenuButton, "Opening the app-menu button"); - } - await BrowserTestUtils.waitForEvent(win.PanelUI.mainView, "ViewShown"); - - const translateSiteButton = getById( - "appMenu-translate-button", - win.document - ); - - is( - translateSiteButton.disabled, - false, - "The app-menu translate button should be enabled" - ); - - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - () => { - if (openWithKeyboard) { - hitEnterKey(translateSiteButton, "Opening the popup with keyboard"); - } else { - click(translateSiteButton, "Opening the popup"); - } - }, - onOpenPanel - ); - } - - /** - * Opens the translations panel via the translations button. - * - * @param {object} config - * @param {Function} config.onOpenPanel - * - A function to run as soon as the panel opens. - * @param {boolean} config.openWithKeyboard - * - Open the panel by synthesizing the keyboard. If false, synthesizes the mouse. - * @param {ChromeWindow} [config.win] - */ - static async #openPanelViaTranslationsButton({ - onOpenPanel = null, - openWithKeyboard = false, - win = window, - }) { - logAction(); - const { button } = - await FullPageTranslationsTestUtils.assertTranslationsButton( - { button: true }, - "The translations button is visible.", - win - ); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - () => { - if (openWithKeyboard) { - hitEnterKey(button, "Opening the popup with keyboard"); - } else { - click(button, "Opening the popup"); - } - }, - onOpenPanel, - win - ); - } - - /** - * Opens the translations panel settings menu. - * Requires that the translations panel is already open. - */ - static async openTranslationsSettingsMenu() { - logAction(); - const gearIcons = getAllByL10nId("translations-panel-settings-button"); - for (const gearIcon of gearIcons) { - if (BrowserTestUtils.isHidden(gearIcon)) { - continue; - } - click(gearIcon, "Open the settings menu"); - info("Waiting for settings menu to open."); - const manageLanguages = await waitForCondition(() => - maybeGetByL10nId("translations-panel-settings-manage-languages") - ); - ok( - manageLanguages, - "The manage languages item should be visible in the settings menu." - ); - return; - } - } - - /** - * Changes the selected language by opening the dropdown menu for each provided language tag. - * - * @param {string} langTag - The BCP-47 language tag to select from the dropdown menu. - * @param {object} elements - Elements involved in the dropdown language selection process. - * @param {Element} elements.menuList - The element that triggers the dropdown menu. - * @param {Element} elements.menuPopup - The dropdown menu element containing selectable languages. - * @param {ChromeWindow} [win] - * - An optional ChromeWindow, for multi-window tests. - * - * @returns {Promise} - */ - static async #changeSelectedLanguage(langTag, elements, win = window) { - const { menuList, menuPopup } = elements; - - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - () => click(menuList), - null /* postEventAssertion */, - win - ); - - const menuItem = menuPopup.querySelector(`[value="${langTag}"]`); - await FullPageTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - () => { - click(menuItem); - // Synthesizing a click on the menuitem isn't closing the popup - // as a click normally would, so this tab keypress is added to - // ensure the popup closes. - EventUtils.synthesizeKey("KEY_Tab", {}, win); - }, - null /* postEventAssertion */, - win - ); - } - - /** - * Switches the selected from-language to the provided language tag. - * - * @param {object} options - * @param {string} options.langTag - A BCP-47 language tag. - * @param {ChromeWindow} [options.win] - * - An optional ChromeWindow, for multi-window tests. - */ - static async changeSelectedFromLanguage({ langTag, win = window }) { - logAction(langTag); - const { fromMenuList: menuList, fromMenuPopup: menuPopup } = - win.FullPageTranslationsPanel.elements; - await FullPageTranslationsTestUtils.#changeSelectedLanguage( - langTag, - { - menuList, - menuPopup, - }, - win - ); - } - - /** - * Switches the selected to-language to the provided language tag. - * - * @param {object} options - * @param {string} options.langTag - A BCP-47 language tag. - * @param {ChromeWindow} [options.win] - * - An optional ChromeWindow, for multi-window tests. - */ - static async changeSelectedToLanguage({ langTag, win = window }) { - logAction(langTag); - const { toMenuList: menuList, toMenuPopup: menuPopup } = - win.FullPageTranslationsPanel.elements; - await FullPageTranslationsTestUtils.#changeSelectedLanguage( - langTag, - { - menuList, - menuPopup, - }, - win - ); - } - - /** - * 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 - * @param {Function} postEventAssertion - * An optional assertion to be made immediately after the event occurs. - * @param {ChromeWindow} [win] - * @returns {Promise} - */ - static async waitForPanelPopupEvent( - eventName, - callback, - postEventAssertion = null, - win = window - ) { - // De-lazify the panel elements. - win.FullPageTranslationsPanel.elements; - await SharedTranslationsTestUtils._waitForPopupEvent( - "full-page-translations-panel", - eventName, - callback, - postEventAssertion, - win - ); - } -} - -/** - * A class containing test utility functions specific to testing select translations. - */ -class SelectTranslationsTestUtils { - /** - * Opens the context menu then asserts properties of the translate-selection item in the context menu. - * - * @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. - * - * @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

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. - * @param {boolean} options.selectFrenchSentence - Selects a French sentence. - * @param {boolean} options.selectEnglishSentence - Selects an English sentence. - * @param {boolean} options.selectSpanishSentence - Selects a Spanish sentence. - * @param {boolean} options.openAtFrenchSection - Opens the context menu at the section of French text. - * @param {boolean} options.openAtEnglishSection - Opens the context menu at the section of English text. - * @param {boolean} options.openAtSpanishSection - Opens the context menu at the section of Spanish text. - * @param {boolean} options.openAtFrenchSentence - Opens the context menu at a French sentence. - * @param {boolean} options.openAtEnglishSentence - Opens the context menu at an English sentence. - * @param {boolean} options.openAtSpanishSentence - Opens the context menu at a Spanish sentence. - * @param {boolean} options.openAtFrenchHyperlink - Opens the context menu at a hyperlinked French text. - * @param {boolean} options.openAtEnglishHyperlink - Opens the context menu at a hyperlinked English text. - * @param {boolean} options.openAtSpanishHyperlink - Opens the context menu at a hyperlinked Spanish text. - * @param {boolean} options.openAtURLHyperlink - Opens the context menu at a hyperlinked URL text. - * @param {string} [message] - A message to log to info. - * @throws Throws an error if the properties of the translate-selection item do not match the expected options. - */ - static async assertContextMenuTranslateSelectionItem( - runInPage, - { - expectMenuItemVisible, - expectedTargetLanguage, - selectH1, - selectPdfSpan, - selectFrenchSection, - selectEnglishSection, - selectSpanishSection, - selectFrenchSentence, - selectEnglishSentence, - selectSpanishSentence, - openAtH1, - openAtPdfSpan, - openAtFrenchSection, - openAtEnglishSection, - openAtSpanishSection, - openAtFrenchSentence, - openAtEnglishSentence, - openAtSpanishSentence, - openAtFrenchHyperlink, - openAtEnglishHyperlink, - openAtSpanishHyperlink, - openAtURLHyperlink, - }, - message - ) { - logAction(); - - if (message) { - info(message); - } - - await closeAllOpenPanelsAndMenus(); - - await SelectTranslationsTestUtils.openContextMenu(runInPage, { - expectMenuItemVisible, - expectedTargetLanguage, - selectH1, - selectPdfSpan, - selectFrenchSection, - selectEnglishSection, - selectSpanishSection, - selectFrenchSentence, - selectEnglishSentence, - selectSpanishSentence, - openAtH1, - openAtPdfSpan, - openAtFrenchSection, - openAtEnglishSection, - openAtSpanishSection, - openAtFrenchSentence, - openAtEnglishSentence, - openAtSpanishSentence, - openAtFrenchHyperlink, - openAtEnglishHyperlink, - openAtSpanishHyperlink, - openAtURLHyperlink, - }); - - const menuItem = maybeGetById( - "context-translate-selection", - /* ensureIsVisible */ false - ); - - if (expectMenuItemVisible !== undefined) { - const visibility = expectMenuItemVisible ? "visible" : "hidden"; - assertVisibility({ [visibility]: { menuItem } }); - } - - if (expectMenuItemVisible === true) { - if (expectedTargetLanguage) { - // Target language expected, check for the data-l10n-id with a `{$language}` argument. - const expectedL10nId = - selectH1 || - selectPdfSpan || - selectFrenchSection || - selectEnglishSection || - selectSpanishSection || - selectFrenchSentence || - selectEnglishSentence || - selectSpanishSentence - ? "main-context-menu-translate-selection-to-language" - : "main-context-menu-translate-link-text-to-language"; - - await waitForCondition( - () => - TranslationsUtils.langTagsMatch( - menuItem.getAttribute("target-language"), - expectedTargetLanguage - ), - `Waiting for translate-selection context menu item to match the expected target language ${expectedTargetLanguage}` - ); - await waitForCondition( - () => menuItem.getAttribute("data-l10n-id") === expectedL10nId, - `Waiting for translate-selection context menu item to have the correct data-l10n-id '${expectedL10nId}` - ); - - if (Services.locale.appLocaleAsBCP47 === "en-US") { - // We only want to test the localized name in CI if the current app locale is the default (en-US). - const expectedLanguageDisplayName = getIntlDisplayName( - expectedTargetLanguage - ); - await waitForCondition(() => { - const l10nArgs = JSON.parse( - menuItem.getAttribute("data-l10n-args") - ); - return l10nArgs.language === expectedLanguageDisplayName; - }, `Waiting for translate-selection context menu item to have the correct data-l10n-args '${expectedLanguageDisplayName}`); - } - } else { - // No target language expected, check for the data-l10n-id that has no `{$language}` argument. - const expectedL10nId = - selectH1 || - selectPdfSpan || - selectFrenchSection || - selectEnglishSection || - selectSpanishSection || - selectFrenchSentence || - selectEnglishSentence || - selectSpanishSentence - ? "main-context-menu-translate-selection" - : "main-context-menu-translate-link-text"; - await waitForCondition( - () => !menuItem.getAttribute("target-language"), - "Waiting for translate-selection context menu item to remove its target-language attribute." - ); - await waitForCondition( - () => menuItem.getAttribute("data-l10n-id") === expectedL10nId, - `Waiting for translate-selection context menu item to have the correct data-l10n-id '${expectedL10nId}` - ); - } - } - } - - /** - * Tests that the context menu displays the expected target language for translation based on - * the provided configurations. - * - * @param {object} options - Options for configuring the test environment and expected language behavior. - * @param {Array.} options.runInPage - A content-exposed function to run within the context of the page. - * @param {Array.} [options.systemLocales=[]] - Locales to mock as system locales. - * @param {Array.} [options.appLocales=[]] - Locales to mock as application locales. - * @param {Array.} [options.webLanguages=[]] - Languages to mock as web languages. - * @param {string} options.expectedTargetLanguage - The expected target language for the translate-selection item. - */ - static async testContextMenuItemWithLocales({ - runInPage, - systemLocales = [], - appLocales = [], - webLanguages = [], - expectedTargetLanguage, - }) { - const cleanupLocales = await mockLocales({ - systemLocales, - appLocales, - webLanguages, - }); - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - { - selectSpanishSentence: true, - openAtSpanishSentence: true, - expectMenuItemVisible: true, - expectedTargetLanguage, - }, - `The translate-selection context menu item should match the expected target language '${expectedTargetLanguage}'` - ); - - await closeAllOpenPanelsAndMenus(); - await cleanupLocales(); - } - - /** - * Asserts that for each provided expectation, the visible state of the corresponding - * element in FullPageTranslationsPanel.elements both exists and matches the visibility expectation. - * - * @param {object} expectations - * A list of expectations for the visibility of any subset of SelectTranslationsPanel.elements - */ - static #assertPanelElementVisibility(expectations = {}) { - SharedTranslationsTestUtils._assertPanelElementVisibility( - SelectTranslationsPanel.elements, - { - 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, - } - ); - } - - /** - * 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", - false, - event => event.detail.phase === phase - ); - } - } - - /** - * Asserts that the SelectTranslationsPanel UI matches the expected - * state when the panel has completed its translation. - */ - 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({ - betaIcon: true, - copyButton: true, - doneButtonPrimary: true, - fromLabel: true, - fromMenuList: true, - header: true, - mainContent: true, - settingsButton: true, - textArea: true, - toLabel: true, - toMenuList: true, - translateFullPageButton: !( - isFullPageTranslationsRestrictedForPage || - isFullPageTranslationsActive() - ), - }); - SelectTranslationsTestUtils.#assertConditionalUIEnabled({ - copyButton: true, - doneButtonPrimary: true, - textArea: true, - translateFullPageButton: !( - sameLanguageSelected || - isFullPageTranslationsRestrictedForPage || - isFullPageTranslationsActive() - ), - }); - - 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(); - await SelectTranslationsTestUtils.#assertPanelTextAreaOverflow(); - - let footerButtons; - if ( - sameLanguageSelected || - isFullPageTranslationsRestrictedForPage || - isFullPageTranslationsActive() - ) { - 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, - initFailureMessageBar, - 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); - const ariaDescribedBy = tryAgainButton.getAttribute("aria-describedby"); - ok(ariaDescribedBy.includes(initFailureMessageBar.id)); - } - - /** - * 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); - const ariaDescribedBy = tryAgainButton.getAttribute("aria-describedby"); - ok(ariaDescribedBy.includes(translationFailureMessageBar.id)); - } - - static #assertPanelTextAreaDirection(langTag = null) { - const expectedTextDirection = langTag - ? Services.intl.getScriptDirection(langTag) - : null; - const { textArea } = SelectTranslationsPanel.elements; - const actualTextDirection = textArea.getAttribute("dir"); - - is( - actualTextDirection, - expectedTextDirection, - `The text direction should be ${expectedTextDirection}` - ); - } - - /** - * 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 async #assertPanelTextAreaOverflow() { - const { textArea } = SelectTranslationsPanel.elements; - 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); - - info("Ensuring that the textarea cursor is at the beginning."); - await waitForCondition( - () => textArea.selectionStart === 0 && textArea.selectionEnd === 0 - ); - } - } - - /** - * Asserts that the SelectTranslationsPanel translated text area is - * the correct height for the length of the translated text. - */ - static #assertPanelTextAreaHeight() { - const { textArea } = SelectTranslationsPanel.elements; - - if ( - SelectTranslationsPanel.getSourceText().length < - SelectTranslationsPanel.textLengthThreshold - ) { - is( - textArea.style.height, - SelectTranslationsPanel.shortTextHeight, - "The panel text area should have the short-text height" - ); - } else { - is( - textArea.style.height, - SelectTranslationsPanel.longTextHeight, - "The panel text area should have the long-text height" - ); - } - } - - /** - * Asserts that the SelectTranslationsPanel UI matches the expected - * state when the panel is actively translating text. - */ - 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({ - betaIcon: true, - copyButton: true, - doneButtonPrimary: true, - fromLabel: true, - fromMenuList: true, - header: true, - mainContent: true, - settingsButton: true, - textArea: true, - toLabel: true, - toMenuList: true, - translateFullPageButton: !( - isFullPageTranslationsRestrictedForPage || - isFullPageTranslationsActive() - ), - }); - SelectTranslationsTestUtils.#assertPanelHasTranslatingPlaceholder(); - } - - /** - * Asserts that the SelectTranslationsPanel UI contains the - * translating placeholder text. - */ - static async #assertPanelHasTranslatingPlaceholder() { - 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, - "Active translation text area should have the translating placeholder." - ); - SelectTranslationsTestUtils.#assertPanelTextAreaDirection(); - SelectTranslationsTestUtils.#assertConditionalUIEnabled({ - textArea: true, - copyButton: false, - doneButtonPrimary: true, - translateFullPageButton: - fromMenuList.value !== toMenuList.value && - !isFullPageTranslationsRestrictedForPage && - !isFullPageTranslationsActive(), - }); - } - - /** - * Asserts that the SelectTranslationsPanel UI contains the - * translated text. - */ - static #assertPanelHasTranslatedText() { - const { textArea, fromMenuList, toMenuList } = - 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 && - !isFullPageTranslationsActive(), - }); - - 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), - `Translated text should match ${fromLanguage} to ${toLanguage}` - ); - is( - SelectTranslationsPanel.getSourceText().length, - SelectTranslationsPanel.getTranslatedText().length - - translatedSuffix.length, - "Expected translated text length to correspond to the source text length." - ); - } - - /** - * Asserts the enabled state of action buttons in the SelectTranslationsPanel. - * - * @param {Record} enabledStates - * - An object that maps whether each element should be enabled (true) or disabled (false). - */ - 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" - }.` - ); - } - } - - /** - * Asserts that the selected from-language matches the provided language tag. - * - * @param {string} langTag - A BCP-47 language tag. - */ - static assertSelectedFromLanguage(langTag = null) { - const { fromMenuList } = SelectTranslationsPanel.elements; - SelectTranslationsTestUtils.#assertSelectedLanguage(fromMenuList, langTag); - } - - /** - * Asserts that the selected to-language matches the provided language tag. - * - * @param {string} langTag - A BCP-47 language tag. - */ - static assertSelectedToLanguage(langTag = null) { - const { toMenuList } = SelectTranslationsPanel.elements; - SelectTranslationsTestUtils.#assertSelectedLanguage(toMenuList, langTag); - } - - /** - * Asserts the selected language in the given menu list if a langTag is provided. - * If no langTag is given, asserts that the menulist displays the localized placeholder. - * - * @param {object} menuList - The menu list object to check. - * @param {string} [langTag] - The optional language tag to assert against. - */ - static #assertSelectedLanguage(menuList, langTag) { - if (langTag) { - SharedTranslationsTestUtils._assertSelectedLanguage(menuList, { - langTag, - }); - } else { - SharedTranslationsTestUtils._assertSelectedLanguage(menuList, { - l10nId: "translations-panel-choose-language", - }); - SharedTranslationsTestUtils._assertHasFocus(menuList); - } - } - - /** - * Simulates clicking the done button and waits for the panel to close. - */ - static async clickDoneButton() { - logAction(); - 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(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]), - ]); - - const translatablePhasePromise = - SelectTranslationsTestUtils.waitForPanelState("translatable"); - click(translateButton); - await translatablePhasePromise; - - 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: false, locale: true, icon: true }, - "The icon presents the locale." - ); - } - - /** - * 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 } }); - - const translatablePhasePromise = downloadHandler - ? SelectTranslationsTestUtils.waitForPanelState("translatable") - : Promise.resolve(); - - if (SelectTranslationsPanel.phase() === "init-failure") { - // The try-again button reopens the panel from the "init-failure" phase. - await SelectTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - () => click(tryAgainButton, "Clicking the try-again button") - ); - } else { - // Otherwise the try-again button just attempts to re-translate. - click(tryAgainButton, "Clicking the try-again button"); - } - - if (downloadHandler) { - await translatablePhasePromise; - 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

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. - * @param {boolean} options.selectFrenchSentence - Selects a French sentence. - * @param {boolean} options.selectEnglishSentence - Selects an English sentence. - * @param {boolean} options.selectSpanishSentence - Selects a Spanish sentence. - * @param {boolean} options.openAtFrenchSection - Opens the context menu at the section of French text. - * @param {boolean} options.openAtEnglishSection - Opens the context menu at the section of English text. - * @param {boolean} options.openAtSpanishSection - Opens the context menu at the section of Spanish text. - * @param {boolean} options.openAtFrenchSentence - Opens the context menu at a French sentence. - * @param {boolean} options.openAtEnglishSentence - Opens the context menu at an English sentence. - * @param {boolean} options.openAtSpanishSentence - Opens the context menu at a Spanish sentence. - * @param {boolean} options.openAtFrenchHyperlink - Opens the context menu at a hyperlinked French text. - * @param {boolean} options.openAtEnglishHyperlink - Opens the context menu at a hyperlinked English text. - * @param {boolean} options.openAtSpanishHyperlink - Opens the context menu at a hyperlinked Spanish text. - * @param {boolean} options.openAtURLHyperlink - Opens the context menu at a hyperlinked URL text. - * @throws Throws an error if no valid option was provided for opening the menu. - */ - static async openContextMenu(runInPage, options) { - logAction(); - - const maybeSelectContentFrom = async keyword => { - const conditionVariableName = `select${keyword}`; - const selectorFunctionName = `get${keyword}`; - - if (options[conditionVariableName]) { - await runInPage( - async (TranslationsTest, data) => { - const selectorFunction = - TranslationsTest.getSelectors()[data.selectorFunctionName]; - if (typeof selectorFunction === "function") { - const element = await selectorFunction(); - TranslationsTest.selectContentElement(element); - } - }, - { selectorFunctionName } - ); - } - }; - - await maybeSelectContentFrom("H1"); - await maybeSelectContentFrom("PdfSpan"); - await maybeSelectContentFrom("FrenchSection"); - await maybeSelectContentFrom("EnglishSection"); - await maybeSelectContentFrom("SpanishSection"); - await maybeSelectContentFrom("FrenchSentence"); - await maybeSelectContentFrom("EnglishSentence"); - await maybeSelectContentFrom("SpanishSentence"); - - const maybeOpenContextMenuAt = async keyword => { - const optionVariableName = `openAt${keyword}`; - const selectorFunctionName = `get${keyword}`; - - if (options[optionVariableName]) { - await SharedTranslationsTestUtils._waitForPopupEvent( - "contentAreaContextMenu", - "popupshown", - async () => { - await runInPage( - async (TranslationsTest, data) => { - const selectorFunction = - TranslationsTest.getSelectors()[data.selectorFunctionName]; - if (typeof selectorFunction === "function") { - const element = await selectorFunction(); - await TranslationsTest.rightClickContentElement(element); - } - }, - { selectorFunctionName } - ); - } - ); - } - }; - - await maybeOpenContextMenuAt("H1"); - await maybeOpenContextMenuAt("PdfSpan"); - await maybeOpenContextMenuAt("FrenchSection"); - await maybeOpenContextMenuAt("EnglishSection"); - await maybeOpenContextMenuAt("SpanishSection"); - await maybeOpenContextMenuAt("FrenchSentence"); - await maybeOpenContextMenuAt("EnglishSentence"); - await maybeOpenContextMenuAt("SpanishSentence"); - await maybeOpenContextMenuAt("FrenchHyperlink"); - await maybeOpenContextMenuAt("EnglishHyperlink"); - await maybeOpenContextMenuAt("SpanishHyperlink"); - await maybeOpenContextMenuAt("URLHyperlink"); - } - - /** - * Handles language-model downloads for the SelectTranslationsPanel, ensuring that expected - * UI states match based on the resolved download state. - * - * @param {object} options - Configuration options for downloads. - * @param {function(number): Promise} options.downloadHandler - The function to resolve or reject the downloads. - * @param {boolean} [options.pivotTranslation] - Whether to expect a pivot translation. - * - * @returns {Promise} - */ - static async handleDownloads({ downloadHandler, pivotTranslation }) { - if (downloadHandler) { - await SelectTranslationsTestUtils.assertPanelViewActivelyTranslating(); - await downloadHandler(pivotTranslation ? 2 : 1); - } - } - - /** - * Switches the selected from-language to the provided language tags - * - * @param {string[]} langTags - An array of BCP-47 language tags. - * @param {object} options - Configuration options for the language change. - * @param {boolean} options.openDropdownMenu - Determines whether the language change should be made via a dropdown menu or directly. - * - * @returns {Promise} - */ - static async changeSelectedFromLanguage(langTags, options) { - logAction(langTags); - const { fromMenuList, fromMenuPopup } = SelectTranslationsPanel.elements; - const { openDropdownMenu } = options; - - const switchFn = openDropdownMenu - ? SelectTranslationsTestUtils.#changeSelectedLanguageViaDropdownMenu - : SelectTranslationsTestUtils.#changeSelectedLanguageDirectly; - - await switchFn( - langTags, - { menuList: fromMenuList, menuPopup: fromMenuPopup }, - options - ); - } - - /** - * 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. - * @param {object} options - Options for selecting paragraphs and opening the context menu. - * @param {boolean} options.openDropdownMenu - Determines whether the language change should be made via a dropdown menu or directly. - * @param {Function} options.downloadHandler - Handler for initiating downloads post language change, if applicable. - * @param {Function} options.onChangeLanguage - Callback function to be executed after the language change. - * - * @returns {Promise} - */ - static async changeSelectedToLanguage(langTags, options) { - logAction(langTags); - const { toMenuList, toMenuPopup } = SelectTranslationsPanel.elements; - const { openDropdownMenu } = options; - - const switchFn = openDropdownMenu - ? SelectTranslationsTestUtils.#changeSelectedLanguageViaDropdownMenu - : SelectTranslationsTestUtils.#changeSelectedLanguageDirectly; - - await switchFn( - langTags, - { menuList: toMenuList, menuPopup: toMenuPopup }, - options - ); - } - - /** - * Directly changes the selected language to each provided language tag without using a dropdown menu. - * - * @param {string[]} langTags - An array of BCP-47 language tags for direct selection. - * @param {object} elements - Elements required for changing the selected language. - * @param {Element} elements.menuList - The menu list element where languages are directly changed. - * @param {object} options - Configuration options for language change and additional actions. - * @param {Function} options.downloadHandler - Handler for initiating downloads post language change, if applicable. - * @param {Function} options.onChangeLanguage - Callback function to be executed after the language change. - * - * @returns {Promise} - */ - static async #changeSelectedLanguageDirectly(langTags, elements, options) { - const { menuList } = elements; - const { textArea } = SelectTranslationsPanel.elements; - const { onChangeLanguage, downloadHandler } = options; - - for (const langTag of langTags) { - const menuListUpdated = BrowserTestUtils.waitForMutationCondition( - menuList, - { attributes: true, attributeFilter: ["value"] }, - () => menuList.value === langTag - ); - - menuList.focus(); - menuList.value = langTag; - menuList.dispatchEvent(new Event("command", { bubbles: true })); - await menuListUpdated; - } - - // 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); - } - - if (onChangeLanguage) { - await onChangeLanguage(); - } - } - - /** - * Changes the selected language by opening the dropdown menu for each provided language tag. - * - * @param {string[]} langTags - An array of BCP-47 language tags for selection via dropdown. - * @param {object} elements - Elements involved in the dropdown language selection process. - * @param {Element} elements.menuList - The element that triggers the dropdown menu. - * @param {Element} elements.menuPopup - The dropdown menu element containing selectable languages. - * @param {object} options - Configuration options for language change and additional actions. - * @param {Function} options.downloadHandler - Handler for initiating downloads post language change, if applicable. - * @param {Function} options.onChangeLanguage - Callback function to be executed after the language change. - * - * @returns {Promise} - */ - static async #changeSelectedLanguageViaDropdownMenu( - langTags, - elements, - options - ) { - const { menuList, menuPopup } = elements; - const { onChangeLanguage } = options; - for (const langTag of langTags) { - await SelectTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - () => click(menuList) - ); - - const menuItem = menuPopup.querySelector(`[value="${langTag}"]`); - await SelectTranslationsTestUtils.waitForPanelPopupEvent( - "popuphidden", - () => { - click(menuItem); - // Synthesizing a click on the menuitem isn't closing the popup - // as a click normally would, so this tab keypress is added to - // ensure the popup closes. - EventUtils.synthesizeKey("KEY_Tab"); - } - ); - - await SelectTranslationsTestUtils.handleDownloads(options); - if (onChangeLanguage) { - await onChangeLanguage(); - } - } - } - - /** - * Opens the Select Translations panel via the context menu based on specified options. - * - * @param {Function} runInPage - A content-exposed function to run within the context of the page. - * @param {object} options - Options for selecting paragraphs and opening the context menu. - * - * The following options will only work when testing SELECT_TEST_PAGE_URL. - * - * @param {string} options.expectedFromLanguage - The expected from-language tag. - * @param {string} options.expectedToLanguage - The expected to-language tag. - * @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. - * @param {boolean} options.selectFrenchSentence - Selects a French sentence. - * @param {boolean} options.selectEnglishSentence - Selects an English sentence. - * @param {boolean} options.selectSpanishSentence - Selects a Spanish sentence. - * @param {boolean} options.openAtFrenchSection - Opens the context menu at the section of French text. - * @param {boolean} options.openAtEnglishSection - Opens the context menu at the section of English text. - * @param {boolean} options.openAtSpanishSection - Opens the context menu at the section of Spanish text. - * @param {boolean} options.openAtFrenchSentence - Opens the context menu at a French sentence. - * @param {boolean} options.openAtEnglishSentence - Opens the context menu at an English sentence. - * @param {boolean} options.openAtSpanishSentence - Opens the context menu at a Spanish sentence. - * @param {boolean} options.openAtFrenchHyperlink - Opens the context menu at a hyperlinked French text. - * @param {boolean} options.openAtEnglishHyperlink - Opens the context menu at a hyperlinked English text. - * @param {boolean} options.openAtSpanishHyperlink - Opens the context menu at a hyperlinked Spanish text. - * @param {boolean} options.openAtURLHyperlink - Opens the context menu at a hyperlinked URL text. - * @param {Function} [options.onOpenPanel] - An optional callback function to execute after the panel opens. - * @param {string|null} [message] - An optional message to log to info. - * @throws Throws an error if the context menu could not be opened with the provided options. - * @returns {Promise} - */ - static async openPanel(runInPage, options, message) { - logAction(); - - if (message) { - info(message); - } - - await SelectTranslationsTestUtils.assertContextMenuTranslateSelectionItem( - runInPage, - options, - message - ); - - const menuItem = getById("context-translate-selection"); - - await SelectTranslationsTestUtils.waitForPanelPopupEvent( - "popupshown", - async () => { - click(menuItem); - await closeContextMenuIfOpen(); - }, - async () => { - const { onOpenPanel } = options; - await SelectTranslationsTestUtils.handleDownloads(options); - if (onOpenPanel) { - await onOpenPanel(); - } - } - ); - - const { expectedFromLanguage, expectedToLanguage } = options; - if (expectedFromLanguage !== undefined) { - SelectTranslationsTestUtils.assertSelectedFromLanguage( - expectedFromLanguage - ); - } - if (expectedToLanguage !== undefined) { - SelectTranslationsTestUtils.assertSelectedToLanguage(expectedToLanguage); - } - - const { panel } = SelectTranslationsPanel.elements; - - const documentRoleElement = panel.querySelector('[role="document"]'); - ok(documentRoleElement, "The document-role element can be found."); - - const ariaDescription = document.getElementById( - documentRoleElement.getAttribute("aria-describedby") - ); - ok(ariaDescription, "The a11y description for the panel can be found."); - - const ariaLabelIds = documentRoleElement - .getAttribute("aria-labelledby") - .split(" "); - for (const id of ariaLabelIds) { - const ariaLabel = document.getElementById(id); - ok(ariaLabel, `The a11y label element '${id}' can be found.`); - assertVisibility({ visible: { ariaLabel } }); - } - } - - /** - * 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 - * @param {Function} postEventAssertion - * An optional assertion to be made immediately after the event occurs. - * @returns {Promise} - */ - static async waitForPanelPopupEvent( - eventName, - callback, - postEventAssertion = null - ) { - // De-lazify the panel elements. - SelectTranslationsPanel.elements; - await SharedTranslationsTestUtils._waitForPopupEvent( - "select-translations-panel", - eventName, - callback, - postEventAssertion - ); - } -} - -class TranslationsSettingsTestUtils { - /** - * Opens the Translation Settings page by clicking the settings button sent in the argument. - * - * @param {HTMLElement} settingsButton - * @returns {Element} - */ - static async openAboutPreferencesTranslationsSettingsPane(settingsButton) { - const document = gBrowser.selectedBrowser.contentDocument; - - const translationsPane = - content.window.gCategoryModules.get("paneTranslations"); - const promise = BrowserTestUtils.waitForEvent( - document, - "paneshown", - false, - event => event.detail.category === "paneTranslations" - ); - - click(settingsButton, "Click settings button"); - await promise; - - return translationsPane.elements; - } - - /** - * Utility function to handle the click event for a `moz-button` element that controls - * the Download/Remove Language functionality. - * - * The button's icon reflects the current state of the language (downloaded, loading, or removed), - * which is represented by a corresponding CSS class. - * - * When this button is clicked for any language, the function waits for the button's state and icon - * to update. It then checks whether the button's state and icon match the expected state as defined - * by the test case, and logs the respective message provided by the test case. - * - * @param {Element} langButton - The `moz-button` element representing the download/remove button. - * @param {string} buttonIcon - The expected CSS class representing the button's state/icon (e.g., download, loading, or remove icon). - * @param {string} logMsg - A custom log message provided by the test case indicating the expected result. - */ - - static async downaloadButtonClick(langButton, buttonIcon, logMsg) { - if ( - !langButton.parentNode - .querySelector("moz-button") - .classList.contains(buttonIcon) - ) { - await BrowserTestUtils.waitForMutationCondition( - langButton.parentNode.querySelector("moz-button"), - { attributes: true, attributeFilter: ["class"] }, - () => - langButton.parentNode - .querySelector("moz-button") - .classList.contains(buttonIcon) - ); - } - ok( - langButton.parentNode - .querySelector("moz-button") - .classList.contains(buttonIcon), - logMsg - ); - } -} diff --git a/src/zen/tests/mochitests/translations/perftest.toml b/src/zen/tests/mochitests/translations/perftest.toml deleted file mode 100644 index 93a251a884..0000000000 --- a/src/zen/tests/mochitests/translations/perftest.toml +++ /dev/null @@ -1,9 +0,0 @@ -[DEFAULT] -support-files = [ - "head.js", - "!/toolkit/components/translations/tests/browser/shared-head.js", - "!/toolkit/components/translations/tests/browser/translations-test.mjs", -] - -["browser_translations_perf_es_en.js"] -disabled = "Disabled since we want to run this only as perftest, not in regular CI."