mirror of
https://github.com/discourse/discourse.git
synced 2024-11-30 18:35:17 +08:00
367de2594d
* FIX: Unlike own posts on ownership transfer If a user has liked a post that has passed the `post_undo_action_window_mins` system setting window and you transfer ownership of that post to that user you will be the owner of a post that you have liked, but cannot unlike resulting in a weird UI behavior. This commit fixes this issue. The existing tests didn't check for the timeout window for unliking posts so I added that in. I couldn't find a good way to do this logic inside of the guardian class so rather than duplicating behavior of the `PostActionDestroyer` class inside of the `PostOwnerChanger` I decided to pass in a "bypass" variable that could be used to check if the calling class is the 'post_owner_changer' and bypass the guardian instead. I went this route because the guardian `can_delete_post_action` method has no way of distinguishing how to allow a user to be able to unlike their own posts after the timeout window but only on a post owner change. * use an options hash instead
241 lines
8.1 KiB
Ruby
241 lines
8.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "rails_helper"
|
|
|
|
describe PostOwnerChanger do
|
|
describe "change_owner!" do
|
|
fab!(:editor) { Fabricate(:admin) }
|
|
fab!(:user_a) { Fabricate(:user) }
|
|
let(:p1) { create_post(post_number: 1) }
|
|
let(:topic) { p1.topic }
|
|
let(:p2) { create_post(topic: topic, post_number: 2) }
|
|
let(:p3) { create_post }
|
|
|
|
it "raises an error with a parameter missing" do
|
|
expect {
|
|
PostOwnerChanger.new(post_ids: [p1.id], topic_id: topic.id, new_owner: nil, acting_user: editor)
|
|
}.to raise_error(ArgumentError)
|
|
end
|
|
|
|
it "calls PostRevisor" do
|
|
PostRevisor.any_instance.expects(:revise!)
|
|
PostOwnerChanger.new(post_ids: [p1.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
|
|
end
|
|
|
|
it "changes the user" do
|
|
bumped_at = freeze_time topic.bumped_at
|
|
now = Time.zone.now
|
|
freeze_time(now - 1.day)
|
|
|
|
old_user = p1.user
|
|
PostActionCreator.like(user_a, p1)
|
|
p1.reload
|
|
expect(p1.topic.like_count).to eq(1)
|
|
|
|
freeze_time(now)
|
|
PostOwnerChanger.new(post_ids: [p1.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
|
|
p1.reload
|
|
expect(p1.topic.like_count).to eq(0)
|
|
expect(p1.topic.bumped_at).to eq_time(bumped_at)
|
|
expect(p1.topic.last_post_user_id).to eq(user_a.id)
|
|
expect(old_user).not_to eq(p1.user)
|
|
expect(p1.user).to eq(user_a)
|
|
end
|
|
|
|
it "changes multiple posts" do
|
|
PostOwnerChanger.new(post_ids: [p1.id, p2.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
|
|
p1.reload; p2.reload
|
|
expect(p1.user).not_to eq(nil)
|
|
expect(p1.user).to eq(user_a)
|
|
expect(p1.user).to eq(p2.user)
|
|
end
|
|
|
|
it "ignores posts in other topics" do
|
|
PostOwnerChanger.new(post_ids: [p1.id, p3.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
|
|
p1.reload; p3.reload
|
|
expect(p1.user).to eq(user_a)
|
|
|
|
expect(p3.topic_id).not_to eq(p1.topic_id)
|
|
expect(p2.user).not_to eq(user_a)
|
|
end
|
|
|
|
it "skips creating new post revision if skip_revision is true" do
|
|
PostOwnerChanger.new(post_ids: [p1.id, p2.id], topic_id: topic.id, new_owner: user_a, acting_user: editor, skip_revision: true).change_owner!
|
|
p1.reload; p2.reload
|
|
expect(p1.revisions.size).to eq(0)
|
|
expect(p2.revisions.size).to eq(0)
|
|
end
|
|
|
|
it "changes the user even when the post does not pass validation" do
|
|
p1.update_attribute(:raw, "foo")
|
|
PostOwnerChanger.new(post_ids: [p1.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
|
|
expect(p1.reload.user).to eq(user_a)
|
|
end
|
|
|
|
it "changes the user even when the topic does not pass validation" do
|
|
topic.update_column(:title, "short")
|
|
|
|
PostOwnerChanger.new(post_ids: [p1.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
|
|
expect(p1.reload.user).to eq(user_a)
|
|
end
|
|
|
|
it "changes the owner when the post is deleted" do
|
|
p4 = Fabricate(:post, topic: topic, reply_to_post_number: p2.post_number)
|
|
PostDestroyer.new(editor, p4).destroy
|
|
|
|
PostOwnerChanger.new(post_ids: [p4.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
|
|
expect(p4.reload.user).to eq(user_a)
|
|
end
|
|
|
|
context "sets topic notification level for the new owner" do
|
|
let(:p4) { create_post(post_number: 2, topic: topic) }
|
|
|
|
it "'watching' if the first post gets a new owner" do
|
|
PostOwnerChanger.new(post_ids: [p1.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
|
|
tu = TopicUser.find_by(user_id: user_a.id, topic_id: topic.id)
|
|
expect(tu.notification_level).to eq(3)
|
|
end
|
|
|
|
it "'tracking' if other than the first post gets a new owner" do
|
|
PostOwnerChanger.new(post_ids: [p4.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
|
|
tu = TopicUser.find_by(user_id: user_a.id, topic_id: topic.id)
|
|
expect(tu.notification_level).to eq(2)
|
|
end
|
|
end
|
|
|
|
context "integration tests" do
|
|
let(:p1user) { p1.user }
|
|
let(:p2user) { p2.user }
|
|
|
|
before do
|
|
topic.update!(user_id: p1user.id)
|
|
|
|
p1user.user_stat.update!(
|
|
topic_count: 1,
|
|
post_count: 1,
|
|
first_post_created_at: p1.created_at,
|
|
)
|
|
|
|
p2user.user_stat.update!(
|
|
topic_count: 0,
|
|
post_count: 1,
|
|
first_post_created_at: p2.created_at,
|
|
)
|
|
|
|
UserAction.create!(action_type: UserAction::NEW_TOPIC, user_id: p1user.id, acting_user_id: p1user.id,
|
|
target_post_id: -1, target_topic_id: p1.topic_id, created_at: p1.created_at)
|
|
UserAction.create!(action_type: UserAction::REPLY, user_id: p2user.id, acting_user_id: p2user.id,
|
|
target_post_id: p2.id, target_topic_id: p2.topic_id, created_at: p2.created_at)
|
|
|
|
UserActionManager.enable
|
|
end
|
|
|
|
subject(:change_owners) do
|
|
PostOwnerChanger.new(
|
|
post_ids: [p1.id, p2.id],
|
|
topic_id: topic.id,
|
|
new_owner: user_a,
|
|
acting_user: editor
|
|
).change_owner!
|
|
end
|
|
|
|
it "updates users' topic and post counts" do
|
|
PostActionCreator.like(p2user, p1)
|
|
expect(p1user.user_stat.reload.likes_received).to eq(1)
|
|
|
|
change_owners
|
|
|
|
p1user.reload; p2user.reload; user_a.reload
|
|
expect(p1user.topic_count).to eq(0)
|
|
expect(p1user.post_count).to eq(0)
|
|
expect(p2user.topic_count).to eq(0)
|
|
expect(p2user.post_count).to eq(0)
|
|
expect(user_a.topic_count).to eq(1)
|
|
expect(user_a.post_count).to eq(2)
|
|
|
|
p1_user_stat = p1user.user_stat
|
|
|
|
expect(p1_user_stat.first_post_created_at).to eq(nil)
|
|
expect(p1_user_stat.likes_received).to eq(0)
|
|
|
|
p2_user_stat = p2user.user_stat
|
|
|
|
expect(p2_user_stat.first_post_created_at).to eq(nil)
|
|
|
|
user_a_stat = user_a.user_stat
|
|
|
|
expect(user_a_stat.first_post_created_at).to be_present
|
|
expect(user_a_stat.likes_received).to eq(1)
|
|
end
|
|
|
|
it "handles whispers" do
|
|
whisper = PostCreator.new(
|
|
editor,
|
|
topic_id: p1.topic_id,
|
|
reply_to_post_number: 1,
|
|
post_type: Post.types[:whisper],
|
|
raw: 'this is a whispered reply'
|
|
).create
|
|
|
|
user_stat = editor.user_stat
|
|
|
|
expect {
|
|
PostOwnerChanger.new(
|
|
post_ids: [whisper.id],
|
|
topic_id: topic.id,
|
|
new_owner: Fabricate(:admin),
|
|
acting_user: editor
|
|
).change_owner!
|
|
}.to_not change { user_stat.reload.post_count }
|
|
end
|
|
|
|
context 'private message topic' do
|
|
# fab!(:topic) { Fabricate(:private_message_topic) }
|
|
let(:pm) do
|
|
create_post(
|
|
archetype: 'private_message',
|
|
target_usernames: [p2user.username]
|
|
)
|
|
end
|
|
let(:pm_poster) { pm.user }
|
|
|
|
it "should update users' counts" do
|
|
PostActionCreator.like(p2user, pm)
|
|
|
|
expect {
|
|
PostOwnerChanger.new(
|
|
post_ids: [pm.id],
|
|
topic_id: pm.topic_id,
|
|
new_owner: user_a,
|
|
acting_user: editor
|
|
).change_owner!
|
|
}.to_not change { pm_poster.user_stat.post_count }
|
|
|
|
expect(pm_poster.user_stat.likes_received).to eq(0)
|
|
|
|
user_a_stat = user_a.user_stat
|
|
expect(user_a_stat.first_post_created_at).to be_present
|
|
expect(user_a_stat.likes_received).to eq(0)
|
|
expect(user_a_stat.post_count).to eq(0)
|
|
end
|
|
end
|
|
|
|
it "updates UserAction records" do
|
|
g = Guardian.new(editor)
|
|
expect(UserAction.stats(user_a.id, g)).to eq([])
|
|
|
|
change_owners
|
|
|
|
expect(UserAction.stats(p1user.id, g)).to eq([])
|
|
expect(UserAction.stats(p2user.id, g)).to eq([])
|
|
stats = UserAction.stats(user_a.id, g)
|
|
expect(stats.size).to eq(2)
|
|
expect(stats[0].action_type).to eq(UserAction::NEW_TOPIC)
|
|
expect(stats[0].count).to eq(1)
|
|
expect(stats[1].action_type).to eq(UserAction::REPLY)
|
|
expect(stats[1].count).to eq(1)
|
|
end
|
|
end
|
|
end
|
|
end
|