0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-06 13:08:40 +08:00
discourse/spec/services/group_mentions_updater_spec.rb
Régis Hanol 73dd5b4da8
FIX: Sync category description when post content changes outside PostRevisor (#39184)
When a group or user is renamed, `GroupMentionsUpdater` and
`Jobs::UpdateUsername` update the post's raw/cooked content but skip
`PostRevisor`, so `categories.description` (a denormalized copy of the
first paragraph) is never refreshed. The Edit Category page and category
banner keep showing the old name, while the actual topic shows the new
one. Same issue with `Post#rebake!` (Rebuild HTML) and `ProcessPost`.

Extract `Post#sync_category_description` as the single source of truth
for deriving `categories.description` from a post's cooked HTML — both
`PostRevisor` and the new `Post#sync_first_post_caches` now delegate to
it. `sync_first_post_caches` also updates `topics.excerpt`, centralizing
all first-post denormalized field updates.

Call `sync_first_post_caches` from every code path that modifies post
content outside PostRevisor: `GroupMentionsUpdater`, `UpdateUsername`,
`ChangeDisplayName`, `ProcessPost`, and `Post#rebake!`.

Skip the update when the description hasn't changed to avoid unnecessary
writes. When it has changed, call `publish_category` and
`Site.clear_cache` so connected clients see the update immediately
(fixes a pre-existing flicker where the old description would briefly
appear then get overwritten by stale cached site data).

Also add a targeted query in `UpdateUsername` for category description
posts authored by the system user, which were missed by the existing
`user_actions`-based and self-mention queries.

Ref - t/181445
2026-05-11 16:13:23 +02:00

77 lines
2.4 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe GroupMentionsUpdater do
fab!(:post)
before { Jobs.run_immediately! }
describe ".update" do
it "should update valid group mentions" do
new_group_name = "awesome_team"
old_group_name = "team"
[
["@#{old_group_name} is awesome!", "@#{new_group_name} is awesome!"],
["This @#{old_group_name} is awesome!", "This @#{new_group_name} is awesome!"],
["Mention us @ @#{old_group_name}", "Mention us @ @#{new_group_name}"],
].each do |raw, expected_raw|
group =
Fabricate(:group, name: old_group_name, mentionable_level: Group::ALIAS_LEVELS[:everyone])
post.update!(raw: raw)
group.update!(name: new_group_name)
post.reload
expect(post.raw_mentions).to eq([new_group_name])
expect(post.raw).to eq(expected_raw)
group.destroy!
end
end
it "should not update invalid group mentions" do
group = Fabricate(:group, name: "team", mentionable_level: Group::ALIAS_LEVELS[:everyone])
post.update!(raw: "This is not valid@team.com")
expect(post.reload.raw_mentions).to eq([])
group.update!(name: "new_team_name")
expect(post.reload.raw_mentions).to eq([])
end
it "should update the category description when a category description topic mentions the group" do
group = Fabricate(:group, name: "old_team", mentionable_level: Group::ALIAS_LEVELS[:everyone])
category = Fabricate(:category_with_definition)
first_post = category.topic.first_post
first_post.revise(first_post.user, { raw: "This category is managed by @old_team" })
category.reload
expect(category.description).to include("old_team")
GroupMentionsUpdater.update("new_team", "old_team")
category.reload
expect(category.description).to include("new_team")
expect(category.description).not_to include("old_team")
end
it "should ignore validations" do
everyone_mention_level = Group::ALIAS_LEVELS[:everyone]
%w[awesome_team pro_team].each do |name|
Fabricate(:group, name: name, mentionable_level: everyone_mention_level)
end
post.update!(raw: "@awesome_team is cool and so is @pro_team")
SiteSetting.max_mentions_per_post = 1
GroupMentionsUpdater.update("cool_team", "awesome_team")
post.reload
expect(post.raw_mentions).to match_array(%w[cool_team pro_team])
end
end
end