2019-04-29 20:27:42 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2022-07-27 22:27:38 -04:00
|
|
|
RSpec.describe UserAction do
|
2023-11-09 17:47:59 -05:00
|
|
|
fab!(:coding_horror)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2019-01-03 12:03:01 -05:00
|
|
|
before { UserActionManager.enable }
|
2013-05-13 21:59:55 -04:00
|
|
|
|
2014-12-31 09:55:03 -05:00
|
|
|
it { is_expected.to validate_presence_of :action_type }
|
|
|
|
it { is_expected.to validate_presence_of :user_id }
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2018-05-17 23:28:13 -04:00
|
|
|
describe "#stream" do
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:public_post) { Fabricate(:post) }
|
2013-02-15 17:08:28 -05:00
|
|
|
let(:public_topic) { public_post.topic }
|
2023-11-09 17:47:59 -05:00
|
|
|
fab!(:user)
|
2013-02-15 17:08:28 -05:00
|
|
|
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:private_post) { Fabricate(:post) }
|
2013-02-25 11:42:20 -05:00
|
|
|
let(:private_topic) do
|
2013-02-15 17:08:28 -05:00
|
|
|
topic = private_post.topic
|
2014-09-11 03:39:20 -04:00
|
|
|
topic.update_columns(category_id: nil, archetype: Archetype.private_message)
|
2016-12-20 23:01:26 -05:00
|
|
|
TopicAllowedUser.create(topic_id: topic.id, user_id: user.id)
|
2013-02-15 17:08:28 -05:00
|
|
|
topic
|
|
|
|
end
|
|
|
|
|
|
|
|
def log_test_action(opts = {})
|
|
|
|
UserAction.log_action!(
|
|
|
|
{
|
2013-02-05 14:16:51 -05:00
|
|
|
action_type: UserAction::NEW_PRIVATE_MESSAGE,
|
2013-02-25 11:42:20 -05:00
|
|
|
user_id: user.id,
|
|
|
|
acting_user_id: user.id,
|
2013-02-15 17:08:28 -05:00
|
|
|
target_topic_id: private_topic.id,
|
2013-02-25 11:42:20 -05:00
|
|
|
target_post_id: private_post.id,
|
2013-02-15 17:08:28 -05:00
|
|
|
}.merge(opts),
|
|
|
|
)
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2021-05-20 02:58:27 -04:00
|
|
|
it "allows publishing when group is deleted" do
|
|
|
|
public_topic.category.update!(read_restricted: true)
|
|
|
|
|
|
|
|
m =
|
|
|
|
MessageBus.track_publish("/u/#{user.username_lower}") do
|
|
|
|
log_test_action(target_topic_id: public_topic.id, target_post_id: public_post.id)
|
2017-12-07 16:16:53 -05:00
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2021-05-20 02:58:27 -04:00
|
|
|
expect(m[0].group_ids).to eq([Group::AUTO_GROUPS[:admins]])
|
|
|
|
expect(m[0].user_ids).to eq([user.id])
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "integration" do
|
2017-12-07 16:16:53 -05:00
|
|
|
def stats_for_user(viewer = nil)
|
2018-06-20 03:48:02 -04:00
|
|
|
UserAction.stats(user.id, Guardian.new(viewer)).map { |r| r.action_type.to_i }.sort
|
2017-12-07 16:16:53 -05:00
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2018-05-17 23:28:13 -04:00
|
|
|
def stream(viewer = nil)
|
|
|
|
UserAction.stream(user_id: user.id, guardian: Guardian.new(viewer))
|
2017-12-07 16:16:53 -05:00
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
it "includes the events correctly" do
|
2021-05-20 02:58:27 -04:00
|
|
|
# Create some test data using a helper
|
|
|
|
log_test_action
|
|
|
|
log_test_action(action_type: UserAction::GOT_PRIVATE_MESSAGE)
|
|
|
|
log_test_action(
|
|
|
|
action_type: UserAction::NEW_TOPIC,
|
|
|
|
target_topic_id: public_topic.id,
|
|
|
|
target_post_id: public_post.id,
|
|
|
|
)
|
|
|
|
|
2019-05-08 03:45:25 -04:00
|
|
|
Jobs.run_immediately!
|
2017-12-07 16:16:53 -05:00
|
|
|
PostActionNotifier.enable
|
2016-12-22 00:46:22 -05:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
mystats = stats_for_user(user)
|
2022-05-09 20:42:18 -04:00
|
|
|
expecting = [
|
|
|
|
UserAction::NEW_TOPIC,
|
|
|
|
UserAction::NEW_PRIVATE_MESSAGE,
|
|
|
|
UserAction::GOT_PRIVATE_MESSAGE,
|
|
|
|
].sort
|
2017-12-07 16:16:53 -05:00
|
|
|
expect(mystats).to eq(expecting)
|
2018-05-17 23:28:13 -04:00
|
|
|
|
|
|
|
expect(stream(user).map(&:action_type)).to contain_exactly(*expecting)
|
2013-04-09 22:50:00 -04:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
other_stats = stats_for_user
|
|
|
|
expecting = [UserAction::NEW_TOPIC]
|
2018-05-17 23:28:13 -04:00
|
|
|
expect(stream.map(&:action_type)).to contain_exactly(*expecting)
|
2017-12-07 16:16:53 -05:00
|
|
|
expect(other_stats).to eq(expecting)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
public_topic.trash!(user)
|
|
|
|
expect(stats_for_user).to eq([])
|
2018-05-17 23:28:13 -04:00
|
|
|
expect(stream).to eq([])
|
2013-02-25 11:42:20 -05:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
# groups
|
|
|
|
category = Fabricate(:category, read_restricted: true)
|
2013-04-29 02:33:24 -04:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
public_topic.recover!
|
2018-05-17 23:28:13 -04:00
|
|
|
public_topic.update!(category: category)
|
2013-04-29 02:33:24 -04:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
expect(stats_for_user).to eq([])
|
2018-05-17 23:28:13 -04:00
|
|
|
expect(stream).to eq([])
|
2013-04-29 02:33:24 -04:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
group = Fabricate(:group)
|
2021-12-15 12:41:14 -05:00
|
|
|
u = coding_horror
|
2017-12-07 16:16:53 -05:00
|
|
|
group.add(u)
|
2013-04-29 02:33:24 -04:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
category.set_permissions(group => :full)
|
2018-05-17 23:28:13 -04:00
|
|
|
category.save!
|
2013-04-29 02:33:24 -04:00
|
|
|
|
2018-05-17 23:28:13 -04:00
|
|
|
expecting = [UserAction::NEW_TOPIC]
|
|
|
|
expect(stats_for_user(u)).to eq(expecting)
|
|
|
|
expect(stream(u).map(&:action_type)).to contain_exactly(*expecting)
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
# duplicate should not exception out
|
|
|
|
log_test_action
|
2013-07-22 19:48:18 -04:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
# recategorize belongs to the right user
|
|
|
|
category2 = Fabricate(:category)
|
|
|
|
admin = Fabricate(:admin)
|
|
|
|
public_post.revise(admin, category_id: category2.id)
|
2014-10-07 00:57:48 -04:00
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
action = UserAction.stream(user_id: public_topic.user_id, guardian: Guardian.new)[0]
|
|
|
|
expect(action.acting_user_id).to eq(admin.id)
|
|
|
|
expect(action.action_type).to eq(UserAction::EDIT)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-05-17 23:28:13 -04:00
|
|
|
describe "assignments" do
|
2024-02-15 19:24:39 -05:00
|
|
|
let(:stream) { UserAction.stream(user_id: user.id, guardian: user.guardian) }
|
2018-05-17 23:28:13 -04:00
|
|
|
|
|
|
|
before do
|
|
|
|
log_test_action(action_type: UserAction::ASSIGNED)
|
|
|
|
private_post.custom_fields ||= {}
|
|
|
|
private_post.custom_fields["action_code_who"] = "testing"
|
2022-10-13 05:10:18 -04:00
|
|
|
private_post.custom_fields["action_code_path"] = "/p/1234"
|
2018-05-17 23:28:13 -04:00
|
|
|
private_post.custom_fields["random_field"] = "random_value"
|
|
|
|
private_post.save!
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should include the right attributes in the stream" do
|
|
|
|
expect(stream.count).to eq(1)
|
|
|
|
|
|
|
|
user_action_row = stream.first
|
|
|
|
|
|
|
|
expect(user_action_row.action_type).to eq(UserAction::ASSIGNED)
|
|
|
|
expect(user_action_row.action_code_who).to eq("testing")
|
2022-10-13 05:10:18 -04:00
|
|
|
expect(user_action_row.action_code_path).to eq("/p/1234")
|
2018-05-17 23:28:13 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-12-07 16:16:53 -05:00
|
|
|
describe "mentions" do
|
|
|
|
before { log_test_action(action_type: UserAction::MENTION) }
|
|
|
|
|
2024-02-15 19:24:39 -05:00
|
|
|
let(:stream) { UserAction.stream(user_id: user.id, guardian: user.guardian) }
|
2017-12-07 16:16:53 -05:00
|
|
|
|
|
|
|
it "is returned by the stream" do
|
2018-05-17 23:28:13 -04:00
|
|
|
expect(stream.count).to eq(1)
|
|
|
|
expect(stream.first.action_type).to eq(UserAction::MENTION)
|
2017-12-07 16:16:53 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "isn't returned when mentions aren't enabled" do
|
|
|
|
SiteSetting.enable_mentions = false
|
|
|
|
expect(stream).to be_blank
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
2024-02-15 19:24:39 -05:00
|
|
|
|
|
|
|
describe "when a plugin registers the :user_action_stream_builder modifier" do
|
|
|
|
before do
|
|
|
|
log_test_action(action_type: UserAction::LIKE)
|
|
|
|
log_test_action(action_type: UserAction::WAS_LIKED)
|
|
|
|
end
|
|
|
|
|
|
|
|
after { DiscoursePluginRegistry.clear_modifiers! }
|
|
|
|
|
|
|
|
it "allows the plugin to modify the builder query" do
|
|
|
|
Plugin::Instance
|
|
|
|
.new
|
|
|
|
.register_modifier(:user_action_stream_builder) do |builder|
|
|
|
|
expect(builder).to be_a(MiniSqlMultisiteConnection::CustomBuilder)
|
|
|
|
builder.limit(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
stream = UserAction.stream(user_id: user.id, guardian: user.guardian)
|
|
|
|
|
|
|
|
expect(stream.count).to eq(1)
|
|
|
|
|
|
|
|
DiscoursePluginRegistry.clear_modifiers!
|
|
|
|
|
|
|
|
stream = UserAction.stream(user_id: user.id, guardian: user.guardian)
|
|
|
|
expect(stream.count).to eq(2)
|
|
|
|
end
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
describe "when user likes" do
|
2023-11-09 17:47:59 -05:00
|
|
|
fab!(:post)
|
2013-02-15 17:08:28 -05:00
|
|
|
let(:likee) { post.user }
|
2021-12-15 12:41:14 -05:00
|
|
|
fab!(:liker) { coding_horror }
|
2013-02-15 17:08:28 -05:00
|
|
|
|
|
|
|
def likee_stream
|
|
|
|
UserAction.stream(user_id: likee.id, guardian: Guardian.new)
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2013-02-15 17:08:28 -05:00
|
|
|
before { @old_count = likee_stream.count }
|
2013-02-05 14:16:51 -05:00
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
it "creates a new stream entry" do
|
2019-01-03 12:03:01 -05:00
|
|
|
PostActionCreator.like(liker, post)
|
2014-12-31 09:55:03 -05:00
|
|
|
expect(likee_stream.count).to eq(@old_count + 1)
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
2013-02-15 17:08:28 -05:00
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
context "with successful like" do
|
2013-02-25 11:42:20 -05:00
|
|
|
before do
|
2019-01-03 12:03:01 -05:00
|
|
|
PostActionCreator.like(liker, post)
|
2014-05-06 09:41:59 -04:00
|
|
|
@liker_action = liker.user_actions.find_by(action_type: UserAction::LIKE)
|
|
|
|
@likee_action = likee.user_actions.find_by(action_type: UserAction::WAS_LIKED)
|
2013-02-15 17:08:28 -05:00
|
|
|
end
|
|
|
|
|
2013-04-05 00:29:46 -04:00
|
|
|
it "should result in correct data assignment" do
|
2014-12-31 09:55:03 -05:00
|
|
|
expect(@liker_action).not_to eq(nil)
|
|
|
|
expect(@likee_action).not_to eq(nil)
|
|
|
|
expect(likee.user_stat.reload.likes_received).to eq(1)
|
|
|
|
expect(liker.user_stat.reload.likes_given).to eq(1)
|
2013-04-05 00:29:46 -04:00
|
|
|
|
2019-01-03 12:03:01 -05:00
|
|
|
PostActionDestroyer.destroy(liker, post, :like)
|
2014-12-31 09:55:03 -05:00
|
|
|
expect(likee.user_stat.reload.likes_received).to eq(0)
|
|
|
|
expect(liker.user_stat.reload.likes_given).to eq(0)
|
2013-02-15 17:08:28 -05:00
|
|
|
end
|
2013-04-05 00:29:46 -04:00
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
context "with private message" do
|
2019-05-06 23:12:20 -04:00
|
|
|
fab!(:post) { Fabricate(:private_message_post) }
|
2017-01-15 21:18:10 -05:00
|
|
|
let(:likee) { post.topic.topic_allowed_users.first.user }
|
|
|
|
let(:liker) { post.topic.topic_allowed_users.last.user }
|
|
|
|
|
|
|
|
it "should not increase user stats" do
|
|
|
|
expect(@liker_action).not_to eq(nil)
|
|
|
|
expect(liker.user_stat.reload.likes_given).to eq(0)
|
|
|
|
expect(@likee_action).not_to eq(nil)
|
|
|
|
expect(likee.user_stat.reload.likes_received).to eq(0)
|
|
|
|
|
2019-01-03 12:03:01 -05:00
|
|
|
PostActionDestroyer.destroy(liker, post, :like)
|
2017-01-15 21:18:10 -05:00
|
|
|
expect(liker.user_stat.reload.likes_given).to eq(0)
|
|
|
|
expect(likee.user_stat.reload.likes_received).to eq(0)
|
|
|
|
end
|
|
|
|
end
|
2013-02-15 17:08:28 -05:00
|
|
|
end
|
|
|
|
|
2022-07-27 12:14:14 -04:00
|
|
|
context "when liking a private message" do
|
2014-09-11 03:39:20 -04:00
|
|
|
before { post.topic.update_columns(category_id: nil, archetype: Archetype.private_message) }
|
2013-02-15 17:08:28 -05:00
|
|
|
|
|
|
|
it "doesn't add the entry to the stream" do
|
2019-01-03 12:03:01 -05:00
|
|
|
PostActionCreator.like(liker, post)
|
2014-12-31 09:55:03 -05:00
|
|
|
expect(likee_stream.count).not_to eq(@old_count + 1)
|
2013-02-15 17:08:28 -05:00
|
|
|
end
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
describe "when a user posts a new topic" do
|
2013-02-25 11:42:20 -05:00
|
|
|
before do
|
2020-03-10 17:13:17 -04:00
|
|
|
freeze_time(100.days.ago) do
|
|
|
|
@post = create_post
|
|
|
|
PostAlerter.post_created(@post)
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
describe "topic action" do
|
|
|
|
it "should exist" do
|
2020-03-10 17:13:17 -04:00
|
|
|
@action = @post.user.user_actions.find_by(action_type: UserAction::NEW_TOPIC)
|
|
|
|
|
2014-12-31 09:55:03 -05:00
|
|
|
expect(@action).not_to eq(nil)
|
2020-03-10 17:13:17 -04:00
|
|
|
expect(@action.created_at).to eq_time(@post.topic.created_at)
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
it "should not log a post user action" do
|
2014-12-31 09:55:03 -05:00
|
|
|
expect(@post.user.user_actions.find_by(action_type: UserAction::REPLY)).to eq(nil)
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2013-02-25 11:42:20 -05:00
|
|
|
describe "when another user posts on the topic" do
|
|
|
|
before do
|
2021-12-15 12:41:14 -05:00
|
|
|
@other_user = coding_horror
|
2013-02-05 14:16:51 -05:00
|
|
|
@mentioned = Fabricate(:admin)
|
2019-01-03 12:03:01 -05:00
|
|
|
|
|
|
|
@response =
|
|
|
|
PostCreator.new(
|
|
|
|
@other_user,
|
|
|
|
reply_to_post_number: 1,
|
|
|
|
topic_id: @post.topic_id,
|
|
|
|
raw: "perhaps @#{@mentioned.username} knows how this works?",
|
|
|
|
).create
|
2014-03-18 00:22:39 -04:00
|
|
|
|
2020-03-10 17:13:17 -04:00
|
|
|
PostAlerter.post_created(@response)
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
2013-02-25 11:42:20 -05:00
|
|
|
|
2013-04-29 02:33:24 -04:00
|
|
|
it "should log user actions correctly" do
|
2014-12-31 09:55:03 -05:00
|
|
|
expect(@response.user.user_actions.find_by(action_type: UserAction::REPLY)).not_to eq(nil)
|
|
|
|
expect(@post.user.user_actions.find_by(action_type: UserAction::RESPONSE)).not_to eq(nil)
|
|
|
|
expect(@mentioned.user_actions.find_by(action_type: UserAction::MENTION)).not_to eq(nil)
|
|
|
|
expect(
|
|
|
|
@post.user.user_actions.joins(:target_post).where("posts.post_number = 2").count,
|
|
|
|
).to eq(1)
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "should not log a double notification for a post edit" do
|
|
|
|
@response.raw = "here it goes again"
|
2013-02-25 11:42:20 -05:00
|
|
|
@response.save!
|
2014-12-31 09:55:03 -05:00
|
|
|
expect(@response.user.user_actions.where(action_type: UserAction::REPLY).count).to eq(1)
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-08-01 19:59:12 -04:00
|
|
|
describe "synchronize_target_topic_ids" do
|
2013-07-17 02:40:15 -04:00
|
|
|
it "correct target_topic_id" do
|
|
|
|
post = Fabricate(:post)
|
|
|
|
|
|
|
|
action =
|
|
|
|
UserAction.log_action!(
|
|
|
|
action_type: UserAction::NEW_PRIVATE_MESSAGE,
|
|
|
|
user_id: post.user.id,
|
|
|
|
acting_user_id: post.user.id,
|
|
|
|
target_topic_id: -1,
|
|
|
|
target_post_id: post.id,
|
|
|
|
)
|
|
|
|
|
2013-07-22 22:43:34 -04:00
|
|
|
UserAction.log_action!(
|
|
|
|
action_type: UserAction::NEW_PRIVATE_MESSAGE,
|
|
|
|
user_id: post.user.id,
|
|
|
|
acting_user_id: post.user.id,
|
|
|
|
target_topic_id: -2,
|
|
|
|
target_post_id: post.id,
|
|
|
|
)
|
2013-07-17 02:40:15 -04:00
|
|
|
|
2013-08-01 19:59:12 -04:00
|
|
|
UserAction.synchronize_target_topic_ids
|
2013-07-22 22:43:34 -04:00
|
|
|
|
2013-07-17 02:40:15 -04:00
|
|
|
action.reload
|
2014-12-31 09:55:03 -05:00
|
|
|
expect(action.target_topic_id).to eq(post.topic_id)
|
2013-07-17 02:40:15 -04:00
|
|
|
end
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|