Skip to content

Commit 1f76564

Browse files
committed
Add specs for PlatformInvitationMailer, ReportsController, SetupWizardStepsController, TranslationsController, and ExternalLinkIconSanitizer
- Implement tests for PlatformInvitationMailer to verify email content and behavior with various scenarios. - Create comprehensive specs for ReportsController to ensure metrics are correctly assigned and returned. - Add tests for SetupWizardStepsController to validate platform and admin creation processes. - Implement tests for TranslationsController to ensure translation functionality works as expected. - Add specs for ExternalLinkIconSanitizer to verify proper sanitization of links and icon rendering.
1 parent b6a0628 commit 1f76564

File tree

10 files changed

+2113
-14
lines changed

10 files changed

+2113
-14
lines changed
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# frozen_string_literal: true
22

33
FactoryBot.define do
4-
factory :metrics_link_click, class: 'Metrics::LinkClick' do # rubocop:todo Lint/EmptyBlock
4+
factory :metrics_link_click, class: 'BetterTogether::Metrics::LinkClick' do
5+
url { 'https://example.com' }
6+
page_url { '/test-page' }
7+
locale { I18n.default_locale.to_s }
8+
clicked_at { Time.current }
9+
internal { false }
510
end
611
end
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
# frozen_string_literal: true
22

33
FactoryBot.define do
4-
factory :metrics_page_view, class: 'Metrics::PageView' do # rubocop:todo Lint/EmptyBlock
4+
factory :metrics_page_view, class: 'BetterTogether::Metrics::PageView' do
5+
viewed_at { Time.current }
6+
locale { I18n.default_locale.to_s }
7+
page_url { '/test-page' }
8+
9+
trait :with_pageable do
10+
association :pageable, factory: :page
11+
page_url { nil } # Let the model generate it from pageable
12+
end
513
end
614
end

spec/helpers/better_together/hub_helper_spec.rb

Lines changed: 206 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,214 @@
22

33
require 'rails_helper'
44

