discourse/plugins/discourse-rewind/spec/serializers/user_option_serializer_spec.rb
Régis Hanol 7955a472bc
FEATURE: Store rewind dismiss state in database instead of localStorage (#36625)
Users were seeing repeated rewind notifications across different devices
and browsers because the dismiss state was stored in localStorage, which
is per-browser and easily cleared.

Move the dismiss state to a new `discourse_rewind_dismissed_at` column
in the `user_options` table. This allows the dismiss to sync across all
devices and persist through browser data clears.

The timestamp is compared using "rewind year" logic - dismissing in
January 2025 (for rewind 2024) won't block the notification for rewind
2025 in December 2025.

- Add `discourse_rewind_dismissed_at` datetime column to user_options
- Add POST /rewinds/dismiss endpoint
- Add `discourse_rewind_dismissed` to user_option serializers
- Extract `DiscourseRewind.rewind_year` helper for year calculation
- Update frontend service to read from server state instead of
localStorage

---------

Co-authored-by: Martin Brennan <martin@discourse.org>
2025-12-12 15:16:22 +10:00

59 lines
1.9 KiB
Ruby

# frozen_string_literal: true
RSpec.describe UserOptionSerializer do
before { SiteSetting.discourse_rewind_enabled = true }
fab!(:user)
let(:serializer) do
UserOptionSerializer.new(user.user_option, scope: Guardian.new(user), root: false)
end
def set_dismissed_at(date_string)
user.user_option.update!(discourse_rewind_dismissed_at: DateTime.parse(date_string))
end
describe "#discourse_rewind_dismissed" do
it "returns false when dismissed_at is nil" do
expect(serializer.as_json[:discourse_rewind_dismissed]).to eq(false)
end
context "when in December 2024 (showing rewind 2024)" do
before { freeze_time DateTime.parse("2024-12-15") }
it "returns true when dismissed in Dec 2024" do
set_dismissed_at("2024-12-01")
expect(serializer.as_json[:discourse_rewind_dismissed]).to eq(true)
end
it "returns false when dismissed in Jan 2024 (was for rewind 2023)" do
set_dismissed_at("2024-01-10")
expect(serializer.as_json[:discourse_rewind_dismissed]).to eq(false)
end
it "returns false when dismissed in Dec 2023" do
set_dismissed_at("2023-12-01")
expect(serializer.as_json[:discourse_rewind_dismissed]).to eq(false)
end
end
context "when in January 2025 (still showing rewind 2024)" do
before { freeze_time DateTime.parse("2025-01-15") }
it "returns true when dismissed in Dec 2024" do
set_dismissed_at("2024-12-20")
expect(serializer.as_json[:discourse_rewind_dismissed]).to eq(true)
end
it "returns true when dismissed in Jan 2025" do
set_dismissed_at("2025-01-05")
expect(serializer.as_json[:discourse_rewind_dismissed]).to eq(true)
end
it "returns false when dismissed in Jan 2024 (was for rewind 2023)" do
set_dismissed_at("2024-01-20")
expect(serializer.as_json[:discourse_rewind_dismissed]).to eq(false)
end
end
end
end