discourse/spec/models/private_message_topic_tracking_state_spec.rb
Alan Guo Xiang Tan f66007ec83
FEATURE: Display unread and new counts for messages. (#14059)
There are certain design decisions that were made in this commit.

Private messages implements its own version of topic tracking state because there are significant differences between regular and private_message topics. Regular topics have to track categories and tags while private messages do not. It is much easier to design the new topic tracking state if we maintain two different classes, instead of trying to mash this two worlds together.

One MessageBus channel per user and one MessageBus channel per group. This allows each user and each group to have their own channel backlog instead of having one global channel which requires the client to filter away unrelated messages.
2021-08-25 11:17:56 +08:00

207 lines
6.2 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
describe PrivateMessageTopicTrackingState do
fab!(:user) { Fabricate(:user) }
fab!(:user_2) { Fabricate(:user) }
fab!(:group) do
Fabricate(:group, messageable_level: Group::ALIAS_LEVELS[:everyone]).tap do |g|
g.add(user_2)
end
end
fab!(:group_message) do
create_post(
user: user,
target_group_names: [group.name],
archetype: Archetype.private_message
).topic
end
fab!(:private_message) do
create_post(
user: user,
target_usernames: [user_2.username],
archetype: Archetype.private_message
).topic
end
fab!(:private_message_2) do
create_post(
user: user,
target_usernames: [Fabricate(:user).username],
archetype: Archetype.private_message
).topic
end
describe '.report' do
it 'returns the right tracking state' do
TopicUser.find_by(user: user_2, topic: group_message).update!(
last_read_post_number: 1
)
expect(described_class.report(user_2).map(&:topic_id))
.to contain_exactly(private_message.id)
create_post(user: user, topic: group_message)
report = described_class.report(user_2)
expect(report.map(&:topic_id)).to contain_exactly(
group_message.id,
private_message.id
)
state = report.first
expect(state.topic_id).to eq(private_message.id)
expect(state.user_id).to eq(user_2.id)
expect(state.last_read_post_number).to eq(nil)
expect(state.notification_level).to eq(NotificationLevels.all[:watching])
expect(state.highest_post_number).to eq(1)
expect(state.group_ids).to eq([])
expect(report.last.group_ids).to contain_exactly(group.id)
end
it 'returns the right tracking state when topics contain whispers' do
TopicUser.find_by(user: user_2, topic: private_message).update!(
last_read_post_number: 1
)
create_post(
raw: "this is a test post",
topic: private_message,
post_type: Post.types[:whisper],
user: Fabricate(:admin)
)
expect(described_class.report(user_2).map(&:topic_id))
.to contain_exactly(group_message.id)
user_2.grant_admin!
tracking_state = described_class.report(user_2)
expect(tracking_state.map { |topic| [topic.topic_id, topic.highest_post_number] })
.to contain_exactly(
[group_message.id, 1],
[private_message.id, 2]
)
end
it 'returns the right tracking state when topics have been dismissed' do
DismissedTopicUser.create!(
user_id: user_2.id,
topic_id: group_message.id
)
expect(described_class.report(user_2).map(&:topic_id))
.to contain_exactly(private_message.id)
end
end
describe '.publish_new' do
it 'should publish the right message_bus message' do
messages = MessageBus.track_publish do
described_class.publish_new(private_message)
end
expect(messages.map(&:channel)).to contain_exactly(
described_class.user_channel(user.id),
described_class.user_channel(user_2.id)
)
data = messages.find do |message|
message.channel == described_class.user_channel(user.id)
end.data
expect(data['message_type']).to eq(described_class::NEW_MESSAGE_TYPE)
end
it 'should publish the right message_bus message for a group message' do
messages = MessageBus.track_publish do
described_class.publish_new(group_message)
end
expect(messages.map(&:channel)).to contain_exactly(
described_class.group_channel(group.id),
described_class.user_channel(user.id)
)
data = messages.find do |message|
message.channel == described_class.group_channel(group.id)
end.data
expect(data['message_type']).to eq(described_class::NEW_MESSAGE_TYPE)
expect(data['topic_id']).to eq(group_message.id)
expect(data['payload']['last_read_post_number']).to eq(nil)
expect(data['payload']['highest_post_number']).to eq(1)
expect(data['payload']['group_ids']).to eq([group.id])
end
end
describe '.publish_unread' do
it 'should publish the right message_bus message' do
messages = MessageBus.track_publish do
described_class.publish_unread(private_message.first_post)
end
expect(messages.map(&:channel)).to contain_exactly(
described_class.user_channel(user.id),
described_class.user_channel(user_2.id)
)
data = messages.find do |message|
message.channel == described_class.user_channel(user.id)
end.data
expect(data['message_type']).to eq(described_class::UNREAD_MESSAGE_TYPE)
expect(data['topic_id']).to eq(private_message.id)
expect(data['payload']['last_read_post_number']).to eq(1)
expect(data['payload']['highest_post_number']).to eq(1)
expect(data['payload']['notification_level'])
.to eq(NotificationLevels.all[:watching])
expect(data['payload']['group_ids']).to eq([])
end
end
describe '.publish_user_archived' do
it 'should publish the right message_bus message' do
message = MessageBus.track_publish(described_class.user_channel(user.id)) do
described_class.publish_user_archived(private_message, user.id)
end.first
data = message.data
expect(data['topic_id']).to eq(private_message.id)
expect(data['message_type']).to eq(described_class::ARCHIVE_MESSAGE_TYPE)
end
end
describe '.publish_group_archived' do
it 'should publish the right message_bus message' do
user_3 = Fabricate(:user)
group.add(user_3)
messages = MessageBus.track_publish do
described_class.publish_group_archived(group_message, group.id)
end
expect(messages.map(&:channel)).to contain_exactly(
described_class.group_channel(group.id)
)
data = messages.find do |message|
message.channel == described_class.group_channel(group.id)
end.data
expect(data['message_type']).to eq(described_class::GROUP_ARCHIVE_MESSAGE_TYPE)
expect(data['topic_id']).to eq(group_message.id)
expect(data['payload']['group_ids']).to contain_exactly(group.id)
end
end
end