Skip to content

Commit 88633e8

Browse files
committed
feat: add community privacy level and update translations; add tests for privacy scopes and validations
1 parent 1e789eb commit 88633e8

File tree

6 files changed

+190
-4
lines changed

6 files changed

+190
-4
lines changed

app/models/concerns/better_together/privacy.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module Privacy
77

88
PRIVACY_LEVELS = {
99
public: 'public',
10+
community: 'community',
1011
private: 'private'
1112
}.freeze
1213

@@ -21,6 +22,7 @@ module Privacy
2122
validates :privacy, presence: true, inclusion: { in: PRIVACY_LEVELS.values }
2223

2324
scope :privacy_public, -> { where(privacy: 'public') }
25+
scope :privacy_community, -> { where(privacy: 'community') }
2426
scope :privacy_private, -> { where(privacy: 'private') }
2527
end
2628

config/locales/en.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ en:
672672
hint_label: Short title for the checklist item (required).
673673
hint_parent: 'Optional: nest this item under another. Maximum nesting depth
674674
is 2.'
675-
hint_privacy: 'Choose who can see this item: Public or Private.'
675+
hint_privacy: 'Choose who can see this item: Public, Community, or Private.'
676676
label: Label
677677
move_down: Move down
678678
move_up: Move up

config/locales/es.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ es:
672672
hint_label: Título corto para el elemento de la lista (requerido).
673673
hint_parent: 'Opcional: anide este elemento bajo otro. La profundidad máxima
674674
de anidamiento es 2.'
675-
hint_privacy: 'Elija quién puede ver este elemento: Público o Privado.'
675+
hint_privacy: 'Elija quién puede ver este elemento: Público, Comunidad o Privado.'
676676
label: Etiqueta
677677
move_down: Mover hacia abajo
678678
move_up: Mover hacia arriba

config/locales/fr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ fr:
676676
hint_label: Titre court pour l'élément de la liste (requis).
677677
hint_parent: 'Optionnel : imbriquez cet élément sous un autre. La profondeur
678678
maximale d''imbrication est de 2.'
679-
hint_privacy: 'Choisissez qui peut voir cet élément : Public ou Privé.'
679+
hint_privacy: 'Choisissez qui peut voir cet élément : Public, Communauté ou Privé.'
680680
label: Libellé
681681
move_down: Déplacer vers le bas
682682
move_up: Déplacer vers le haut

