Files
fizzy/test/models/bubble_test.rb
T
Kevin McConnell 16a80ff3a6 More dynamic activity scores
This introduces a more dynamic system of activity scoring, to improve
the way bubbles "bubble up" due to their activity. There are a few
different parts we can tune here, and it's likely we'll need to make
adjustments once we get a feel for how this works in practice.

The basic idea here is:

- We assign points for certain types of event that happen on a bubble. A
  boost gets 1 point, a comment gets 10 points, and so on.
- These points decay over time, at a rate of 50% per day. So old
  activity is worth much less than new activity. Bubbles should rise up
  quickly when acted upon, bit will float back down if left idle.
- Some comments can score higher than others: the first comment from
  each person on a bubble is worth more (20) because it signals that
  more people are getting involved; and comments that follow a comment
  by a different author are also worth more (15) because that signals
  there's ongoing conversation between people, not just a series of
  notes being left by one individual.

In terms of implementation, we persist the score on the bubble
whenever it changes, but we handle the decay on the client side. That
allows us to cache the bubble representation without having to
continually change it while its activity decays.

We also keep a separate `activity_score_order` attribute on the model.
This can be used to sort the bubbles in order of "most active", without
having to think about the decay.
2025-03-05 17:16:31 +00:00

124 lines
3.9 KiB
Ruby

require "test_helper"
class BubbleTest < ActiveSupport::TestCase
setup do
Current.session = sessions(:david)
end
test "capturing messages" do
assert_difference "bubbles(:logo).messages.comments.count", +1 do
bubbles(:logo).capture Comment.new(body: "Agreed.")
end
assert_equal "Agreed.", bubbles(:logo).messages.comments.last.messageable.body.to_plain_text.chomp
end
test "boosting" do
assert_changes -> { bubbles(:logo).activity_score } do
assert_difference -> { bubbles(:logo).boosts_count }, +1 do
bubbles(:logo).boost!(bubbles(:logo).boosts_count+ 1)
end
end
end
test "assignment states" do
assert bubbles(:logo).assigned_to?(users(:kevin))
assert_not bubbles(:logo).assigned_to?(users(:david))
end
test "assignment toggling" do
assert bubbles(:logo).assigned_to?(users(:kevin))
assert_difference({ "bubbles(:logo).assignees.count" => -1, "Event.count" => +1 }) do
bubbles(:logo).toggle_assignment users(:kevin)
end
assert_not bubbles(:logo).assigned_to?(users(:kevin))
assert_equal "unassigned", Event.last.action
assert_equal [ users(:kevin) ], Event.last.assignees
assert_difference %w[ bubbles(:logo).assignees.count Event.count ], +1 do
bubbles(:logo).toggle_assignment users(:kevin)
end
assert bubbles(:logo).assigned_to?(users(:kevin))
assert_equal "assigned", Event.last.action
assert_equal [ users(:kevin) ], Event.last.assignees
end
test "tagged states" do
assert bubbles(:logo).tagged_with?(tags(:web))
assert_not bubbles(:logo).tagged_with?(tags(:mobile))
end
test "tag toggling" do
assert bubbles(:logo).tagged_with?(tags(:web))
assert_difference "bubbles(:logo).taggings.count", -1 do
bubbles(:logo).toggle_tag tags(:web)
end
assert_not bubbles(:logo).tagged_with?(tags(:web))
assert_difference "bubbles(:logo).taggings.count", +1 do
bubbles(:logo).toggle_tag tags(:web)
end
assert bubbles(:logo).tagged_with?(tags(:web))
assert_difference %w[ bubbles(:logo).taggings.count accounts("37s").tags.count ], +1 do
bubbles(:logo).toggle_tag Tag.new(title: "prioritized")
end
assert_equal "prioritized", bubbles(:logo).taggings.last.tag.title
end
test "searchable by title" do
bubble = buckets(:writebook).bubbles.create! title: "Insufficient haggis", creator: users(:kevin)
assert_includes Bubble.search("haggis"), bubble
end
test "ordering by comments" do
assert_equal bubbles(:logo, :layout, :shipping, :text), Bubble.ordered_by_comments
end
test "ordering by boosts" do
bubbles(:layout).update! boosts_count: 1_000
assert_equal bubbles(:layout, :logo, :shipping, :text), Bubble.ordered_by_boosts
end
test "popped" do
assert_equal [ bubbles(:shipping) ], Bubble.popped
end
test "active" do
assert_equal bubbles(:logo, :layout, :text), Bubble.active
end
test "unassigned" do
assert_equal bubbles(:shipping, :text), Bubble.unassigned
end
test "assigned to" do
assert_equal bubbles(:logo, :layout), Bubble.assigned_to(users(:jz))
end
test "assigned by" do
assert_equal bubbles(:layout, :logo), Bubble.assigned_by(users(:david))
end
test "in bucket" do
new_bucket = accounts("37s").buckets.create! name: "New Bucket", creator: users(:david)
assert_equal bubbles(:logo, :shipping, :layout, :text), Bubble.in_bucket(buckets(:writebook))
assert_empty Bubble.in_bucket(new_bucket)
end
test "tagged with" do
assert_equal bubbles(:layout, :text), Bubble.tagged_with(tags(:mobile))
end
test "mentioning" do
bubble = buckets(:writebook).bubbles.create! title: "Insufficient haggis", creator: users(:kevin)
bubbles(:logo).capture Comment.new(body: "I hate haggis")
bubbles(:text).capture Comment.new(body: "I love haggis")
assert_equal [ bubble, bubbles(:logo), bubbles(:text) ].sort, Bubble.mentioning("haggis").sort
end
end