0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-06 13:08:40 +08:00
discourse/spec/serializers/site_serializer_spec.rb
Kris d2d79d290e
FEATURE: explicit default homepage setting (#41785)
This creates an explicit "default homepage" setting, because right now
the experience of changing the homepage via the "top menu" setting isn't
very intuitive. This will also make it easier to support new homepage
options in the future that don't necessarily need to exist within "top
menu."

The setting is empty by default, and when empty it falls back to "First
item in top menu" — using the current functionality as a fallback means
we don't need a migration.

The options in the list are the core top menu choices plus anything
registered via `Discourse.filters.push(:filter)`. Registered filters are
an existing pattern that come with all the prerequisites to function as
a homepage (server & client routes, and a topic list).

So for example, how the "votes" option is produced

plugins/discourse-topic-voting/plugin.rb
```ruby
Discourse.filters.push(:votes)
Discourse.anonymous_filters.push(:votes)
```

anonymous_filters is optional, if there's no anonymous equivalent of a
given option, we fall back to the first anon-viewable top menu item
(there's always at least one)

lib/discourse_topic_voting/topic_query_extension.rb
```ruby
def list_votes
  create_list(:votes, unordered: true) do |topics|
    topics.joins(
      "LEFT JOIN topic_voting_topic_vote_count dvtvc ON dvtvc.topic_id = topics.id",
    ).order("COALESCE(dvtvc.votes_count,'0')::integer DESC, topics.bumped_at DESC")
  end
end
```

config/locales/client.en.yml
```yaml
js:
  filters:
    votes:
      title: "Votes"
      help: "topics with the all time most votes"
```

<img width="600" alt="image"
src="https://github.com/user-attachments/assets/6b580e92-1b58-477c-81ab-6ceacc020672"
/>

This also adds a persistent "Default" option to the Default Home Page
user preference, which was previously only visible when a custom
homepage is set by a theme.

A future enhancement could add a plugin API for registering non-filter
homepage options (e.g. a chat channel)

Some related fixes along for the ride:

* select-kit treated a blank value as "clear selection", so it could not
be selected or displayed... this allows "First item in top menu" as an
alias for being unset
* the admin combo-box couldn't detect when the first choice's value was
blank, and submitted the whole object
* topic lists advertised RSS feeds that don't exist for registered
filters (this was happening with /votes)
2026-07-22 16:22:19 -04:00

733 lines
26 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe SiteSerializer do
let(:guardian) { Guardian.new }
let(:category) { Fabricate(:category) }
after { Site.clear_cache }
describe "category_types" do
it "is included on each serialized category in the site payload" do
category
Site.clear_cache
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
c = serialized[:categories].find { |entry| entry[:id] == category.id }
expect(c).to have_key(:category_types)
end
end
describe "#homepage_choices" do
it "exposes the eligible homepage choices" do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:homepage_choices]).to eq(TopMenu.homepage_choices)
end
end
describe "#user_tips" do
it "is included if enable_user_tips" do
SiteSetting.enable_user_tips = true
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:user_tips]).to eq(User.user_tips)
end
it "is not included if enable_user_tips is disabled" do
SiteSetting.enable_user_tips = false
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:user_tips]).to eq(nil)
end
end
describe "#access_control" do
let(:target_class) do
Class.new(ActiveRecord::Base) do
include AclTarget
self.table_name = "posts"
def self.name
"SiteSerializerSpecTarget"
end
def self.mandatory_acl
[{ type: :group, id: Group::AUTO_GROUPS[:admins], permission: "manage" }]
end
def self.banned_acl
[{ type: :group, id: Group::AUTO_GROUPS[:anonymous_users], permission: "edit" }]
end
end
end
after { DiscoursePluginRegistry.reset_register!(:acl_target_classes) }
it "includes mandatory ACLs by target class" do
target_class
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized.dig(:access_control, :mandatory_acl)).to include(
"SiteSerializerSpecTarget" => [
{ type: :group, id: Group::AUTO_GROUPS[:admins], permission: "manage" },
],
)
end
it "includes banned ACLs by target class" do
target_class
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized.dig(:access_control, :banned_acl)).to include(
"SiteSerializerSpecTarget" => [
{ type: :group, id: Group::AUTO_GROUPS[:anonymous_users], permission: "edit" },
],
)
end
it "includes plugin-registered target classes" do
Object.const_set(:SiteSerializerSpecTarget, target_class)
AclTarget.loaded_target_classes.delete(target_class)
DiscoursePluginRegistry.register_acl_target_class(
"SiteSerializerSpecTarget",
Plugin::Instance.new,
)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized.dig(:access_control, :mandatory_acl)).to include(
"SiteSerializerSpecTarget" => [
{ type: :group, id: Group::AUTO_GROUPS[:admins], permission: "manage" },
],
)
ensure
Object.send(:remove_const, :SiteSerializerSpecTarget) if defined?(SiteSerializerSpecTarget)
end
end
it "includes category custom fields only if its preloaded" do
category.custom_fields["enable_marketplace"] = true
category.save_custom_fields
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
c1 = serialized[:categories].find { |c| c[:id] == category.id }
expect(c1[:custom_fields]).to eq(nil)
Site.preloaded_category_custom_fields << "enable_marketplace"
Site.clear_cache
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
c1 = serialized[:categories].find { |c| c[:id] == category.id }
expect(c1[:custom_fields]["enable_marketplace"]).to eq("t")
ensure
Site.reset_preloaded_category_custom_fields
end
it "includes category tags" do
tag = Fabricate(:tag)
tag_group = Fabricate(:tag_group)
tag_group_2 = Fabricate(:tag_group)
category.tags << tag
category.tag_groups << tag_group
category.update!(
category_required_tag_groups: [
CategoryRequiredTagGroup.new(tag_group: tag_group_2, min_count: 1),
],
)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
c1 = serialized[:categories].find { |c| c[:id] == category.id }
expect(c1[:allowed_tags]).to contain_exactly({ id: tag.id, name: tag.name, slug: tag.slug })
expect(c1[:allowed_tag_groups]).to contain_exactly(tag_group.name)
expect(c1[:required_tag_groups]).to eq([{ name: tag_group_2.name, min_count: 1 }])
end
it "doesn't explode when category_required_tag_group is missing" do
tag = Fabricate(:tag)
tag_group = Fabricate(:tag_group)
crtg = CategoryRequiredTagGroup.new(tag_group: tag_group, min_count: 1)
category.update!(category_required_tag_groups: [crtg])
tag_group.delete # Bypassing hooks like this should never happen in the app
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
c1 = serialized[:categories].find { |c| c[:id] == category.id }
expect(c1[:required_tag_groups]).to eq([{ name: nil, min_count: 1 }])
end
it "returns correct notification level for categories" do
SiteSetting.mute_all_categories_by_default = true
SiteSetting.default_categories_normal = category.id.to_s
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
categories = serialized[:categories]
expect(categories[0][:notification_level]).to eq(0)
expect(categories[-1][:notification_level]).to eq(1)
end
it "includes user-selectable color schemes" do
dark_scheme =
ColorScheme.create_from_base(
name: "AnotherDarkScheme",
base_scheme_id: ColorScheme::NAMES_TO_ID_MAP["Dark"],
)
dark_scheme.user_selectable = true
dark_scheme.save!
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:user_color_schemes].count).to eq(1)
expect(serialized[:user_color_schemes][0][:is_dark]).to eq(true)
end
describe "only_theme_color_schemes modifier" do
fab!(:theme)
fab!(:color_scheme) { Fabricate(:color_scheme, theme_id: theme.id, user_selectable: false) }
before do
theme.update!(user_selectable: true)
theme.theme_modifier_set.update!(only_theme_color_schemes: true)
end
it "includes theme color schemes in user_color_schemes when modifier is active" do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
scheme_ids = serialized[:user_color_schemes].map { |s| s[:id] }
expect(scheme_ids).to include(color_scheme.id)
end
it "includes only_theme_color_schemes flag in user_themes" do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
theme_data = serialized[:user_themes].find { |t| t["theme_id"] == theme.id }
expect(theme_data["only_theme_color_schemes"]).to eq(true)
end
end
it "includes default dark mode scheme" do
scheme = ColorScheme.last
Theme.find_default.update!(dark_color_scheme_id: scheme.id)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
default_dark_scheme = expect(serialized[:default_dark_color_scheme][:name]).to eq(scheme.name)
Theme.find_default.update!(dark_color_scheme_id: nil)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:default_dark_color_scheme]).to eq(nil)
end
it "does not include shared_drafts_category_id if the category is Uncategorized" do
admin = Fabricate(:admin)
admin_guardian = Guardian.new(admin)
SiteSetting.shared_drafts_category = SiteSetting.uncategorized_category_id
serialized =
described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json
expect(serialized[:shared_drafts_category_id]).to eq(nil)
end
context "with lazy loaded categories enabled" do
fab!(:user)
fab!(:category)
fab!(:sidebar) { Fabricate(:category_sidebar_section_link, linkable: category, user: user) }
before { SiteSetting.lazy_load_categories_groups = "#{Group::AUTO_GROUPS[:logged_in_users]}" }
it "includes categories for anonymous users" do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:categories].map { |category| category[:id] }).to include(category.id)
end
it "includes preloaded categories for logged in users" do
guardian = Guardian.new(user)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:categories].map { |c| c[:id] }).to contain_exactly(category.id)
end
end
describe "#anonymous_default_navigation_menu_tags" do
fab!(:user)
fab!(:tag) { Fabricate(:tag, name: "dev", description: "some description") }
fab!(:tag2) { Fabricate(:tag, name: "random") }
fab!(:hidden_tag) { Fabricate(:tag, name: "secret") }
fab!(:staff_tag_group) do
Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: [hidden_tag.name])
end
before do
SiteSetting.navigation_menu = "sidebar"
SiteSetting.tagging_enabled = true
SiteSetting.default_navigation_menu_tags = "#{tag.name}|#{tag2.name}|#{hidden_tag.name}"
end
it "is not included in the serialised object when tagging is not enabled" do
SiteSetting.tagging_enabled = false
guardian = Guardian.new(user)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:anonymous_default_navigation_menu_tags]).to eq(nil)
end
it "is not included in the serialised object when user is not anonymous" do
guardian = Guardian.new(user)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:anonymous_default_navigation_menu_tags]).to eq(nil)
end
it "is not included in the serialisd object when default sidebar tags have not been configured" do
SiteSetting.default_navigation_menu_tags = ""
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:anonymous_default_navigation_menu_tags]).to eq(nil)
end
it "includes only tags user can see in the serialised object when user is anonymous" do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:anonymous_default_navigation_menu_tags]).to eq(
[
{
id: tag.id,
name: "dev",
slug: tag.slug,
description: "some description",
pm_only: false,
},
{
id: tag2.id,
name: "random",
slug: tag2.slug,
description: tag2.description,
pm_only: false,
},
],
)
end
end
describe "#anonymous_sidebar_sections" do
fab!(:user)
fab!(:public_sidebar_section) do
Fabricate(:sidebar_section, title: "Public section", public: true)
end
fab!(:private_sidebar_section) do
Fabricate(:sidebar_section, title: "Private section", user: user, public: false)
end
it "is not included in the serialised object when user is not anonymous" do
guardian = Guardian.new(user)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized).not_to have_key(:anonymous_sidebar_sections)
end
it "includes only public sidebar sections serialised object when user is anonymous" do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:anonymous_sidebar_sections].map { |section| section[:title] }).to eq(
["Community", "Public section"],
)
end
it "eager loads sidebar_urls" do
public_section_link =
Fabricate(:custom_sidebar_section_link, user: user, sidebar_section: public_sidebar_section)
# warmup
described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
initial_count =
track_sql_queries do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:anonymous_sidebar_sections].count).to eq(2)
expect(
serialized[:anonymous_sidebar_sections].last[:links].map { |link| link[:id] },
).to eq([public_section_link.linkable.id])
end.count
public_section_link_2 =
Fabricate(:custom_sidebar_section_link, user: user, sidebar_section: public_sidebar_section)
public_section_link_3 =
Fabricate(:custom_sidebar_section_link, user: user, sidebar_section: public_sidebar_section)
final_count =
track_sql_queries do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:anonymous_sidebar_sections].count).to eq(2)
expect(
serialized[:anonymous_sidebar_sections].last[:links].map { |link| link[:id] },
).to eq(
[
public_section_link.linkable.id,
public_section_link_2.linkable.id,
public_section_link_3.linkable.id,
],
)
end.count
expect(final_count).to eq(initial_count)
end
end
describe "#top_tags" do
fab!(:tag)
describe "when tagging is not enabled" do
before { SiteSetting.tagging_enabled = false }
it "is not included in the serialised object" do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:top_tags]).to eq(nil)
end
end
describe "when tagging is enabled" do
fab!(:tag2, :tag)
fab!(:tag3, :tag)
before { SiteSetting.tagging_enabled = true }
it "is not included in the serialised object when there are no tags" do
tag.destroy!
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:top_tags]).to eq([])
end
it "is included in the serialised object containing the top tags" do
tag2 = Fabricate(:tag)
tag2 = Fabricate(:tag)
SiteSetting.max_tags_in_filter_list = 1
CategoryTagStat.create!(
category_id: SiteSetting.uncategorized_category_id,
tag_id: tag2.id,
topic_count: 2,
)
CategoryTagStat.create!(
category_id: SiteSetting.uncategorized_category_id,
tag_id: tag.id,
topic_count: 1,
)
CategoryTagStat.create!(
category_id: SiteSetting.uncategorized_category_id,
tag_id: tag3.id,
topic_count: 5,
)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:top_tags]).to eq(
[
{ id: tag3.id, name: tag3.name, slug: tag3.slug },
{ id: tag2.id, name: tag2.name, slug: tag2.slug },
],
)
end
end
end
describe "#navigation_menu_site_top_tags" do
fab!(:tag1) do
Fabricate(:tag, name: "tag 1").tap { |tag| Fabricate.times(2, :topic, tags: [tag]) }
end
fab!(:tag2) do
Fabricate(:tag, name: "tag 2").tap { |tag| Fabricate.times(1, :topic, tags: [tag]) }
end
fab!(:tag3) do
Fabricate(:tag, name: "tag 3").tap { |tag| Fabricate.times(3, :topic, tags: [tag]) }
end
fab!(:hidden_tag) do
Fabricate(:tag, name: "tag 4").tap { |tag| Fabricate.times(4, :topic, tags: [tag]) }
end
fab!(:staff_tag_group) do
Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: [hidden_tag.name])
end
it "should return the site's top tags as the default tags for sidebar" do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:navigation_menu_site_top_tags]).to eq(
[
{
id: tag3.id,
name: tag3.name,
slug: tag3.slug_for_url,
description: tag3.description,
pm_only: false,
},
{
id: tag1.id,
name: tag1.name,
slug: tag1.slug_for_url,
description: tag1.description,
pm_only: false,
},
{
id: tag2.id,
name: tag2.name,
slug: tag2.slug_for_url,
description: tag2.description,
pm_only: false,
},
],
)
end
it "should not be serialized if `tagging_enabled` site setting is set to false" do
SiteSetting.set(:tagging_enabled, false)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:navigation_menu_site_top_tags]).to eq(nil)
end
it "should use slug_for_url for tags with empty slugs" do
numeric_tag =
Fabricate(:tag, name: "1").tap { |tag| Fabricate.times(10, :topic, tags: [tag]) }
expect(numeric_tag.slug).to eq("")
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
numeric_entry =
serialized[:navigation_menu_site_top_tags].find { |t| t[:id] == numeric_tag.id }
expect(numeric_entry[:slug]).to eq("#{numeric_tag.id}-tag")
end
it "should return an empty array if site has no top tags" do
Tag.delete_all
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:navigation_menu_site_top_tags]).to eq([])
end
end
describe "#whispers_allowed_groups_names" do
fab!(:admin)
fab!(:allowed_user, :user)
fab!(:not_allowed_user, :user)
fab!(:group1) { Fabricate(:group, name: "whisperers1", users: [allowed_user]) }
fab!(:group2) { Fabricate(:group, name: "whisperers2", users: [allowed_user]) }
it "returns correct group names for created groups" do
admin_guardian = Guardian.new(admin)
SiteSetting.whispers_allowed_groups = "#{group1.id}|#{group2.id}"
serialized =
described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json
expect(serialized[:whispers_allowed_groups_names]).to contain_exactly(
"whisperers1",
"whisperers2",
)
end
it "returns correct group names for automatic groups" do
admin_guardian = Guardian.new(admin)
SiteSetting.whispers_allowed_groups =
"#{Group::AUTO_GROUPS[:staff]}|#{Group::AUTO_GROUPS[:trust_level_4]}"
serialized =
described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json
expect(serialized[:whispers_allowed_groups_names]).to contain_exactly(
"trust_level_4",
"staff",
)
end
it "returns group names when user is allowed to whisper" do
user_guardian = Guardian.new(allowed_user)
SiteSetting.whispers_allowed_groups = "#{group1.id}|#{group2.id}"
serialized =
described_class.new(Site.new(user_guardian), scope: user_guardian, root: false).as_json
expect(serialized[:whispers_allowed_groups_names]).to contain_exactly(
"whisperers1",
"whisperers2",
)
end
it "returns nil when user is not allowed to whisper" do
user_guardian = Guardian.new(not_allowed_user)
SiteSetting.whispers_allowed_groups =
"#{Group::AUTO_GROUPS[:staff]}|#{Group::AUTO_GROUPS[:trust_level_4]}"
serialized =
described_class.new(Site.new(user_guardian), scope: user_guardian, root: false).as_json
expect(serialized[:whispers_allowed_groups_names]).to eq(nil)
end
end
describe "#full_name_required_for_signup" do
let(:site_json) do
described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
end
it "is false when full_name_requirement setting is optional_at_signup" do
SiteSetting.full_name_requirement = "optional_at_signup"
expect(site_json[:full_name_required_for_signup]).to eq(false)
end
it "is false when full_name_requirement setting is hidden_at_signup" do
SiteSetting.full_name_requirement = "hidden_at_signup"
SiteSetting.enable_names = true
expect(site_json[:full_name_required_for_signup]).to eq(false)
end
it "is true when full_name_requirement setting is required_at_signup and enable_names is true" do
SiteSetting.full_name_requirement = "required_at_signup"
SiteSetting.enable_names = true
expect(site_json[:full_name_required_for_signup]).to eq(true)
end
end
describe "#full_name_visible_in_signup" do
let(:site_json) do
described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
end
it "is false when full_name_requirement is hidden_at_signup" do
SiteSetting.full_name_requirement = "hidden_at_signup"
expect(site_json[:full_name_visible_in_signup]).to eq(false)
end
it "is true when enable_names setting is true and full_name_requirement is optional_at_signup" do
SiteSetting.full_name_requirement = "optional_at_signup"
expect(site_json[:full_name_visible_in_signup]).to eq(true)
end
it "is true when enable_names setting is true and full_name_requirement is required_at_signup" do
SiteSetting.full_name_requirement = "required_at_signup"
expect(site_json[:full_name_visible_in_signup]).to eq(true)
end
it "is false when enable_names setting is true and full_name_requirement is hidden_at_signup" do
SiteSetting.full_name_requirement = "hidden_at_signup"
expect(site_json[:full_name_visible_in_signup]).to eq(false)
end
end
describe "#email_configured" do
it "returns true when smtp_address is set" do
global_setting :smtp_address, "smtp.example.com"
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:email_configured]).to eq(true)
end
it "returns false when smtp_address is blank" do
global_setting :smtp_address, ""
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:email_configured]).to eq(false)
end
end
describe "#groups" do
fab!(:group)
fab!(:admin)
it "serializes the automatic field of each group" do
serialized_groups =
described_class.new(Site.new(admin.guardian), scope: admin.guardian, root: false).as_json[
:groups
]
expect(serialized_groups.find { |g| g["name"] == "trust_level_1" }["automatic"]).to eq(true)
expect(serialized_groups.find { |g| g["name"] == group.name }["automatic"]).to eq(false)
end
end
describe "#admin_config_login_routes" do
fab!(:admin)
fab!(:user)
before { DiscoursePluginRegistry.admin_config_login_routes << "plugin_login_route" }
after { DiscoursePluginRegistry.admin_config_login_routes.delete("plugin_login_route") }
it "is included for admin users" do
admin_guardian = Guardian.new(admin)
serialized =
described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json
expect(serialized[:admin_config_login_routes]).to include("plugin_login_route")
end
it "is not included for anonymous users" do
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized).not_to have_key(:admin_config_login_routes)
end
it "is not included for non-admin users" do
user_guardian = Guardian.new(user)
serialized =
described_class.new(Site.new(user_guardian), scope: user_guardian, root: false).as_json
expect(serialized).not_to have_key(:admin_config_login_routes)
end
end
describe "#upcoming_changes_with_css" do
it "returns upcoming changes with body_class: true" do
mock_upcoming_change_metadata(
{
enable_upload_debug_mode: {
impact: "other,developers",
status: :beta,
impact_type: "other",
impact_role: "developers",
body_class: true,
},
enable_user_tips: {
impact: "feature,all_members",
status: :alpha,
impact_type: "feature",
impact_role: "all_members",
body_class: false,
},
},
)
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
expect(serialized[:upcoming_changes_with_css]).to include(:enable_upload_debug_mode)
expect(serialized[:upcoming_changes_with_css]).not_to include(:enable_user_tips)
end
end
describe "#permanent_upcoming_change_names" do
before do
UpcomingChanges.stubs(:permanent_upcoming_change_names).returns(%w[enable_permanent_feature])
end
it "returns the permanent change names for staff" do
admin = Fabricate(:admin)
admin_guardian = Guardian.new(admin)
serialized =
described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json
expect(serialized[:permanent_upcoming_change_names]).to eq(%w[enable_permanent_feature])
end
it "is not included for non-staff users" do
user = Fabricate(:user)
user_guardian = Guardian.new(user)
serialized =
described_class.new(Site.new(user_guardian), scope: user_guardian, root: false).as_json
expect(serialized).not_to have_key(:permanent_upcoming_change_names)
end
end
end