2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-03-04 01:15:08 +08:00
discourse/spec/requests/post_localizations_controller_spec.rb
Natalie Tay 3f8ccda7aa
FEATURE: Allow post authors to localize their own posts (#36178)
We should allow authors to localize their own content.

This is gated behind the
`content_localization_allow_author_localization` setting, which is
enabled by default.

Meta:
https://meta.discourse.org/t/feature-request-allow-users-to-localize-only-their-own-topics/389147
2025-11-25 11:02:22 +08:00

282 lines
8.5 KiB
Ruby

# frozen_string_literal: true
describe PostLocalizationsController do
fab!(:user)
fab!(:group)
fab!(:post_record) { Fabricate(:post, version: 100) }
let(:locale) { "ja" }
let(:raw) { "これは翻訳です。" }
before do
SiteSetting.content_localization_enabled = true
SiteSetting.content_localization_allowed_groups = group.id.to_s
group.add(user)
sign_in(user)
end
describe "#show" do
it "allows users in allowed groups to view localizations" do
Fabricate(:post_localization, post: post_record, locale:)
get "/post_localizations/#{post_record.id}.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["post_localizations"].length).to eq(1)
end
it "denies users not in allowed groups" do
group.remove(user)
get "/post_localizations/#{post_record.id}.json"
expect(response.status).to eq(403)
end
context "with author localization enabled" do
fab!(:author, :user)
fab!(:author_post) { Fabricate(:post, user: author) }
before do
SiteSetting.content_localization_allow_author_localization = true
group.remove(author)
end
it "allows post authors to view localizations for their own posts" do
Fabricate(:post_localization, post: author_post, locale:)
sign_in(author)
get "/post_localizations/#{author_post.id}.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["post_localizations"].length).to eq(1)
end
it "denies post authors from viewing localizations for others' posts" do
Fabricate(:post_localization, post: post_record, locale:)
sign_in(author)
get "/post_localizations/#{post_record.id}.json"
expect(response.status).to eq(403)
end
end
end
describe "#create_or_update" do
context "when localization does not exist" do
it "creates a new localization" do
expect {
post "/post_localizations/create_or_update.json",
params: {
post_id: post_record.id,
locale:,
raw:,
}
}.to change { PostLocalization.count }.by(1)
expect(response.status).to eq(201)
localization = PostLocalization.last
expect(localization).to have_attributes(
locale:,
raw:,
post_id: post_record.id,
post_version: post_record.version,
localizer_user_id: user.id,
)
end
end
context "when localization already exists" do
it "updates the existing localization" do
localization = Fabricate(:post_localization, post: post_record, locale:, raw: "古い翻訳")
new_user = Fabricate(:user, groups: [group])
sign_in(new_user)
expect {
post "/post_localizations/create_or_update.json",
params: {
post_id: post_record.id,
locale:,
raw:,
}
}.not_to change { PostLocalization.count }
expect(response.status).to eq(200)
localization.reload
expect(localization.raw).to eq(raw)
expect(localization.localizer_user_id).to eq(new_user.id)
end
end
it "returns forbidden if user is not in allowed group" do
group.remove(user)
post "/post_localizations/create_or_update.json",
params: {
post_id: post_record.id,
locale:,
raw:,
}
expect(response.status).to eq(403)
end
it "returns not found if post does not exist" do
post "/post_localizations/create_or_update.json", params: { post_id: -1, locale:, raw: }
expect(response.status).to eq(404)
end
end
describe "#destroy" do
it "destroys the localization" do
Fabricate(:post_localization, post: post_record, locale:)
expect {
delete "/post_localizations/destroy.json", params: { post_id: post_record.id, locale: }
}.to change { PostLocalization.count }.by(-1)
expect(response.status).to eq(204)
end
it "returns 404 if localization is missing" do
delete "/post_localizations/destroy.json", params: { post_id: post_record.id, locale: "nope" }
expect(response.status).to eq(404)
end
end
context "with author localization" do
fab!(:author, :user)
fab!(:author_post) { Fabricate(:post, user: author, version: 100) }
fab!(:other_user, :user)
before { group.remove(author) }
describe "#create_or_update for post authors" do
it "allows post author to create localization on their own post" do
sign_in(author)
SiteSetting.content_localization_allow_author_localization = false
expect {
post "/post_localizations/create_or_update.json",
params: {
post_id: author_post.id,
locale:,
raw:,
}
}.not_to change { PostLocalization.count }
SiteSetting.content_localization_allow_author_localization = true
expect {
post "/post_localizations/create_or_update.json",
params: {
post_id: author_post.id,
locale:,
raw:,
}
}.to change { PostLocalization.count }.by(1)
expect(response.status).to eq(201)
localization = PostLocalization.last
expect(localization.localizer_user_id).to eq(author.id)
end
it "denies post author from creating localization on others' posts" do
SiteSetting.content_localization_allow_author_localization = true
sign_in(author)
expect {
post "/post_localizations/create_or_update.json",
params: {
post_id: post_record.id,
locale:,
raw:,
}
}.not_to change { PostLocalization.count }
expect(response.status).to eq(403)
end
it "allows author to update their own localization" do
localization =
Fabricate(
:post_localization,
post: author_post,
locale:,
raw: "古い翻訳",
localizer_user_id: author.id,
)
sign_in(author)
SiteSetting.content_localization_allow_author_localization = false
expect {
post "/post_localizations/create_or_update.json",
params: {
post_id: author_post.id,
locale:,
raw:,
}
}.not_to change { localization.reload.raw }
SiteSetting.content_localization_allow_author_localization = true
post "/post_localizations/create_or_update.json",
params: {
post_id: author_post.id,
locale:,
raw:,
}
expect(response.status).to eq(200)
localization.reload
expect(localization.raw).to eq(raw)
end
end
describe "#destroy for post authors" do
it "allows author to delete their own localization" do
Fabricate(:post_localization, post: author_post, locale:, localizer_user_id: author.id)
sign_in(author)
SiteSetting.content_localization_allow_author_localization = false
expect {
delete "/post_localizations/destroy.json", params: { post_id: author_post.id, locale: }
}.not_to change { PostLocalization.count }
SiteSetting.content_localization_allow_author_localization = true
expect {
delete "/post_localizations/destroy.json", params: { post_id: author_post.id, locale: }
}.to change { PostLocalization.count }.by(-1)
expect(response.status).to eq(204)
end
end
it "allows users in allowed groups full access regardless of author setting" do
localization =
Fabricate(:post_localization, post: author_post, locale:, localizer_user_id: author.id)
sign_in(user)
SiteSetting.content_localization_allow_author_localization = false
expect {
post "/post_localizations/create_or_update.json",
params: {
post_id: author_post.id,
locale:,
raw: "1",
}
}.to change { localization.reload.raw }
SiteSetting.content_localization_allow_author_localization = true
expect {
post "/post_localizations/create_or_update.json",
params: {
post_id: author_post.id,
locale:,
raw: "2",
}
}.to change { localization.reload.raw }
end
end
end