statuses_spec.rb 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. require 'rails_helper'
  2. RSpec.describe Trends::Statuses do
  3. subject! { described_class.new(threshold: 5, review_threshold: 10, score_halflife: 8.hours) }
  4. let!(:at_time) { DateTime.new(2021, 11, 14, 10, 15, 0) }
  5. describe 'Trends::Statuses::Query' do
  6. let!(:query) { subject.query }
  7. let!(:today) { at_time }
  8. let!(:status1) { Fabricate(:status, text: 'Foo', language: 'en', trendable: true, created_at: today) }
  9. let!(:status2) { Fabricate(:status, text: 'Bar', language: 'en', trendable: true, created_at: today) }
  10. before do
  11. 15.times { reblog(status1, today) }
  12. 12.times { reblog(status2, today) }
  13. subject.refresh(today)
  14. end
  15. describe '#filtered_for' do
  16. let(:account) { Fabricate(:account) }
  17. it 'returns a composable query scope' do
  18. expect(query.filtered_for(account)).to be_a Trends::Query
  19. end
  20. it 'filters out blocked accounts' do
  21. account.block!(status1.account)
  22. expect(query.filtered_for(account).to_a).to eq [status2]
  23. end
  24. it 'filters out muted accounts' do
  25. account.mute!(status2.account)
  26. expect(query.filtered_for(account).to_a).to eq [status1]
  27. end
  28. it 'filters out blocked-by accounts' do
  29. status1.account.block!(account)
  30. expect(query.filtered_for(account).to_a).to eq [status2]
  31. end
  32. end
  33. end
  34. describe '#add' do
  35. let(:status) { Fabricate(:status) }
  36. before do
  37. subject.add(status, 1, at_time)
  38. end
  39. it 'records use' do
  40. expect(subject.send(:recently_used_ids, at_time)).to eq [status.id]
  41. end
  42. end
  43. describe '#query' do
  44. it 'returns a composable query scope' do
  45. expect(subject.query).to be_a Trends::Query
  46. end
  47. it 'responds to filtered_for' do
  48. expect(subject.query).to respond_to(:filtered_for)
  49. end
  50. end
  51. describe '#refresh' do
  52. let!(:today) { at_time }
  53. let!(:yesterday) { today - 1.day }
  54. let!(:status1) { Fabricate(:status, text: 'Foo', language: 'en', trendable: true, created_at: yesterday) }
  55. let!(:status2) { Fabricate(:status, text: 'Bar', language: 'en', trendable: true, created_at: today) }
  56. let!(:status3) { Fabricate(:status, text: 'Baz', language: 'en', trendable: true, created_at: today) }
  57. before do
  58. 13.times { reblog(status1, today) }
  59. 13.times { reblog(status2, today) }
  60. 4.times { reblog(status3, today) }
  61. end
  62. context do
  63. before do
  64. subject.refresh(today)
  65. end
  66. it 'calculates and re-calculates scores' do
  67. expect(subject.query.limit(10).to_a).to eq [status2, status1]
  68. end
  69. it 'omits statuses below threshold' do
  70. expect(subject.query.limit(10).to_a).to_not include(status3)
  71. end
  72. end
  73. it 'decays scores' do
  74. subject.refresh(today)
  75. original_score = status2.trend.score
  76. expect(original_score).to be_a Float
  77. subject.refresh(today + subject.options[:score_halflife])
  78. decayed_score = status2.trend.reload.score
  79. expect(decayed_score).to be <= original_score / 2
  80. end
  81. end
  82. def reblog(status, at_time)
  83. reblog = Fabricate(:status, reblog: status, created_at: at_time)
  84. subject.add(status, reblog.account_id, at_time)
  85. end
  86. end