2019-04-30 08:27:42 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2022-07-28 10:27:38 +08:00
|
|
|
RSpec.describe PostTiming do
|
2023-11-10 06:47:59 +08:00
|
|
|
fab!(:post)
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
it { is_expected.to validate_presence_of :post_number }
|
|
|
|
it { is_expected.to validate_presence_of :msecs }
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2013-07-04 09:47:12 +08:00
|
|
|
describe "pretend_read" do
|
2019-05-07 11:12:20 +08:00
|
|
|
fab!(:p1) { Fabricate(:post) }
|
|
|
|
fab!(:p2) { Fabricate(:post, topic: p1.topic, user: p1.user) }
|
|
|
|
fab!(:p3) { Fabricate(:post, topic: p1.topic, user: p1.user) }
|
2013-07-04 09:47:12 +08:00
|
|
|
|
|
|
|
let :topic_id do
|
|
|
|
p1.topic_id
|
|
|
|
end
|
|
|
|
|
|
|
|
def timing(user_id, post_number)
|
|
|
|
PostTiming.create!(topic_id: topic_id, user_id: user_id, post_number: post_number, msecs: 0)
|
|
|
|
end
|
|
|
|
|
2021-07-05 14:17:31 +08:00
|
|
|
def topic_user(user_id, last_read_post_number)
|
2013-07-04 09:47:12 +08:00
|
|
|
TopicUser.create!(
|
|
|
|
topic_id: topic_id,
|
|
|
|
user_id: user_id,
|
|
|
|
last_read_post_number: last_read_post_number,
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "works correctly" do
|
|
|
|
timing(1, 1)
|
|
|
|
timing(2, 1)
|
|
|
|
timing(2, 2)
|
|
|
|
timing(3, 1)
|
|
|
|
timing(3, 2)
|
|
|
|
timing(3, 3)
|
|
|
|
|
2021-07-05 14:17:31 +08:00
|
|
|
_tu_one = topic_user(1, 1)
|
|
|
|
_tu_two = topic_user(2, 2)
|
|
|
|
_tu_three = topic_user(3, 3)
|
2013-07-04 09:47:12 +08:00
|
|
|
|
|
|
|
PostTiming.pretend_read(topic_id, 2, 3)
|
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(PostTiming.where(topic_id: topic_id, user_id: 1, post_number: 3).count).to eq(0)
|
|
|
|
expect(PostTiming.where(topic_id: topic_id, user_id: 2, post_number: 3).count).to eq(1)
|
|
|
|
expect(PostTiming.where(topic_id: topic_id, user_id: 3, post_number: 3).count).to eq(1)
|
2013-07-04 09:47:12 +08:00
|
|
|
|
2014-05-06 21:41:59 +08:00
|
|
|
tu = TopicUser.find_by(topic_id: topic_id, user_id: 1)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(tu.last_read_post_number).to eq(1)
|
2013-07-04 09:47:12 +08:00
|
|
|
|
2014-05-06 21:41:59 +08:00
|
|
|
tu = TopicUser.find_by(topic_id: topic_id, user_id: 2)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(tu.last_read_post_number).to eq(3)
|
2013-07-04 09:47:12 +08:00
|
|
|
|
2014-05-06 21:41:59 +08:00
|
|
|
tu = TopicUser.find_by(topic_id: topic_id, user_id: 3)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(tu.last_read_post_number).to eq(3)
|
2013-07-04 09:47:12 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-04-14 23:49:44 +08:00
|
|
|
describe "safeguard" do
|
|
|
|
it "doesn't store timings that are larger than the account lifetime" do
|
|
|
|
user = Fabricate(:user, created_at: 3.minutes.ago)
|
|
|
|
|
|
|
|
PostTiming.process_timings(user, post.topic_id, 1, [[post.post_number, 123]])
|
|
|
|
msecs = PostTiming.where(post_number: post.post_number, user_id: user.id).pluck(:msecs)[0]
|
|
|
|
expect(msecs).to eq(123)
|
|
|
|
|
|
|
|
PostTiming.process_timings(
|
|
|
|
user,
|
|
|
|
post.topic_id,
|
|
|
|
1,
|
|
|
|
[[post.post_number, 10.minutes.to_i * 1000]],
|
|
|
|
)
|
|
|
|
msecs = PostTiming.where(post_number: post.post_number, user_id: user.id).pluck(:msecs)[0]
|
2015-06-19 08:35:55 +08:00
|
|
|
expect(msecs).to eq(123 + PostTiming::MAX_READ_TIME_PER_BATCH)
|
2015-04-14 23:49:44 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-02-26 00:42:20 +08:00
|
|
|
describe "process_timings" do
|
2017-11-18 05:08:31 +08:00
|
|
|
# integration tests
|
2013-02-25 15:42:42 +08:00
|
|
|
|
2013-02-26 00:42:20 +08:00
|
|
|
it "processes timings correctly" do
|
2016-12-22 13:46:22 +08:00
|
|
|
PostActionNotifier.enable
|
2013-05-14 09:59:55 +08:00
|
|
|
|
2017-11-18 05:08:31 +08:00
|
|
|
(2..5).each { |i| Fabricate(:post, topic: post.topic, post_number: i) }
|
2015-06-19 08:35:55 +08:00
|
|
|
user2 = Fabricate(:coding_horror, created_at: 1.day.ago)
|
2013-02-25 15:42:42 +08:00
|
|
|
|
2019-01-04 01:03:01 +08:00
|
|
|
PostActionCreator.like(user2, post)
|
2013-02-26 00:42:20 +08:00
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(post.user.unread_notifications).to eq(1)
|
2013-02-26 00:42:20 +08:00
|
|
|
|
2013-04-08 09:12:52 +08:00
|
|
|
PostTiming.process_timings(post.user, post.topic_id, 1, [[post.post_number, 100]])
|
2013-02-25 15:42:42 +08:00
|
|
|
|
|
|
|
post.user.reload
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(post.user.unread_notifications).to eq(0)
|
2013-02-26 00:42:20 +08:00
|
|
|
|
2015-06-19 08:35:55 +08:00
|
|
|
PostTiming.process_timings(post.user, post.topic_id, 1, [[post.post_number, 1.day]])
|
|
|
|
|
2017-11-18 05:08:31 +08:00
|
|
|
user_visit = post.user.user_visits.order("id DESC").first
|
|
|
|
expect(user_visit.posts_read).to eq(1)
|
|
|
|
|
|
|
|
# Skip to bottom
|
|
|
|
PostTiming.process_timings(post.user, post.topic_id, 1, [[5, 100]])
|
|
|
|
expect(user_visit.reload.posts_read).to eq(2)
|
|
|
|
|
|
|
|
# Scroll up
|
|
|
|
PostTiming.process_timings(post.user, post.topic_id, 1, [[4, 100]])
|
|
|
|
expect(user_visit.reload.posts_read).to eq(3)
|
|
|
|
PostTiming.process_timings(post.user, post.topic_id, 1, [[2, 100], [3, 100]])
|
|
|
|
expect(user_visit.reload.posts_read).to eq(5)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does not count private message posts read" do
|
|
|
|
pm = Fabricate(:private_message_topic, user: Fabricate(:admin))
|
|
|
|
user1, user2 = pm.topic_allowed_users.map(&:user)
|
|
|
|
|
|
|
|
(1..3).each { |i| Fabricate(:post, topic: pm, user: user1) }
|
|
|
|
|
|
|
|
PostTiming.process_timings(user2, pm.id, 10, [[1, 100]])
|
|
|
|
user_visit = user2.user_visits.last
|
|
|
|
expect(user_visit.posts_read).to eq(0)
|
|
|
|
|
|
|
|
PostTiming.process_timings(user2, pm.id, 10, [[2, 100], [3, 100]])
|
|
|
|
expect(user_visit.reload.posts_read).to eq(0)
|
2013-02-25 15:42:42 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-02-06 03:16:51 +08:00
|
|
|
describe "recording" do
|
|
|
|
before do
|
2021-12-23 01:09:43 +08:00
|
|
|
@topic = post.topic
|
2013-02-06 03:16:51 +08:00
|
|
|
@coding_horror = Fabricate(:coding_horror)
|
2021-12-23 01:09:43 +08:00
|
|
|
@timing_attrs = {
|
|
|
|
msecs: 1234,
|
|
|
|
topic_id: post.topic_id,
|
|
|
|
user_id: @coding_horror.id,
|
|
|
|
post_number: post.post_number,
|
|
|
|
}
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it "adds a view to the post" do
|
2014-12-31 22:55:03 +08:00
|
|
|
expect {
|
2013-02-06 03:16:51 +08:00
|
|
|
PostTiming.record_timing(@timing_attrs)
|
2021-12-23 01:09:43 +08:00
|
|
|
post.reload
|
|
|
|
}.to change(post, :reads).by(1)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
2021-02-23 22:36:00 +08:00
|
|
|
it "doesn't update the posts read count if the topic is a PM" do
|
|
|
|
pm = Fabricate(:private_message_post).topic
|
|
|
|
@timing_attrs = @timing_attrs.merge(topic_id: pm.id)
|
|
|
|
|
|
|
|
PostTiming.record_timing(@timing_attrs)
|
|
|
|
|
|
|
|
expect(@coding_horror.user_stat.posts_read_count).to eq(0)
|
|
|
|
end
|
|
|
|
|
2013-02-06 03:16:51 +08:00
|
|
|
describe "multiple calls" do
|
2014-08-07 12:20:42 +08:00
|
|
|
it "correctly works" do
|
2013-02-06 03:16:51 +08:00
|
|
|
PostTiming.record_timing(@timing_attrs)
|
|
|
|
PostTiming.record_timing(@timing_attrs)
|
2021-12-23 01:09:43 +08:00
|
|
|
timing =
|
|
|
|
PostTiming.find_by(
|
|
|
|
topic_id: post.topic_id,
|
|
|
|
user_id: @coding_horror.id,
|
|
|
|
post_number: post.post_number,
|
|
|
|
)
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(timing).to be_present
|
|
|
|
expect(timing.msecs).to eq(2468)
|
2013-02-06 03:16:51 +08:00
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(@coding_horror.user_stat.posts_read_count).to eq(1)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
2013-02-26 00:42:20 +08:00
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
2019-10-09 02:39:23 +08:00
|
|
|
describe "decrementing posts read count when destroying post timings" do
|
|
|
|
let(:initial_read_count) { 0 }
|
|
|
|
let(:post) { Fabricate(:post, reads: initial_read_count) }
|
|
|
|
|
|
|
|
before { PostTiming.process_timings(post.user, post.topic_id, 1, [[post.post_number, 100]]) }
|
|
|
|
|
|
|
|
it "#destroy_last_for decrements the reads count for a post" do
|
2022-02-22 04:45:01 +08:00
|
|
|
PostTiming.destroy_last_for(post.user, topic_id: post.topic_id)
|
2019-10-09 02:39:23 +08:00
|
|
|
|
|
|
|
expect(post.reload.reads).to eq initial_read_count
|
|
|
|
end
|
|
|
|
|
|
|
|
it "#destroy_for decrements the reads count for a post" do
|
|
|
|
PostTiming.destroy_for(post.user, [post.topic_id])
|
|
|
|
|
|
|
|
expect(post.reload.reads).to eq initial_read_count
|
|
|
|
end
|
|
|
|
end
|
2020-09-03 14:02:15 +08:00
|
|
|
|
|
|
|
describe ".destroy_last_for" do
|
|
|
|
it "updates first unread for a user correctly when topic is public" do
|
|
|
|
post.topic.update!(updated_at: 10.minutes.ago)
|
|
|
|
PostTiming.process_timings(post.user, post.topic_id, 1, [[post.post_number, 100]])
|
|
|
|
|
2022-02-22 04:45:01 +08:00
|
|
|
PostTiming.destroy_last_for(post.user, topic_id: post.topic_id)
|
2020-09-03 14:02:15 +08:00
|
|
|
|
|
|
|
expect(post.user.user_stat.reload.first_unread_at).to eq_time(post.topic.updated_at)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "updates first unread for a user correctly when topic is a pm" do
|
|
|
|
post = Fabricate(:private_message_post)
|
|
|
|
post.topic.update!(updated_at: 10.minutes.ago)
|
|
|
|
PostTiming.process_timings(post.user, post.topic_id, 1, [[post.post_number, 100]])
|
|
|
|
|
2022-02-22 04:45:01 +08:00
|
|
|
PostTiming.destroy_last_for(post.user, topic_id: post.topic_id)
|
2020-09-03 14:02:15 +08:00
|
|
|
|
|
|
|
expect(post.user.user_stat.reload.first_unread_pm_at).to eq_time(post.topic.updated_at)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "updates first unread for a user correctly when topic is a group pm" do
|
|
|
|
topic = Fabricate(:private_message_topic, updated_at: 10.minutes.ago)
|
|
|
|
post = Fabricate(:post, topic: topic)
|
|
|
|
user = Fabricate(:user)
|
|
|
|
group = Fabricate(:group)
|
|
|
|
group.add(user)
|
|
|
|
topic.allowed_groups << group
|
|
|
|
PostTiming.process_timings(user, topic.id, 1, [[post.post_number, 100]])
|
|
|
|
|
2022-02-22 04:45:01 +08:00
|
|
|
PostTiming.destroy_last_for(user, topic_id: topic.id)
|
2020-09-03 14:02:15 +08:00
|
|
|
|
|
|
|
expect(GroupUser.find_by(user: user, group: group).first_unread_pm_at).to eq_time(
|
|
|
|
post.topic.updated_at,
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|