discourse/spec/system/post_translation_spec.rb
Alan Guo Xiang Tan 55b05c921b
DEV: Add client settled checks for system tests (#35230)
This change seeks to improve the reliability of our system tests by
resolving the lack of consistency in the state of the client side
application between steps in a system test. This is achieved by patching
various action methods in `Capybara::Playwright::Node` and
`Capybara::Playwright::Browser` so that the methods execute an async
JavaScript function on the client side that waits for the client side
application to reach a settled state. A settled state is currently
defined as:

1. No inflight ajax requests. (_messageBus and presence requests are
excluded_)
2. 2 event cycles of the Javascript event loop has happened for for all
"click", "input", "mousedown", "keydown", "focusin", "focusout",
"touchstart", "change", "resize", "scroll" DOM events that fired.

For debugging purposes, a `--debug-client-settled` CLI flag has been
added to `bin/rspec`. When used, detailed debugging information will be
printed to the browser's console as well as to `stdout` of the
`bin/rspec` process.

This change was inspired by
https://evilmartians.com/chronicles/flaky-tests-be-gone-long-lasting-relief-chronic-ci-retry-irritation
and the https://github.com/makandra/capybara-lockstep rubygem.
2025-10-10 11:03:18 +08:00

168 lines
7.2 KiB
Ruby

# frozen_string_literal: true
describe "Post translations", type: :system do
POST_LANGUAGE_SWITCHER_SELECTOR = "button[data-identifier='post-language-selector']"
fab!(:admin)
fab!(:topic)
fab!(:post) { Fabricate(:post, topic:) }
let(:topic_page) { PageObjects::Pages::Topic.new }
let(:composer) { PageObjects::Components::Composer.new }
let(:translation_selector) do
PageObjects::Components::SelectKit.new(".translation-selector-dropdown")
end
let(:post_language_selector) do
PageObjects::Components::DMenu.new(POST_LANGUAGE_SWITCHER_SELECTOR)
end
let(:view_translations_modal) { PageObjects::Modals::ViewTranslationsModal.new }
before do
SiteSetting.default_locale = "en"
SiteSetting.content_localization_supported_locales = "fr|es|pt_BR"
SiteSetting.content_localization_enabled = true
SiteSetting.post_menu =
"read|like|copyLink|flag|edit|bookmark|delete|admin|reply|addTranslation"
sign_in(admin)
end
context "when a post does not have translations" do
it "should only show the languages listed in the site setting" do
post.update!(locale: "en")
topic_page.visit_topic(topic)
find("#post_1 .post-action-menu-edit-translations-trigger").click
find(".update-translations-menu__add .post-action-menu__add-translation").click
translation_selector.expand
expect(all(".translation-selector-dropdown .select-kit-collection li").count).to eq(3)
expect(translation_selector).to have_option_value("fr")
expect(translation_selector).to have_option_value("es")
expect(translation_selector).to have_option_value("pt_BR")
expect(translation_selector).to have_no_option_value("de")
end
it "allows a user to translate a post" do
topic_page.visit_topic(topic)
find("#post_1 .post-action-menu-edit-translations-trigger").click
find(".update-translations-menu__add .post-action-menu__add-translation").click
expect(composer).to be_opened
translation_selector.expand
translation_selector.select_row_by_value("fr")
find("#translated-topic-title").fill_in(with: "Ceci est un sujet de test 0")
composer.fill_content("Bonjour le monde")
composer.submit
expect(TopicLocalization.exists?(topic_id: topic.id, locale: "fr")).to be true
expect(PostLocalization.exists?(post_id: post.id, locale: "fr")).to be true
expect(PostLocalization.find_by(post_id: post.id, locale: "fr").raw).to eq("Bonjour le monde")
expect(TopicLocalization.find_by(topic_id: topic.id, locale: "fr").title).to eq(
"Ceci est un sujet de test 0",
)
end
end
context "when a post already has translations" do
fab!(:post_localization) do
Fabricate(:post_localization, post: post, locale: "fr", raw: "Bonjour le monde")
end
let(:confirmation_dialog) { PageObjects::Components::Dialog.new }
it "allows a user to add a new translation" do
topic_page.visit_topic(topic)
find("#post_1 .post-action-menu-edit-translations-trigger").click
find(".update-translations-menu__add .post-action-menu__add-translation").click
expect(composer).to be_opened
translation_selector.expand
translation_selector.select_row_by_value("es")
find("#translated-topic-title").fill_in(with: "Este es un tema de prueba 0")
composer.fill_content("Hola mundo")
composer.submit
expect(TopicLocalization.exists?(topic_id: topic.id, locale: "es")).to be true
expect(PostLocalization.exists?(post_id: post.id, locale: "es")).to be true
expect(PostLocalization.find_by(post_id: post.id, locale: "es").raw).to eq("Hola mundo")
expect(TopicLocalization.find_by(topic_id: topic.id, locale: "es").title).to eq(
"Este es un tema de prueba 0",
)
end
it "allows a user to see locales translated" do
topic_page.visit_topic(topic)
find("#post_#{post.post_number} .post-action-menu-edit-translations-trigger").click
view_translation_button = find(".post-action-menu__view-translation")
expect(view_translation_button).to be_visible
expect(view_translation_button).to have_text(
I18n.t("js.post.localizations.view", { count: 1 }),
)
view_translation_button.click
expect(view_translations_modal).to be_open
expect(find(".post-translations-modal__locale")).to have_text("fr")
end
it "allows a user to edit a translation" do
topic_page.visit_topic(topic)
find("#post_#{post.post_number} .post-action-menu-edit-translations-trigger").click
find(".post-action-menu__view-translation").click
find(".post-translations-modal__edit-action .btn").click
expect(composer).to be_opened
expect(translation_selector).to have_selected_value("fr")
find("#translated-topic-title").fill_in(with: "C'est un sujet de test 0.")
composer.fill_content("Bonjour le monde")
composer.submit
expect(TopicLocalization.exists?(topic_id: topic.id, locale: "fr")).to be true
expect(PostLocalization.exists?(post_id: post.id, locale: "fr")).to be true
expect(PostLocalization.find_by(post_id: post.id, locale: "fr").raw).to eq("Bonjour le monde")
expect(TopicLocalization.find_by(topic_id: topic.id, locale: "fr").title).to eq(
"C'est un sujet de test 0.",
)
end
it "allows a user in content_localization_allowed_groups to delete a translation" do
topic_page.visit_topic(topic)
expect(PostLocalization.exists?(post_id: post.id, locale: "fr")).to be true
find("#post_#{post.post_number} .post-action-menu-edit-translations-trigger").click
find(".post-action-menu__view-translation").click
find(".post-translations-modal__delete-action .btn").click
expect(confirmation_dialog).to be_open
confirmation_dialog.click_yes
expect(PostLocalization.exists?(post_id: post.id, locale: "fr")).to be false
end
end
context "when creating a new post in a different locale" do
it "should only show the languages listed in the site setting and default locale and a none value" do
visit("/latest")
page.find("#create-topic").click
post_language_selector.expand
expect(post_language_selector).to have_content("English (US)") # default locale
expect(post_language_selector).to have_content("French (Français)")
expect(post_language_selector).to have_content("Spanish (Español)")
expect(post_language_selector).to have_content("Portuguese (Português (BR))")
expect(post_language_selector).to have_content(
I18n.t("js.post.localizations.post_language_selector.none"),
)
end
it "should allow a user to create a post in a different locale" do
visit("/latest")
page.find("#create-topic").click
post_language_selector.expand
post_language_selector.option(".dropdown-menu__item[data-menu-option-id='fr']").click
composer.fill_title("Ceci est un sujet de test 1")
composer.fill_content("Bonjour le monde")
composer.submit
updated_post = Topic.last.posts.first
expect(updated_post.locale).to eq("fr")
end
it "should not have a locale set by default" do
visit("/latest")
page.find("#create-topic").click
expect(page.has_no_css?("#{POST_LANGUAGE_SWITCHER_SELECTOR} .d-button-label")).to be true
end
end
end