2014-01-02 09:00:08 +08:00
|
|
|
# encoding: utf-8
|
2019-04-30 08:27:42 +08:00
|
|
|
# frozen_string_literal: true
|
2014-01-02 09:00:08 +08:00
|
|
|
|
2022-07-28 10:27:38 +08:00
|
|
|
RSpec.describe CategoryUser do
|
2019-06-25 10:13:27 +08:00
|
|
|
fab!(:user) { Fabricate(:user) }
|
2014-01-02 14:58:49 +08:00
|
|
|
|
2016-07-08 10:58:18 +08:00
|
|
|
def tracking
|
|
|
|
CategoryUser.notification_levels[:tracking]
|
|
|
|
end
|
|
|
|
|
|
|
|
def regular
|
|
|
|
CategoryUser.notification_levels[:regular]
|
|
|
|
end
|
|
|
|
|
2022-07-27 18:21:10 +08:00
|
|
|
describe '#batch_set' do
|
2019-06-25 10:13:27 +08:00
|
|
|
fab!(:category) { Fabricate(:category) }
|
2014-01-02 14:58:49 +08:00
|
|
|
|
2019-06-25 10:13:27 +08:00
|
|
|
def category_ids_at_level(level)
|
|
|
|
CategoryUser.where(
|
|
|
|
user_id: user.id,
|
|
|
|
notification_level: CategoryUser.notification_levels[level]
|
|
|
|
).pluck(:category_id)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should add new records where required" do
|
|
|
|
CategoryUser.batch_set(user, :watching, [category.id])
|
|
|
|
|
|
|
|
expect(category_ids_at_level(:watching)).to eq([category.id])
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should change existing records where required" do
|
|
|
|
CategoryUser.create!(
|
|
|
|
user_id: user.id,
|
|
|
|
category_id: category.id,
|
|
|
|
notification_level: CategoryUser.notification_levels[:muted]
|
|
|
|
)
|
|
|
|
|
|
|
|
CategoryUser.batch_set(user, :watching, [category.id])
|
|
|
|
|
|
|
|
expect(category_ids_at_level(:watching)).to eq([category.id])
|
|
|
|
expect(category_ids_at_level(:muted)).to eq([])
|
|
|
|
end
|
2014-01-02 14:58:49 +08:00
|
|
|
|
2019-06-25 10:13:27 +08:00
|
|
|
it "should delete extraneous records where required" do
|
|
|
|
CategoryUser.create!(
|
|
|
|
user_id: user.id,
|
|
|
|
category_id: category.id,
|
|
|
|
notification_level: CategoryUser.notification_levels[:watching]
|
|
|
|
)
|
2014-01-02 14:58:49 +08:00
|
|
|
|
2019-06-25 10:13:27 +08:00
|
|
|
CategoryUser.batch_set(user, :watching, [])
|
2014-01-02 14:58:49 +08:00
|
|
|
|
2019-06-25 10:13:27 +08:00
|
|
|
expect(category_ids_at_level(:watching)).to eq([])
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should return true when something changed" do
|
|
|
|
expect(CategoryUser.batch_set(user, :watching, [category.id])).to eq(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should return false when nothing changed" do
|
|
|
|
CategoryUser.batch_set(user, :watching, [category.id])
|
|
|
|
|
|
|
|
expect(CategoryUser.batch_set(user, :watching, [category.id])).to eq(false)
|
|
|
|
end
|
2014-01-02 14:58:49 +08:00
|
|
|
end
|
|
|
|
|
2016-07-08 10:58:18 +08:00
|
|
|
it 'should correctly auto_track' do
|
|
|
|
tracking_user = Fabricate(:user)
|
|
|
|
topic = Fabricate(:post).topic
|
|
|
|
|
|
|
|
TopicUser.change(user.id, topic.id, total_msecs_viewed: 10)
|
|
|
|
TopicUser.change(tracking_user.id, topic.id, total_msecs_viewed: 10)
|
|
|
|
|
|
|
|
CategoryUser.create!(user: tracking_user, category: topic.category, notification_level: tracking)
|
|
|
|
CategoryUser.auto_track(user_id: tracking_user.id)
|
|
|
|
|
|
|
|
expect(TopicUser.get(topic, tracking_user).notification_level).to eq(tracking)
|
|
|
|
expect(TopicUser.get(topic, user).notification_level).to eq(regular)
|
|
|
|
end
|
|
|
|
|
2016-08-02 23:22:02 +08:00
|
|
|
it 'allows updating notification level' do
|
|
|
|
category = Fabricate(:category)
|
|
|
|
|
|
|
|
CategoryUser.set_notification_level_for_category(user,
|
|
|
|
NotificationLevels.all[:watching_first_post],
|
|
|
|
category.id)
|
|
|
|
|
|
|
|
expect(CategoryUser.where(user_id: user.id,
|
|
|
|
category_id: category.id,
|
|
|
|
notification_level: NotificationLevels.all[:watching_first_post]).exists?).to eq(true)
|
|
|
|
|
|
|
|
CategoryUser.set_notification_level_for_category(user,
|
|
|
|
NotificationLevels.all[:regular],
|
|
|
|
category.id)
|
|
|
|
|
|
|
|
expect(CategoryUser.where(user_id: user.id,
|
|
|
|
category_id: category.id,
|
|
|
|
notification_level: NotificationLevels.all[:regular]).exists?).to eq(true)
|
|
|
|
end
|
2014-01-02 14:58:49 +08:00
|
|
|
|
2022-07-28 00:14:14 +08:00
|
|
|
describe 'integration' do
|
2014-01-02 09:00:08 +08:00
|
|
|
before do
|
2019-03-14 22:47:38 +08:00
|
|
|
Jobs.run_immediately!
|
2016-12-22 12:29:34 +08:00
|
|
|
NotificationEmailer.enable
|
2014-01-02 09:00:08 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'should operate correctly' do
|
|
|
|
watched_category = Fabricate(:category)
|
|
|
|
muted_category = Fabricate(:category)
|
2014-06-02 11:55:01 +08:00
|
|
|
tracked_category = Fabricate(:category)
|
|
|
|
|
2016-07-08 10:58:18 +08:00
|
|
|
early_watched_post = create_post(category: watched_category)
|
|
|
|
|
2014-01-02 09:00:08 +08:00
|
|
|
CategoryUser.create!(user: user, category: watched_category, notification_level: CategoryUser.notification_levels[:watching])
|
|
|
|
CategoryUser.create!(user: user, category: muted_category, notification_level: CategoryUser.notification_levels[:muted])
|
2014-06-02 11:55:01 +08:00
|
|
|
CategoryUser.create!(user: user, category: tracked_category, notification_level: CategoryUser.notification_levels[:tracking])
|
2014-01-02 09:00:08 +08:00
|
|
|
|
|
|
|
watched_post = create_post(category: watched_category)
|
2015-11-30 14:03:47 +08:00
|
|
|
_muted_post = create_post(category: muted_category)
|
2014-06-02 11:55:01 +08:00
|
|
|
tracked_post = create_post(category: tracked_category)
|
2014-01-02 09:00:08 +08:00
|
|
|
|
2016-07-08 10:58:18 +08:00
|
|
|
create_post(topic_id: early_watched_post.topic_id)
|
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(Notification.where(user_id: user.id, topic_id: watched_post.topic_id).count).to eq 1
|
2016-07-08 10:58:18 +08:00
|
|
|
expect(Notification.where(user_id: user.id, topic_id: early_watched_post.topic_id).count).to eq 1
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(Notification.where(user_id: user.id, topic_id: tracked_post.topic_id).count).to eq 0
|
2014-06-02 11:55:01 +08:00
|
|
|
|
2016-07-08 10:58:18 +08:00
|
|
|
# we must create a record so tracked flicks over
|
|
|
|
TopicUser.change(user.id, tracked_post.topic_id, total_msecs_viewed: 10)
|
2014-06-02 11:55:01 +08:00
|
|
|
tu = TopicUser.get(tracked_post.topic, user)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(tu.notification_level).to eq TopicUser.notification_levels[:tracking]
|
|
|
|
expect(tu.notifications_reason_id).to eq TopicUser.notification_reasons[:auto_track_category]
|
2015-03-05 02:39:17 +08:00
|
|
|
end
|
|
|
|
|
2016-07-08 10:58:18 +08:00
|
|
|
it "topics that move to a tracked category should auto track" do
|
|
|
|
first_post = create_post
|
|
|
|
tracked_category = first_post.topic.category
|
2014-01-02 09:00:08 +08:00
|
|
|
|
2016-07-08 10:58:18 +08:00
|
|
|
TopicUser.change(user.id, first_post.topic_id, total_msecs_viewed: 10)
|
|
|
|
tu = TopicUser.get(first_post.topic, user)
|
|
|
|
expect(tu.notification_level).to eq TopicUser.notification_levels[:regular]
|
|
|
|
|
|
|
|
CategoryUser.set_notification_level_for_category(user, CategoryUser.notification_levels[:tracking], tracked_category.id)
|
|
|
|
|
|
|
|
tu = TopicUser.get(first_post.topic, user)
|
|
|
|
expect(tu.notification_level).to eq TopicUser.notification_levels[:tracking]
|
2014-01-02 09:00:08 +08:00
|
|
|
end
|
|
|
|
|
2015-08-20 04:40:20 +08:00
|
|
|
it "unwatches categories that have been changed" do
|
|
|
|
watched_category = Fabricate(:category)
|
|
|
|
CategoryUser.create!(user: user, category: watched_category, notification_level: CategoryUser.notification_levels[:watching])
|
|
|
|
|
|
|
|
post = create_post(category: watched_category)
|
|
|
|
tu = TopicUser.get(post.topic, user)
|
2016-07-08 10:58:18 +08:00
|
|
|
|
|
|
|
# we start watching cause a notification is sent to the watching user
|
|
|
|
# this position sent is tracking in topic users
|
2015-08-20 04:40:20 +08:00
|
|
|
expect(tu.notification_level).to eq TopicUser.notification_levels[:watching]
|
|
|
|
|
|
|
|
# Now, change the topic's category
|
|
|
|
unwatched_category = Fabricate(:category)
|
|
|
|
post.topic.change_category_to_id(unwatched_category.id)
|
2016-07-08 10:58:18 +08:00
|
|
|
expect(TopicUser.get(post.topic, user).notification_level).to eq TopicUser.notification_levels[:tracking]
|
2015-08-20 04:40:20 +08:00
|
|
|
end
|
|
|
|
|
2016-01-26 02:34:49 +08:00
|
|
|
it "does not delete TopicUser record when topic category is changed, and new category has same notification level" do
|
|
|
|
# this is done so as to maintain topic notification state when topic category is changed and the new category has same notification level for the user
|
|
|
|
# see: https://meta.discourse.org/t/changing-topic-from-one-watched-category-to-another-watched-category-makes-topic-new-again/36517/15
|
|
|
|
|
|
|
|
watched_category_1 = Fabricate(:category)
|
|
|
|
watched_category_2 = Fabricate(:category)
|
2016-07-08 10:58:18 +08:00
|
|
|
category_3 = Fabricate(:category)
|
|
|
|
|
|
|
|
post = create_post(category: watched_category_1)
|
|
|
|
|
2016-01-26 02:34:49 +08:00
|
|
|
CategoryUser.create!(user: user, category: watched_category_1, notification_level: CategoryUser.notification_levels[:watching])
|
|
|
|
CategoryUser.create!(user: user, category: watched_category_2, notification_level: CategoryUser.notification_levels[:watching])
|
|
|
|
|
2016-07-08 10:58:18 +08:00
|
|
|
# we must have a topic user record otherwise it will be watched implicitly
|
|
|
|
TopicUser.change(user.id, post.topic_id, total_msecs_viewed: 10)
|
|
|
|
|
|
|
|
expect(TopicUser.get(post.topic, user).notification_level).to eq TopicUser.notification_levels[:watching]
|
|
|
|
|
|
|
|
post.topic.change_category_to_id(category_3.id)
|
|
|
|
expect(TopicUser.get(post.topic, user).notification_level).to eq TopicUser.notification_levels[:tracking]
|
2016-01-26 02:34:49 +08:00
|
|
|
|
|
|
|
post.topic.change_category_to_id(watched_category_2.id)
|
2016-07-08 10:58:18 +08:00
|
|
|
expect(TopicUser.get(post.topic, user).notification_level).to eq TopicUser.notification_levels[:watching]
|
|
|
|
|
|
|
|
post.topic.change_category_to_id(watched_category_1.id)
|
|
|
|
expect(TopicUser.get(post.topic, user).notification_level).to eq TopicUser.notification_levels[:watching]
|
2016-01-26 02:34:49 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it "deletes TopicUser record when topic category is changed, and new category has different notification level" do
|
|
|
|
watched_category = Fabricate(:category)
|
|
|
|
tracked_category = Fabricate(:category)
|
|
|
|
CategoryUser.create!(user: user, category: watched_category, notification_level: CategoryUser.notification_levels[:watching])
|
|
|
|
CategoryUser.create!(user: user, category: tracked_category, notification_level: CategoryUser.notification_levels[:tracking])
|
|
|
|
|
|
|
|
post = create_post(category: watched_category)
|
|
|
|
tu = TopicUser.get(post.topic, user)
|
|
|
|
expect(tu.notification_level).to eq TopicUser.notification_levels[:watching]
|
|
|
|
|
|
|
|
# Now, change the topic's category
|
|
|
|
post.topic.change_category_to_id(tracked_category.id)
|
|
|
|
expect(TopicUser.get(post.topic, user).notification_level).to eq TopicUser.notification_levels[:tracking]
|
|
|
|
end
|
|
|
|
|
2015-09-03 02:43:15 +08:00
|
|
|
it "is destroyed when a user is deleted" do
|
|
|
|
category = Fabricate(:category)
|
|
|
|
|
|
|
|
CategoryUser.create!(user: user, category: category, notification_level: CategoryUser.notification_levels[:watching])
|
|
|
|
|
|
|
|
expect(CategoryUser.where(user_id: user.id).count).to eq(1)
|
|
|
|
|
|
|
|
user.destroy!
|
|
|
|
|
|
|
|
expect(CategoryUser.where(user_id: user.id).count).to eq(0)
|
|
|
|
end
|
2021-05-06 07:14:07 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
describe "#notification_levels_for" do
|
|
|
|
let!(:category1) { Fabricate(:category) }
|
|
|
|
let!(:category2) { Fabricate(:category) }
|
|
|
|
let!(:category3) { Fabricate(:category) }
|
|
|
|
let!(:category4) { Fabricate(:category) }
|
|
|
|
let!(:category5) { Fabricate(:category) }
|
|
|
|
|
|
|
|
context "for anon" do
|
|
|
|
let(:user) { nil }
|
|
|
|
before do
|
|
|
|
SiteSetting.default_categories_watching = category1.id.to_s
|
|
|
|
SiteSetting.default_categories_tracking = category2.id.to_s
|
|
|
|
SiteSetting.default_categories_watching_first_post = category3.id.to_s
|
2022-06-20 11:49:33 +08:00
|
|
|
SiteSetting.default_categories_normal = category4.id.to_s
|
2021-05-06 07:14:07 +08:00
|
|
|
SiteSetting.default_categories_muted = category5.id.to_s
|
|
|
|
end
|
|
|
|
it "every category from the default_categories_* site settings get overridden to regular, except for muted" do
|
2021-05-14 07:45:14 +08:00
|
|
|
levels = CategoryUser.notification_levels_for(user)
|
2021-05-06 07:14:07 +08:00
|
|
|
expect(levels[category1.id]).to eq(CategoryUser.notification_levels[:regular])
|
|
|
|
expect(levels[category2.id]).to eq(CategoryUser.notification_levels[:regular])
|
|
|
|
expect(levels[category3.id]).to eq(CategoryUser.notification_levels[:regular])
|
|
|
|
expect(levels[category4.id]).to eq(CategoryUser.notification_levels[:regular])
|
|
|
|
expect(levels[category5.id]).to eq(CategoryUser.notification_levels[:muted])
|
|
|
|
end
|
|
|
|
end
|
2015-09-03 02:43:15 +08:00
|
|
|
|
2021-05-06 07:14:07 +08:00
|
|
|
context "for a user" do
|
|
|
|
before do
|
|
|
|
CategoryUser.create(user: user, category: category1, notification_level: CategoryUser.notification_levels[:watching])
|
|
|
|
CategoryUser.create(user: user, category: category2, notification_level: CategoryUser.notification_levels[:tracking])
|
|
|
|
CategoryUser.create(user: user, category: category3, notification_level: CategoryUser.notification_levels[:watching_first_post])
|
|
|
|
CategoryUser.create(user: user, category: category4, notification_level: CategoryUser.notification_levels[:regular])
|
|
|
|
CategoryUser.create(user: user, category: category5, notification_level: CategoryUser.notification_levels[:muted])
|
|
|
|
end
|
|
|
|
it "gets the category_user notification levels for all categories the user is tracking and does not
|
|
|
|
include categories the user is not tracking at all" do
|
|
|
|
category6 = Fabricate(:category)
|
2021-05-14 07:45:14 +08:00
|
|
|
levels = CategoryUser.notification_levels_for(user)
|
2021-05-06 07:14:07 +08:00
|
|
|
expect(levels[category1.id]).to eq(CategoryUser.notification_levels[:watching])
|
|
|
|
expect(levels[category2.id]).to eq(CategoryUser.notification_levels[:tracking])
|
|
|
|
expect(levels[category3.id]).to eq(CategoryUser.notification_levels[:watching_first_post])
|
|
|
|
expect(levels[category4.id]).to eq(CategoryUser.notification_levels[:regular])
|
|
|
|
expect(levels[category5.id]).to eq(CategoryUser.notification_levels[:muted])
|
|
|
|
expect(levels.key?(category6.id)).to eq(false)
|
|
|
|
end
|
|
|
|
end
|
2014-01-02 09:00:08 +08:00
|
|
|
end
|
2022-02-17 07:42:02 +08:00
|
|
|
|
2022-03-02 12:02:09 +08:00
|
|
|
describe ".muted_category_ids" do
|
2022-07-28 00:14:14 +08:00
|
|
|
context "with max category nesting 2" do
|
2022-02-17 07:42:02 +08:00
|
|
|
fab!(:category1) { Fabricate(:category) }
|
|
|
|
fab!(:category2) { Fabricate(:category, parent_category: category1) }
|
|
|
|
fab!(:category3) { Fabricate(:category, parent_category: category1) }
|
|
|
|
|
|
|
|
it "calculates muted categories based on parent category state" do
|
|
|
|
expect(CategoryUser.indirectly_muted_category_ids(user)).to eq([])
|
2022-03-02 12:02:09 +08:00
|
|
|
expect(CategoryUser.muted_category_ids(user)).to eq([])
|
2022-02-17 07:42:02 +08:00
|
|
|
|
|
|
|
category_user = CategoryUser.create!(user: user, category: category1, notification_level: CategoryUser.notification_levels[:muted])
|
|
|
|
expect(CategoryUser.indirectly_muted_category_ids(user)).to contain_exactly(category2.id, category3.id)
|
2022-03-02 12:02:09 +08:00
|
|
|
expect(CategoryUser.muted_category_ids(user)).to contain_exactly(category1.id, category2.id, category3.id)
|
2022-02-17 07:42:02 +08:00
|
|
|
|
|
|
|
CategoryUser.create!(user: user, category: category3, notification_level: CategoryUser.notification_levels[:muted])
|
|
|
|
expect(CategoryUser.indirectly_muted_category_ids(user)).to contain_exactly(category2.id)
|
2022-03-02 12:02:09 +08:00
|
|
|
expect(CategoryUser.muted_category_ids(user)).to contain_exactly(category1.id, category2.id, category3.id)
|
2022-02-17 07:42:02 +08:00
|
|
|
|
2022-03-02 12:02:09 +08:00
|
|
|
category_user.update!(notification_level: CategoryUser.notification_levels[:regular])
|
2022-02-17 07:42:02 +08:00
|
|
|
expect(CategoryUser.indirectly_muted_category_ids(user)).to eq([])
|
2022-03-02 12:02:09 +08:00
|
|
|
expect(CategoryUser.muted_category_ids(user)).to contain_exactly(category3.id)
|
2022-02-17 07:42:02 +08:00
|
|
|
end
|
|
|
|
end
|
2022-07-28 00:14:14 +08:00
|
|
|
|
|
|
|
context "with max category nesting 3" do
|
2022-02-17 07:42:02 +08:00
|
|
|
let(:category1) { Fabricate(:category) }
|
|
|
|
let(:category2) { Fabricate(:category, parent_category: category1) }
|
|
|
|
let(:category3) { Fabricate(:category, parent_category: category2) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
SiteSetting.max_category_nesting = 3
|
|
|
|
category1
|
|
|
|
category2
|
|
|
|
category3
|
|
|
|
end
|
|
|
|
it "calculates muted categories based on parent category state" do
|
|
|
|
expect(CategoryUser.indirectly_muted_category_ids(user)).to eq([])
|
|
|
|
|
|
|
|
CategoryUser.create!(user: user, category: category1, notification_level: CategoryUser.notification_levels[:muted])
|
|
|
|
expect(CategoryUser.indirectly_muted_category_ids(user)).to contain_exactly(category2.id, category3.id)
|
2022-03-02 12:02:09 +08:00
|
|
|
expect(CategoryUser.muted_category_ids(user)).to contain_exactly(category1.id, category2.id, category3.id)
|
2022-02-17 07:42:02 +08:00
|
|
|
|
|
|
|
category_user3 = CategoryUser.create!(user: user, category: category3, notification_level: CategoryUser.notification_levels[:muted])
|
|
|
|
expect(CategoryUser.indirectly_muted_category_ids(user)).to contain_exactly(category2.id)
|
2022-03-02 12:02:09 +08:00
|
|
|
expect(CategoryUser.muted_category_ids(user)).to contain_exactly(category1.id, category2.id, category3.id)
|
2022-02-17 07:42:02 +08:00
|
|
|
|
2022-03-02 12:02:09 +08:00
|
|
|
category_user3.destroy!
|
2022-02-17 07:42:02 +08:00
|
|
|
category_user2 = CategoryUser.create!(user: user, category: category2, notification_level: CategoryUser.notification_levels[:muted])
|
|
|
|
expect(CategoryUser.indirectly_muted_category_ids(user)).to contain_exactly(category3.id)
|
2022-03-02 12:02:09 +08:00
|
|
|
expect(CategoryUser.muted_category_ids(user)).to contain_exactly(category1.id, category2.id, category3.id)
|
2022-02-17 07:42:02 +08:00
|
|
|
|
2022-03-02 12:02:09 +08:00
|
|
|
category_user2.update!(notification_level: CategoryUser.notification_levels[:regular])
|
2022-02-17 07:42:02 +08:00
|
|
|
expect(CategoryUser.indirectly_muted_category_ids(user)).to eq([])
|
2022-03-02 12:02:09 +08:00
|
|
|
expect(CategoryUser.muted_category_ids(user)).to contain_exactly(category1.id)
|
2022-02-17 07:42:02 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2014-01-02 09:00:08 +08:00
|
|
|
end
|