mirror of
https://github.com/discourse/discourse.git
synced 2025-01-31 15:48:28 +08:00
5bd55acf83
Ensures that `UserStat#post_count` and `UserStat#topic_count` does not go below 0. When it does like it did now, we tend to have bugs in our code since we're usually coding with the assumption that the count isn't negative. In order to support the constraints, our post and topic fabricators in tests will now automatically increment the count for the respective user's `UserStat` as well. We have to do this because our fabricators bypasss `PostCreator` which holds the responsibility of updating `UserStat#post_count` and `UserStat#topic_count`.
252 lines
8.6 KiB
Ruby
252 lines
8.6 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: 0,
|
|
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(1)
|
|
|
|
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
|
|
|
|
it "updates reply_to_user_id" do
|
|
p4 = Fabricate(:post, topic: topic, reply_to_post_number: p1.post_number, reply_to_user_id: p1.user_id)
|
|
p5 = Fabricate(:post, topic: topic, reply_to_post_number: p2.post_number, reply_to_user_id: p2.user_id)
|
|
|
|
PostOwnerChanger.new(post_ids: [p1.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
|
|
p4.reload; p5.reload
|
|
|
|
expect(p4.reply_to_user_id).to eq(user_a.id)
|
|
expect(p5.reply_to_user_id).to eq(p2.user_id)
|
|
end
|
|
end
|
|
end
|
|
end
|