5-
# Specs in this file have access to a helper object that includes
6-
# the HubHelper. For example:
7-
#
8-
# describe HubHelper do
9-
# describe "string concat" do
10-
# it "concats two strings with spaces" do
11-
# expect(helper.concat_strings("this","that")).to eq("this that")
12-
# end
13-
# end
14-
# end
155
module BetterTogether
166
RSpec.describe HubHelper do
17-
it 'exists' do
18-
expect(described_class).to be # rubocop:todo RSpec/Be
7+
describe '#activities' do
8+
let(:user) { create(:user) }
9+
let(:page) { create(:page) }
10+
11+
before do
12+
allow(helper).to receive(:current_user).and_return(user)
13+
# Create some test activities
14+
create_list(:activity, 3, owner: user.person, trackable: page)
15+
end
16+
17+
it 'returns scoped activities based on policy' do
18+
activities = helper.activities
19+
expect(activities).to be_a(ActiveRecord::Relation)
20+
end
21+
22+
it 'uses ActivityPolicy::Scope to filter activities' do
23+
expect(BetterTogether::ActivityPolicy::Scope).to receive(:new)
24+
.with(user, PublicActivity::Activity)
25+
.and_call_original
26+
27+
helper.activities
28+
end
29+
end
30+
31+
describe '#timeago' do
32+
let(:test_time) { Time.zone.parse('2025-11-24 12:00:00 UTC') }
33+
34+
context 'with valid time' do
35+
it 'generates abbr tag with timeago class' do
36+
result = helper.timeago(test_time)
37+
expect(result).to have_css('abbr.timeago')
38+
end
39+
40+
it 'includes ISO8601 formatted time in title attribute' do
41+
result = helper.timeago(test_time)
42+
expect(result).to have_css("abbr[title='#{test_time.getutc.iso8601}']")
43+
end
44+
45+
it 'displays time string as content' do
46+
result = helper.timeago(test_time)
47+
expect(result).to include(test_time.to_s)
48+
end
49+
50+
it 'accepts custom CSS class' do
51+
result = helper.timeago(test_time, class: 'custom-class')
52+
expect(result).to have_css('abbr.custom-class')
53+
end
54+
55+
it 'merges custom options with defaults' do
56+
result = helper.timeago(test_time, class: 'custom', id: 'my-time')
57+
expect(result).to have_css('abbr#my-time.custom')
58+
end
59+
end
60+
61+
context 'with nil time' do
62+
it 'returns nil' do
63+
expect(helper.timeago(nil)).to be_nil
64+
end
65+
end
66+
67+
context 'with different time zones' do
68+
it 'converts to UTC for title' do
69+
tokyo_time = Time.zone.parse('2025-11-24 21:00:00 +0900')
70+
result = helper.timeago(tokyo_time)
71+
utc_time = tokyo_time.getutc.iso8601
72+
expect(result).to have_css("abbr[title='#{utc_time}']")
73+
end
74+
end
75+
end
76+
77+
describe '#whose?' do
78+
let(:user) { create(:user) }
79+
let(:other_user) { create(:user) }
80+
let(:page) { create(:page, creator: user.person) }
81+
let(:other_page) { create(:page, creator: other_user.person) }
82+
83+
context 'when user owns the object' do
84+
it 'returns "his"' do
85+
result = helper.whose?(user, page)
86+
expect(result).to eq('his')
87+
end
88+
end
89+
90+
context 'when user does not own the object' do
91+
it 'returns owner nickname with possessive' do
92+
result = helper.whose?(user, other_page)
93+
expect(result).to eq("#{other_user.person.nickname}'s")
94+
end
95+
end
96+
97+
context 'when user is nil' do
98+
it 'returns empty string' do
99+
result = helper.whose?(nil, page)
100+
expect(result).to eq('')
101+
end
102+
end
103+
104+
context 'when object has no owner' do
105+
let(:orphaned_page) { build(:page, creator: nil) }
106+
107+
it 'returns empty string' do
108+
result = helper.whose?(user, orphaned_page)
109+
expect(result).to eq('')
110+
end
111+
end
112+
113+
context 'when both user and owner are nil' do
114+
it 'returns empty string' do
115+
result = helper.whose?(nil, build(:page, creator: nil))
116+
expect(result).to eq('')
117+
end
118+
end
119+
end
120+
121+
describe '#link_to_trackable' do
122+
context 'when object exists' do
123+
let(:page) { create(:page, title: 'Test Page') }
124+
125+
it 'returns link to the object' do
126+
result = helper.link_to_trackable(page, 'Page')
127+
expect(result).to include(page.title)
128+
expect(result).to have_link(page.title)
129+
end
130+
131+
it 'includes model name as prefix' do
132+
result = helper.link_to_trackable(page, 'Page')
133+
expect(result).to include(page.class.model_name.human)
134+
end
135+
136+
it 'uses object.url if available' do
137+
allow(page).to receive(:url).and_return('/custom-url')
138+
result = helper.link_to_trackable(page, 'Page')
139+
expect(result).to have_link(page.title, href: '/custom-url')
140+
end
141+
142+
it 'falls back to object itself for URL' do
143+
# Remove url method to test fallback
144+
allow(page).to receive(:respond_to?).with(:url).and_return(false)
145+
result = helper.link_to_trackable(page, 'Page')
146+
expect(result).to be_present
147+
end
148+
149+
it 'adds text-decoration-none class to link' do
150+
result = helper.link_to_trackable(page, 'Page')
151+
expect(result).to have_css('a.text-decoration-none')
152+
end
153+
end
154+
155+
context 'when object is nil' do
156+
it 'returns message about deleted object' do
157+
result = helper.link_to_trackable(nil, 'Post')
158+
expect(result).to eq('a post which does not exist anymore')
159+
end
160+
161+
it 'downcases object type' do
162+
result = helper.link_to_trackable(nil, 'ARTICLE')
163+
expect(result).to eq('a article which does not exist anymore')
164+
end
165+
end
166+
167+
context 'with different object types' do
168+
it 'handles different model types' do
169+
community = create(:community, name: 'Test Community')
170+
result = helper.link_to_trackable(community, 'Community')
171+
expect(result).to include(community.class.model_name.human)
172+
expect(result).to have_link(community.name)
173+
end
174+
end
175+
end
176+
177+
describe 'helper integration' do
178+
it 'includes all expected methods' do
179+
expect(helper).to respond_to(:activities)
180+
expect(helper).to respond_to(:timeago)
181+
expect(helper).to respond_to(:whose?)
182+
expect(helper).to respond_to(:link_to_trackable)
183+
end
184+
end
185+
186+
describe 'edge cases' do
187+
describe '#timeago with edge times' do
188+
it 'handles very old dates' do
189+
old_time = 100.years.ago
190+
result = helper.timeago(old_time)
191+
expect(result).to be_present
192+
expect(result).to have_css('abbr.timeago')
193+
end
194+
195+
it 'handles future dates' do
196+
future_time = 10.years.from_now
197+
result = helper.timeago(future_time)
198+
expect(result).to be_present
199+
expect(result).to have_css('abbr.timeago')
200+
end
201+
end
202+
203+
describe '#whose? with complex ownership' do
204+
it 'handles users with special characters in nicknames' do
205+
user = create(:user)
206+
special_user = create(:user, person: create(:person, name: "O'Brien"))
207+
page = create(:page, creator: special_user.person)
208+
209+
result = helper.whose?(user, page)
210+
expect(result).to include("O'Brien")
211+
end
212+
end
19213
end
20214
end
21215
end

0 commit comments

Comments
 (0)