0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 17:53:55 +08:00
discourse/spec/serializers/theme_settings_serializer_spec.rb
Martin Brennan fc8df41adb
DEV: Add disallowed_groups to theme/component settings (#41792)
Further following on from bee1be8599,
this brings greater parity between theme settings and site settings.

This commit adds a new `disallowed_groups` field to theme and component
settings, which allows theme authors to specify groups that cannot be
selected
by admins for a particular list type or object group type setting.

This is useful for cases where the group-based setting isn't usable
for a group like e.g. anonymous_users, no point allowing them for
a setting that requires a user to be logged in to take effect.

c.f.
https://meta.discourse.org/t/granular-group-based-permissions-for-anonymous-and-logged-in-users/402273/18?u=martin

### List groups

With `disallowed_groups: "4|5"` specified (`logged_in_users` &
`anonymous_users`)

<img width="734" height="450" alt="image"
src="https://github.com/user-attachments/assets/ed8d7338-65fa-44e6-8dce-7073a87076e6"
/>

### Object groups

With `disallowed_groups: "4|5"` specified (`logged_in_users` &
`anonymous_users`)

<img width="696" height="725" alt="image"
src="https://github.com/user-attachments/assets/1a9103d4-cf44-4038-9d62-3838cb779b49"
/>
2026-07-20 09:28:52 +10:00

179 lines
5 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe ThemeSettingsSerializer do
fab!(:theme)
let(:theme_setting) do
yaml = File.read("#{Rails.root.join("spec/fixtures/theme_settings/objects_settings.yaml")}")
theme.set_field(target: :settings, name: "yaml", value: yaml)
theme.save!
theme.settings
end
describe "#objects_schema" do
it "should include the attribute when theme setting is typed objects" do
payload = ThemeSettingsSerializer.new(theme_setting[:objects_setting]).as_json
expect(payload[:theme_settings][:objects_schema][:name]).to eq("section")
end
it "includes disallowed groups metadata for group properties" do
theme.set_field(target: :settings, name: "yaml", value: <<~YAML)
objects_setting:
type: objects
default: []
schema:
name: section
properties:
group_ids:
type: groups
disallowed_groups: "0|1"
YAML
theme.save!
payload = ThemeSettingsSerializer.new(theme.reload.settings[:objects_setting]).as_json
expect(
payload[:theme_settings][:objects_schema][:properties][:group_ids][:disallowed_groups],
).to eq("0|1")
end
end
describe "#disallowed_groups" do
it "includes disallowed groups metadata for group list settings" do
theme.set_field(target: :settings, name: "yaml", value: <<~YAML)
groups_setting:
type: list
list_type: group
disallowed_groups: "0|1"
default: "2|3"
YAML
theme.save!
payload = ThemeSettingsSerializer.new(theme.reload.settings[:groups_setting]).as_json
expect(payload[:theme_settings][:disallowed_groups]).to eq("0|1")
end
end
describe "#valid_values" do
fab!(:theme_with_enum, :theme)
before do
theme_with_enum.set_field(target: :settings, name: "yaml", value: <<~YAML)
my_enum:
type: enum
default: option_a
choices:
- option_a
- option_b
- option_c
YAML
theme_with_enum.save!
end
it "returns choice labels from locale files when defined" do
ThemeField.create!(
theme_id: theme_with_enum.id,
name: "en",
type_id: ThemeField.types[:yaml],
target_id: Theme.targets[:translations],
value: <<~YAML,
en:
theme_metadata:
settings:
my_enum:
choices:
option_a: "Option A Label"
option_b: "Option B Label"
option_c: "Option C Label"
YAML
)
payload =
ThemeSettingsSerializer.new(theme_with_enum.reload.settings[:my_enum]).as_json[
:theme_settings
]
expect(payload[:valid_values]).to eq(
[
{ name: "Option A Label", value: "option_a" },
{ name: "Option B Label", value: "option_b" },
{ name: "Option C Label", value: "option_c" },
],
)
end
it "returns raw values when no locale labels are defined" do
payload =
ThemeSettingsSerializer.new(theme_with_enum.settings[:my_enum]).as_json[:theme_settings]
expect(payload[:valid_values]).to eq(%w[option_a option_b option_c])
end
it "handles mixed case where some choices have labels and some don't" do
ThemeField.create!(
theme_id: theme_with_enum.id,
name: "en",
type_id: ThemeField.types[:yaml],
target_id: Theme.targets[:translations],
value: <<~YAML,
en:
theme_metadata:
settings:
my_enum:
choices:
option_a: "Option A Label"
YAML
)
payload =
ThemeSettingsSerializer.new(theme_with_enum.reload.settings[:my_enum]).as_json[
:theme_settings
]
expect(payload[:valid_values]).to eq(
[{ name: "Option A Label", value: "option_a" }, "option_b", "option_c"],
)
end
it "handles integer choice values with string locale keys" do
theme_with_enum.set_field(target: :settings, name: "yaml", value: <<~YAML)
int_enum:
type: enum
default: 1
choices:
- 1
- 2
- 3
YAML
theme_with_enum.save!
ThemeField.create!(
theme_id: theme_with_enum.id,
name: "en",
type_id: ThemeField.types[:yaml],
target_id: Theme.targets[:translations],
value: <<~YAML,
en:
theme_metadata:
settings:
int_enum:
choices:
"1": "One"
"2": "Two"
"3": "Three"
YAML
)
payload =
ThemeSettingsSerializer.new(theme_with_enum.reload.settings[:int_enum]).as_json[
:theme_settings
]
expect(payload[:valid_values]).to eq(
[{ name: "One", value: 1 }, { name: "Two", value: 2 }, { name: "Three", value: 3 }],
)
end
end
end