config/locales/uk.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ uk:
669669
hint_label: Короткий заголовок для елемента чек-листа (обов'язково).
670670
hint_parent: 'Необов''язково: вкласти цей елемент під інший. Максимальна глибина
671671
вкладення становить 2.'
672-
hint_privacy: 'Виберіть, хто може бачити цей елемент: Публічний або Приватний.'
672+
hint_privacy: 'Виберіть, хто може бачити цей елемент: Публічний, Спільнота або Приватний.'
673673
label: Мітка
674674
move_down: Перемістити вниз
675675
move_up: Перемістити вгору
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
RSpec.describe BetterTogether::Privacy do # rubocop:todo RSpec/SpecFilePathFormat
6+
# Test using the actual Page model which includes Privacy
7+
describe 'scopes' do
8+
before do
9+
BetterTogether::Page.delete_all
10+
create(:better_together_page, title: 'Public Page', slug: 'public-test', privacy: 'public')
11+
create(:better_together_page, title: 'Community Page', slug: 'community-test', privacy: 'community')
12+
create(:better_together_page, title: 'Private Page', slug: 'private-test', privacy: 'private')
13+
end
14+
15+
describe '.privacy_public' do
16+
it 'returns only public records' do
17+
results = BetterTogether::Page.privacy_public
18+
expect(results.count).to be >= 1
19+
results.each do |record|
20+
expect(record.privacy).to eq('public')
21+
end
22+
end
23+
end
24+
25+
describe '.privacy_community' do
26+
it 'returns only community records' do
27+
results = BetterTogether::Page.privacy_community
28+
expect(results.count).to be >= 1
29+
results.each do |record|
30+
expect(record.privacy).to eq('community')
31+
end
32+
end
33+
end
34+
35+
describe '.privacy_private' do
36+
it 'returns only private records' do
37+
results = BetterTogether::Page.privacy_private
38+
expect(results.count).to be >= 1
39+
results.each do |record|
40+
expect(record.privacy).to eq('private')
41+
end
42+
end
43+
end
44+
end
45+
46+
describe 'privacy enum' do
47+
let(:page) { build(:better_together_page, privacy: 'public') }
48+
49+
it 'defines all privacy levels' do
50+
expect(BetterTogether::Page.privacies.keys).to contain_exactly('public', 'community', 'private')
51+
end
52+
53+
it 'allows setting privacy to public' do
54+
page.privacy = 'public'
55+
expect(page.privacy_public?).to be true
56+
expect(page.privacy).to eq('public')
57+
end
58+
59+
it 'allows setting privacy to community' do
60+
page.privacy = 'community'
61+
expect(page.privacy_community?).to be true
62+
expect(page.privacy).to eq('community')
63+
end
64+
65+
it 'allows setting privacy to private' do
66+
page.privacy = 'private'
67+
expect(page.privacy_private?).to be true
68+
expect(page.privacy).to eq('private')
69+
end
70+
71+
it 'prefixes enum methods with privacy_' do
72+
expect(page).to respond_to(:privacy_public?)
73+
expect(page).to respond_to(:privacy_community?)
74+
expect(page).to respond_to(:privacy_private?)
75+
end
76+
end
77+
78+
describe 'validations' do
79+
let(:page) { build(:better_together_page) }
80+
81+
it 'requires privacy to be present' do
82+
page.privacy = nil
83+
page.valid?
84+
expect(page.errors[:privacy]).to include("can't be blank")
85+
end
86+
87+
it 'validates privacy is in allowed values' do
88+
expect { page.privacy = 'invalid' }.to raise_error(ArgumentError)
89+
end
90+
91+
it 'accepts all defined privacy levels' do
92+
%w[public community private].each do |level|
93+
page.privacy = level
94+
expect(page).to be_valid
95+
end
96+
end
97+
end
98+
99+
describe 'translations' do
100+
it 'provides translated privacy level names' do
101+
I18n.with_locale(:en) do
102+
expect(I18n.t('attributes.privacy_list.public')).to eq('Public')
103+
expect(I18n.t('attributes.privacy_list.community')).to eq('Community')
104+
expect(I18n.t('attributes.privacy_list.private')).not_to be_nil
105+
end
106+
end
107+
108+
it 'has translations for all supported locales' do
109+
I18n.available_locales.each do |locale|
110+
I18n.with_locale(locale) do
111+
expect(I18n.t('attributes.privacy_list.public')).not_to match(/translation missing/)
112+
expect(I18n.t('attributes.privacy_list.community')).not_to match(/translation missing/)
113+
end
114+
end
115+
end
116+
end
117+
118+
describe '.extra_permitted_attributes' do
119+
it 'includes privacy in permitted attributes' do
120+
expect(BetterTogether::Page.extra_permitted_attributes).to include(:privacy)
121+
end
122+
end
123+
124+
describe '.included_in_models' do
125+
it 'returns models that include Privacy concern' do
126+
models = described_class.included_in_models
127+
expect(models).to include(BetterTogether::Page)
128+
expect(models.all? { |m| m.included_modules.include?(described_class) }).to be true
129+
end
130+
end
131+
132+
describe 'privacy level semantics' do
133+
let(:page) { build(:better_together_page) }
134+
135+
context 'when privacy is public' do
136+
it 'indicates content visible to everyone' do
137+
page.privacy = 'public'
138+
expect(page.privacy_public?).to be true
139+
expect(page.privacy_community?).to be false
140+
expect(page.privacy_private?).to be false
141+
end
142+
end
143+
144+
context 'when privacy is community' do
145+
it 'indicates content visible to authenticated community members' do
146+
page.privacy = 'community'
147+
expect(page.privacy_public?).to be false
148+
expect(page.privacy_community?).to be true
149+
expect(page.privacy_private?).to be false
150+
end
151+
end
152+
153+
context 'when privacy is private' do
154+
it 'indicates content visible only to owner' do
155+
page.privacy = 'private'
156+
expect(page.privacy_public?).to be false
157+
expect(page.privacy_community?).to be false
158+
expect(page.privacy_private?).to be true
159+
end
160+
end
161+
end
162+
163+
describe 'database storage' do
164+
it 'stores privacy as string value' do
165+
page = create(:better_together_page, privacy: 'community')
166+
167+
# Reload from database
168+
reloaded = BetterTogether::Page.find(page.id)
169+
expect(reloaded.privacy).to eq('community')
170+
expect(reloaded.read_attribute(:privacy)).to eq('community')
171+
end
172+
173+
it 'stores all privacy levels as recognizable strings' do
174+
%w[public community private].each do |level|
175+
record = create(:better_together_page,
176+
slug: "test-#{level}-#{SecureRandom.hex(4)}",
177+
privacy: level)
178+
179+
expect(record.read_attribute(:privacy)).to eq(level)
180+
expect(record.reload.read_attribute(:privacy)).to eq(level)
181+
end
182+
end
183+
end
184+
end

0 commit comments

Comments
 (0)