# frozen_string_literal: true RSpec.describe TopicConverter do describe "convert_to_public_topic" do fab!(:admin) fab!(:author) { Fabricate(:user) } fab!(:category) { Fabricate(:category, topic_count: 1) } fab!(:private_message) { Fabricate(:private_message_topic, user: author) } # creates a topic without a first post let(:first_post) do create_post(user: author, topic: private_message, allow_uncategorized_topics: false) end let(:other_user) { private_message.topic_allowed_users.find { |u| u.user != author }.user } let(:uncategorized_category) { Category.find(SiteSetting.uncategorized_category_id) } context "with success" do it "converts private message to regular topic" do SiteSetting.allow_uncategorized_topics = true topic = nil _pm_post_2 = Fabricate(:post, topic: private_message, user: author) _pm_post_3 = Fabricate(:post, topic: private_message, user: author) other_pm = Fabricate(:private_message_post).topic other_pm_post = Fabricate(:private_message_post, topic: other_pm) other_pm_post_2 = Fabricate(:private_message_post, topic: other_pm, user: other_pm_post.user) expect do topic = TopicConverter.new(first_post.topic, admin).convert_to_public_topic topic.reload end.to change { uncategorized_category.reload.topic_count }.by(1).and change { author.reload.topic_count }.from(0).to(1).and change { author.reload.post_count }.from(0).to(2) # Ensure query does not affect users from other topics or posts as DB query to update count is quite complex. expect(other_pm.user.topic_count).to eq(0) expect(other_pm.user.post_count).to eq(0) expect(other_pm_post.user.topic_count).to eq(0) expect(other_pm_post.user.post_count).to eq(0) expect(topic).to be_valid expect(topic.archetype).to eq("regular") expect(topic.category_id).to eq(SiteSetting.uncategorized_category_id) end context "when uncategorized category is not allowed" do before do SiteSetting.allow_uncategorized_topics = false category.update!(read_restricted: false) end it "should convert private message into the right category" do topic = TopicConverter.new(first_post.topic, admin).convert_to_public_topic topic.reload expect(topic).to be_valid expect(topic.archetype).to eq("regular") first_category = Category .where.not(id: SiteSetting.uncategorized_category_id) .where(read_restricted: false) .order("id asc") .first expect(topic.category_id).to eq(first_category.id) expect(topic.category.topic_count).to eq(2) end end context "when a custom category_id is given" do it "should convert private message into the right category" do topic = TopicConverter.new(first_post.topic, admin).convert_to_public_topic(category.id) expect(topic.reload.category).to eq(category) expect(topic.category.topic_count).to eq(2) end end it "updates user stats" do first_post topic_user = TopicUser.find_by(user_id: author.id, topic_id: private_message.id) expect(private_message.user.user_stat.topic_count).to eq(0) expect(private_message.user.user_stat.post_count).to eq(0) private_message.convert_to_public_topic(admin) expect(private_message.reload.user.user_stat.topic_count).to eq(1) expect(private_message.user.user_stat.post_count).to eq(0) expect(topic_user.reload.notification_level).to eq(TopicUser.notification_levels[:watching]) end context "with a reply" do before do Jobs.run_immediately! UserActionManager.enable first_post create_post(topic: private_message, user: other_user) private_message.reload end it "updates UserActions" do TopicConverter.new(private_message, admin).convert_to_public_topic expect( author.user_actions.where(action_type: UserAction::NEW_PRIVATE_MESSAGE).count, ).to eq(0) expect(author.user_actions.where(action_type: UserAction::NEW_TOPIC).count).to eq(1) expect( other_user.user_actions.where(action_type: UserAction::NEW_PRIVATE_MESSAGE).count, ).to eq(0) expect( other_user.user_actions.where(action_type: UserAction::GOT_PRIVATE_MESSAGE).count, ).to eq(0) expect(other_user.user_actions.where(action_type: UserAction::REPLY).count).to eq(1) end end it "deletes notifications for users not allowed to see the topic" do staff_category = Fabricate(:private_category, group: Group[:staff]) user_notification = Fabricate(:mentioned_notification, post: first_post, user: Fabricate(:user)) admin_notification = Fabricate(:mentioned_notification, post: first_post, user: Fabricate(:admin)) Jobs.run_immediately! TopicConverter.new(first_post.topic, admin).convert_to_public_topic(staff_category.id) expect(Notification.exists?(user_notification.id)).to eq(false) expect(Notification.exists?(admin_notification.id)).to eq(true) end end end describe "convert_to_private_message" do fab!(:admin) fab!(:author) { Fabricate(:user) } fab!(:category) fab!(:topic) { Fabricate(:topic, user: author, category_id: category.id) } fab!(:post) { Fabricate(:post, topic: topic, user: topic.user) } context "with success" do it "converts regular topic to private message" do private_message = topic.convert_to_private_message(post.user) expect(private_message).to be_valid expect(topic.archetype).to eq("private_message") expect(topic.category_id).to eq(nil) expect(category.reload.topic_count).to eq(0) end it "converts unlisted topic to private message" do topic.update_status("visible", false, admin) private_message = topic.convert_to_private_message(post.user) expect(private_message).to be_valid expect(topic.archetype).to eq("private_message") expect(topic.category_id).to eq(nil) expect(topic.user.post_count).to eq(0) expect(topic.user.topic_count).to eq(0) expect(category.reload.topic_count).to eq(0) end it "updates user stats when converting topic to private message" do _post_2 = Fabricate(:post, topic: topic, user: author) _post_3 = Fabricate(:post, topic: topic, user: author) other_topic = Fabricate(:post).topic other_post = Fabricate(:post, topic: other_topic) topic_user = TopicUser.create!(user_id: author.id, topic_id: topic.id, posted: true) expect do topic.convert_to_private_message(admin) end.to change { author.reload.post_count }.from(2).to(0).and change { author.reload.topic_count }.from(1).to(0) # Ensure query does not affect users from other topics or posts as DB query to update count is quite complex. expect(other_topic.user.post_count).to eq(0) expect(other_topic.user.topic_count).to eq(1) expect(other_post.user.post_count).to eq(1) expect(other_post.user.topic_count).to eq(0) expect(topic.reload.topic_allowed_users.where(user_id: author.id).count).to eq(1) expect(topic_user.reload.notification_level).to eq(TopicUser.notification_levels[:watching]) end it "invites only users with regular posts" do post2 = Fabricate(:post, topic: topic) Fabricate(:post, topic: topic, post_type: Post.types[:whisper]) Fabricate(:post, topic: topic, post_type: Post.types[:small_action]) topic.convert_to_private_message(admin) expect(topic.reload.topic_allowed_users.pluck(:user_id)).to contain_exactly( admin.id, post.user_id, post2.user_id, ) end it "changes user_action type" do Jobs.run_immediately! UserActionManager.enable topic.convert_to_private_message(admin) expect(author.user_actions.where(action_type: UserAction::NEW_TOPIC).count).to eq(0) expect(author.user_actions.where(action_type: UserAction::NEW_PRIVATE_MESSAGE).count).to eq( 1, ) end it "deletes notifications for users not allowed to see the message" do user_notification = Fabricate(:mentioned_notification, post: post, user: Fabricate(:user)) admin_notification = Fabricate(:mentioned_notification, post: post, user: Fabricate(:admin)) Jobs.run_immediately! topic.convert_to_private_message(admin) expect(Notification.exists?(user_notification.id)).to eq(false) expect(Notification.exists?(admin_notification.id)).to eq(true) end it "limits PM participants" do SiteSetting.max_allowed_message_recipients = 2 Fabricate(:post, topic: topic) Fabricate(:post, topic: topic) private_message = topic.convert_to_private_message(post.user) # Skips posters and just adds the acting user expect(private_message.topic_allowed_users.count).to eq(1) end it "includes the poster of a single-post topic" do moderator = Fabricate(:moderator) private_message = topic.convert_to_private_message(moderator) expect(private_message.allowed_users).to match_array([topic.user, moderator]) end end context "when topic has replies" do before do @replied_user = Fabricate(:coding_horror) create_post(topic: topic, user: @replied_user) topic.reload end it "adds users who replied to topic in Private Message" do topic.convert_to_private_message(admin) expect(topic.reload.topic_allowed_users.where(user_id: @replied_user.id).count).to eq(1) expect(topic.reload.user.user_stat.post_count).to eq(0) end end context "when user already exists in topic_allowed_users table" do before { topic.topic_allowed_users.create!(user_id: admin.id) } it "works" do topic.convert_to_private_message(admin) expect(topic.reload.archetype).to eq("private_message") end end context "with user_profiles with newly converted PM as featured topic" do it "sets all matching user_profile featured topic ids to nil" do author.user_profile.update(featured_topic: topic) topic.convert_to_private_message(admin) expect(author.user_profile.reload.featured_topic).to eq(nil) end end end end