Site configuration improvements (#8157)

* feat: alphabetize the site config page

* chore: move twitter hashtag into social media and rename Mailchimp list ID's to Newsletter

* chore: reorder the site config

* fix: don't show a broken image when the value does not exist

* if there are 3 or more parameters lets move it to its own method

* chore: empty line

* fix: seems like we couldn't update the token

* chore: amend the test to mimic the order on the site config

* chore: oops - add back the welcome_notifications_live_at
This commit is contained in:
Ridhwana 2020-05-30 11:42:27 +02:00 committed by GitHub
parent b6a88778ad
commit af6d2325e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 580 additions and 568 deletions

View file

@ -28,32 +28,24 @@ class Internal::ConfigsController < Internal::ApplicationController
def config_params
allowed_params = %i[
favicon_url
ga_view_id ga_fetch_rate
logo_png
logo_svg
main_social_image
mascot_image_description
mascot_image_url
mascot_user_id
onboarding_taskcard_image
periodic_email_digest_max
periodic_email_digest_min
primary_sticker_image_url
shop_url
sidebar_tags
suggested_tags
twitter_hashtag
suggested_users
tagline
shop_url
payment_pointer
health_check_token
]
allowed_params = allowed_params |
campaign_params |
community_params |
mailchimp_params |
rate_limit_params
newsletter_params |
rate_limit_params |
mascot_params |
image_params |
onboarding_params
params.require(:site_config).permit(
allowed_params,
@ -97,10 +89,11 @@ class Internal::ConfigsController < Internal::ApplicationController
community_description
community_member_description
community_member_label
tagline
]
end
def mailchimp_params
def newsletter_params
%i[
mailchimp_community_moderators_id
mailchimp_newsletter_id
@ -119,4 +112,30 @@ class Internal::ConfigsController < Internal::ApplicationController
rate_limit_organization_creation
]
end
def mascot_params
%i[
mascot_image_description
mascot_image_url
mascot_user_id
]
end
def image_params
%i[
favicon_url
logo_png
logo_svg
main_social_image
primary_sticker_image_url
]
end
def onboarding_params
%i[
onboarding_taskcard_image
suggested_tags
suggested_users
]
end
end

View file

@ -11,49 +11,12 @@ class SiteConfig < RailsSettings::Base
# the cache, or call SiteConfig.clear_cache
cache_prefix { "v1" }
# Community Content
field :community_description, type: :string, default: "A constructive and inclusive social network. Open source and radically transparent."
field :community_member_description, type: :string, default: "amazing humans who code."
field :community_member_label, type: :string, default: "user"
field :tagline, type: :string, default: "We're a place where coders share, stay up-to-date and grow their careers."
# Mascot
field :mascot_user_id, type: :integer, default: 1
field :mascot_image_url, type: :string, default: "https://practicaldev-herokuapp-com.freetls.fastly.net/assets/sloan.png"
field :mascot_image_description, type: :string, default: "Sloan, the sloth mascot"
# Social Media and Email
field :staff_user_id, type: :integer, default: 1
field :social_media_handles, type: :hash, default: {
twitter: nil,
facebook: nil,
github: nil,
instagram: nil,
twitch: nil
}
field :twitter_hashtag, type: :string, default: "#DEVCommunity"
# Emails
field :email_addresses, type: :hash, default: {
default: "yo@dev.to",
business: "partners@dev.to",
privacy: "privacy@dev.to",
members: "members@dev.to"
}
# Meta keywords
field :meta_keywords, type: :hash, default: {
default: nil,
article: nil,
tag: nil
}
# API Tokens
field :health_check_token, type: :string, default: "secret"
# Authentication
field :authentication_providers, type: :array, default: Authentication::Providers.available
# Broadcast
field :welcome_notifications_live_at, type: :date
# Campaign
field :campaign_hero_html_variant_name, type: :string, default: ""
field :campaign_featured_tags, type: :array, default: %w[]
@ -62,10 +25,28 @@ class SiteConfig < RailsSettings::Base
field :campaign_url, type: :string, default: nil
field :campaign_articles_require_approval, type: :boolean, default: 0
# Onboarding
field :onboarding_taskcard_image, type: :string, default: "https://practicaldev-herokuapp-com.freetls.fastly.net/assets/staggered-dev.svg"
field :suggested_tags, type: :array, default: %w[beginners career computerscience javascript security ruby rails swift kotlin]
field :suggested_users, type: :array, default: %w[ben jess peter maestromac andy liana]
# Community Content
field :community_description, type: :string, default: "A constructive and inclusive social network. Open source and radically transparent."
field :community_member_description, type: :string, default: "amazing humans who code."
field :community_member_label, type: :string, default: "user"
field :tagline, type: :string, default: "We're a place where coders share, stay up-to-date and grow their careers."
# Emails
field :email_addresses, type: :hash, default: {
default: "yo@dev.to",
business: "partners@dev.to",
privacy: "privacy@dev.to",
members: "members@dev.to"
}
# Email digest frequency
field :periodic_email_digest_max, type: :integer, default: 0
field :periodic_email_digest_min, type: :integer, default: 2
# Google Analytics Reporting API v4
# <https://developers.google.com/analytics/devguides/reporting/core/v4>
field :ga_view_id, type: :string, default: ""
field :ga_fetch_rate, type: :integer, default: 25
# Images
field :main_social_image, type: :string, default: "https://thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png"
@ -74,8 +55,36 @@ class SiteConfig < RailsSettings::Base
field :logo_svg, type: :string, default: ""
field :primary_sticker_image_url, type: :string, default: "https://practicaldev-herokuapp-com.freetls.fastly.net/assets/rainbowdev.svg"
# Mascot
field :mascot_user_id, type: :integer, default: 1
field :mascot_image_url, type: :string, default: "https://practicaldev-herokuapp-com.freetls.fastly.net/assets/sloan.png"
field :mascot_image_description, type: :string, default: "Sloan, the sloth mascot"
# Meta keywords
field :meta_keywords, type: :hash, default: {
default: nil,
article: nil,
tag: nil
}
# Monetization
field :payment_pointer, type: :string, default: "$ilp.uphold.com/24HhrUGG7ekn" # Experimental
field :shop_url, type: :string, default: "https://shop.dev.to"
# Newsletter
# <https://mailchimp.com/developer/>
field :mailchimp_newsletter_id, type: :string, default: ""
field :mailchimp_sustaining_members_id, type: :string, default: ""
field :mailchimp_tag_moderators_id, type: :string, default: ""
field :mailchimp_community_moderators_id, type: :string, default: ""
# Mailchimp webhook secret. Part of the callback URL in the Mailchimp settings.
# <https://mailchimp.com/developer/guides/about-webhooks/#Webhooks_security>
field :mailchimp_incoming_webhook_secret, type: :string, default: ""
# Onboarding
field :onboarding_taskcard_image, type: :string, default: "https://practicaldev-herokuapp-com.freetls.fastly.net/assets/staggered-dev.svg"
field :suggested_tags, type: :array, default: %w[beginners career computerscience javascript security ruby rails swift kotlin]
field :suggested_users, type: :array, default: %w[ben jess peter maestromac andy liana]
# Rate limits
field :rate_limit_follow_count_daily, type: :integer, default: 500
@ -91,32 +100,20 @@ class SiteConfig < RailsSettings::Base
field :rate_limit_feedback_message_creation, type: :integer, default: 5
field :rate_limit_user_update, type: :integer, default: 5
# Google Analytics Reporting API v4
# <https://developers.google.com/analytics/devguides/reporting/core/v4>
field :ga_view_id, type: :string, default: ""
field :ga_fetch_rate, type: :integer, default: 25
# Mailchimp lists IDs
# <https://mailchimp.com/developer/>
field :mailchimp_newsletter_id, type: :string, default: ""
field :mailchimp_sustaining_members_id, type: :string, default: ""
field :mailchimp_tag_moderators_id, type: :string, default: ""
field :mailchimp_community_moderators_id, type: :string, default: ""
# Mailchimp webhook secret. Part of the callback URL in the Mailchimp settings.
# <https://mailchimp.com/developer/guides/about-webhooks/#Webhooks_security>
field :mailchimp_incoming_webhook_secret, type: :string, default: ""
# Email digest frequency
field :periodic_email_digest_max, type: :integer, default: 0
field :periodic_email_digest_min, type: :integer, default: 2
# Social Media
field :staff_user_id, type: :integer, default: 1
field :social_media_handles, type: :hash, default: {
twitter: nil,
facebook: nil,
github: nil,
instagram: nil,
twitch: nil
}
field :twitter_hashtag, type: :string, default: "#DEVCommunity"
# Tags
field :sidebar_tags, type: :array, default: %w[help challenge discuss explainlikeimfive meta watercooler]
# Shop
field :shop_url, type: :string, default: "https://shop.dev.to"
# Special API tokens
field :health_check_token, type: :string, default: "secret"
# Broadcast
field :welcome_notifications_live_at, type: :date
end

View file

@ -26,190 +26,20 @@
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Community Content",
header: "API Tokens",
state: "collapse",
target: "contentBodyContainer",
target: "apiBodyContainer",
expanded: "false"
} %>
<div id="contentBodyContainer" class="card-body collapse hide" aria-labelledby="contentBodyContainer">
<div id="apiBodyContainer" class="card-body collapse hide" aria-labelledby="apiBodyContainer">
<div class="form-group">
<%= f.label :community_description, "Community description" %>
<%= f.text_field :community_description,
<%= f.label :health_check_token, "Health Check Token" %>
<%= f.text_field :health_check_token,
class: "form-control",
value: SiteConfig.community_description,
placeholder: "A fabulous community of kind and welcoming people." %>
<div class="alert alert-info">Used in meta description tags etc.</div>
value: SiteConfig.health_check_token,
placeholder: "a secure token" %>
<div class="alert alert-info">Used to authenticate with your health check endpoints.</div>
</div>
<div class="form-group">
<%= f.label :community_member_description, "Community member description" %>
<%= f.text_field :community_member_description,
class: "form-control",
value: SiteConfig.community_member_description,
placeholder: "amazing humans who code." %>
<div class="alert alert-info">Used in pre-login banners.</div>
</div>
<div class="form-group">
<%= f.label :community_member_label, "Community member label" %>
<%= f.text_field :community_member_label,
class: "form-control",
value: SiteConfig.community_member_label,
placeholder: "" %>
<div class="alert alert-info">Used to determine what a member will be called e.g developer, hobbyist etc.</div>
</div>
<div class="form-group">
<%= f.label :tagline, "Tagline" %>
<%= f.text_field :tagline,
class: "form-control",
value: SiteConfig.tagline,
placeholder: "We're a place where coders share, stay up-to-date and grow their careers." %>
<div class="alert alert-info">Used in signup modal.</div>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Mascot",
state: "collapse",
target: "mascotBodyContainer",
expanded: "false"
} %>
<div id="mascotBodyContainer" class="card-body collapse hide" aria-labelledby="mascotBodyContainer">
<div class="form-group">
<%= f.label :mascot_user_id, "Mascot user ID" %>
<%= f.text_field :mascot_user_id,
class: "form-control",
value: SiteConfig.mascot_user_id,
min: 1,
placeholder: "1" %>
<div class="alert alert-info">User ID of the Mascot account</div>
</div>
<div class="form-group">
<%= f.label :mascot_image_url %>
<%= f.text_field :mascot_image_url,
class: "form-control",
value: SiteConfig.mascot_image_url,
placeholder: "https://image.url" %>
<div class="col-12">
<img alt="<%= SiteConfig.mascot_image_description %>" class="img-fluid" src="<%= SiteConfig.mascot_image_url %>" />
</div>
<div class="alert alert-info"> Used as the mascot image. </div>
</div>
<div class="form-group">
<%= f.label :mascot_image_description %>
<%= f.text_field :mascot_image_description,
class: "form-control",
value: SiteConfig.mascot_image_description %>
<div class="alert alert-info">Used as the alt text for the mascot image </div>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Social Media",
state: "collapse",
target: "socialMediaBodyContainer",
expanded: "false"
} %>
<div id="socialMediaBodyContainer" class="card-body collapse hide" aria-labelledby="socialMediaBodyContainer">
<div class="form-group">
<%= f.fields_for :social_media_handles do |social_media_field| %>
<% SiteConfig.social_media_handles.each do |platform, username| %>
<div>
<%= social_media_field.label platform %>
<%= social_media_field.text_field platform,
class: "form-control",
value: SiteConfig.social_media_handles[platform],
placeholder: "" %>
<div class="alert alert-info"><%= platform.capitalize %> Username</div>
</div>
<% end %>
<% end %>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Twitter Hashtag",
state: "collapse",
target: "twitterHashtagBodyContainer",
expanded: "false"
} %>
<div id="twitterHashtagBodyContainer" class="card-body collapse hide"
aria-labelledby="twitterHashtagBodyContainer">
<div class="form-group">
<%= f.label :twitter_hashtag %>
<%= f.text_field :twitter_hashtag,
class: "form-control",
value: SiteConfig.twitter_hashtag.to_s,
placeholder: "#DEVCommunity" %>
<div class="alert alert-info">Used as the twitter hashtag of the community</div>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Meta Keywords",
state: "collapse",
target: "metaKeywordsBodyContainer",
expanded: "false"
} %>
<div id="metaKeywordsBodyContainer" class="card-body collapse hide" aria-labelledby="metaKeywordsBodyContainer">
<div class="form-group">
<%= f.fields_for :meta_keywords do |meta_keywords_field| %>
<% SiteConfig.meta_keywords.each do |area, keywords| %>
<div>
<%= meta_keywords_field.label area %>
<%= meta_keywords_field.text_field area,
class: "form-control",
value: SiteConfig.meta_keywords[area],
placeholder: "" %>
<div class="alert alert-info"><%= area.capitalize %><%= " page" unless area == "default" %> keywords</div>
</div>
<% end %>
<% end %>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Emails",
state: "collapse",
target: "emailBodyContainer",
expanded: "false"
} %>
<div id="emailBodyContainer" class="card-body collapse hide" aria-labelledby="emailBodyContainer">
<div class="form-group">
<%= f.fields_for :email_addresses do |email_field| %>
<% SiteConfig.email_addresses.each do |type, address| %>
<div>
<%= email_field.label type %>
<%= email_field.text_field type,
class: "form-control",
value: SiteConfig.email_addresses[type],
placeholder: "" %>
<div class="alert alert-info"><%= type.capitalize %> Email</div>
</div>
<% end %>
<% end %>
</div>
</div>
</div>
@ -270,7 +100,7 @@
<div class="form-group">
<%= f.label :campaign_sidebar_image %>
<% if SiteConfig.campaign_sidebar_image %>
<% if SiteConfig.campaign_sidebar_image.present? %>
<div class="row mt-2">
<div class="col-12">
<img alt="Campaign sidebar image" class="img-fluid" src="<%= SiteConfig.campaign_sidebar_image %>" />
@ -307,46 +137,130 @@
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Onboarding",
header: "Community Content",
state: "collapse",
target: "onboardingBodyContainer",
target: "contentBodyContainer",
expanded: "false"
} %>
<div id="onboardingBodyContainer" class="card-body collapse hide" aria-labelledby="onboardingBodyContainer">
<div id="contentBodyContainer" class="card-body collapse hide" aria-labelledby="contentBodyContainer">
<div class="form-group">
<%= f.label :onboarding_taskcard_image %>
<%= f.text_field :onboarding_taskcard_image,
<%= f.label :community_description, "Community description" %>
<%= f.text_field :community_description,
class: "form-control",
value: SiteConfig.onboarding_taskcard_image,
placeholder: "https://image.url" %>
<div class="row mt-2">
<div class="col-12">
<img alt="main social image" class="img-fluid" src="<%= SiteConfig.onboarding_taskcard_image %>" />
</div>
<div class="col-12">
<div class="alert alert-info"> Used as the onboarding task-card image </div>
</div>
</div>
value: SiteConfig.community_description,
placeholder: "A fabulous community of kind and welcoming people." %>
<div class="alert alert-info">Used in meta description tags etc.</div>
</div>
<div class="form-group">
<%= f.label :suggested_users %>
<%= f.text_field :suggested_users,
<%= f.label :community_member_description, "Community member description" %>
<%= f.text_field :community_member_description,
class: "form-control",
value: SiteConfig.suggested_users.join(","),
placeholder: "List of valid usernames: comma separated, letters only e.g. ben,jess,peter,maestromac,andy,liana" %>
<div class="alert alert-info">Determines which users are suggested to follow to new users during onboarding (comma
separated, letters only). Please note that these users will be shown as a fallback if no recently-active commenters or producers can be suggested.</div>
value: SiteConfig.community_member_description,
placeholder: "amazing humans who code." %>
<div class="alert alert-info">Used in pre-login banners.</div>
</div>
<div class="form-group">
<%= f.label :suggested_tags %>
<%= f.text_field :suggested_tags,
<%= f.label :community_member_label, "Community member label" %>
<%= f.text_field :community_member_label,
class: "form-control",
value: SiteConfig.suggested_tags.join(","),
placeholder: "List of valid tags: comma separated, letters only e.g. beginners,javascript,ruby,swift,kotlin" %>
<div class="alert alert-info">Determines which tags are suggested to new users during onboarding (comma
separated, letters only)</div>
value: SiteConfig.community_member_label,
placeholder: "" %>
<div class="alert alert-info">Used to determine what a member will be called e.g developer, hobbyist etc.</div>
</div>
<div class="form-group">
<%= f.label :tagline, "Tagline" %>
<%= f.text_field :tagline,
class: "form-control",
value: SiteConfig.tagline,
placeholder: "We're a place where coders share, stay up-to-date and grow their careers." %>
<div class="alert alert-info">Used in signup modal.</div>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Emails",
state: "collapse",
target: "emailBodyContainer",
expanded: "false"
} %>
<div id="emailBodyContainer" class="card-body collapse hide" aria-labelledby="emailBodyContainer">
<div class="form-group">
<%= f.fields_for :email_addresses do |email_field| %>
<% SiteConfig.email_addresses.each do |type, address| %>
<div>
<%= email_field.label type %>
<%= email_field.text_field type,
class: "form-control",
value: SiteConfig.email_addresses[type],
placeholder: "" %>
<div class="alert alert-info"><%= type.capitalize %> Email</div>
</div>
<% end %>
<% end %>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Email digest frequency",
state: "collapse",
target: "emailDigestBodyContainer",
expanded: "false"
} %>
<div id="emailDigestBodyContainer" class="card-body collapse hide" aria-labelledby="emailDigestBodyContainer">
<div class="form-group">
<%= f.label :periodic_email_digest_max %>
<%= f.number_field :periodic_email_digest_max,
class: "form-control",
value: SiteConfig.periodic_email_digest_max,
placeholder: 0 %>
<div class="alert alert-info">Determines the maximum for the periodic email digest</div>
</div>
<div class="form-group">
<%= f.label :periodic_email_digest_min %>
<%= f.number_field :periodic_email_digest_min,
class: "form-control",
value: SiteConfig.periodic_email_digest_min,
placeholder: 2 %>
<div class="alert alert-info">Determines the mininum for the periodic email digest</div>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Google Analytics Reporting API v4",
state: "collapse",
target: "gaBodyContainer",
expanded: "false"
} %>
<div id="gaBodyContainer" class="card-body collapse hide" aria-labelledby="gaBodyContainer">
<div class="form-group">
<%= f.label :ga_view_id, "View ID" %>
<%= f.text_field :ga_view_id,
class: "form-control",
value: SiteConfig.ga_view_id %>
<div class="alert alert-info">Google Analytics Reporting API v4 - View ID</div>
</div>
<div class="form-group">
<%= f.label :ga_fetch_rate, "Fetch rate" %>
<%= f.number_field :ga_fetch_rate,
class: "form-control",
value: SiteConfig.ga_fetch_rate,
min: 1,
placeholder: 1 %>
<div class="alert alert-info">Determines how often the site updates its Google Analytics stats</div>
</div>
</div>
</div>
@ -426,51 +340,43 @@
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Rate limits",
header: "Mascot",
state: "collapse",
target: "rateLimitsBodyContainer",
target: "mascotBodyContainer",
expanded: "false"
} %>
<div id="rateLimitsBodyContainer" class="card-body collapse hide" aria-labelledby="rateLimitsBodyContainer">
<% configurable_rate_limits.each do |key, field_hash| %>
<div class="form-group">
<%= f.label key %>
<%= f.number_field key,
class: "form-control",
value: SiteConfig.send(key),
min: field_hash[:min],
placeholder: field_hash[:placeholder] %>
<div class="alert alert-info"><%= field_hash[:description] %></div>
</div>
<% end %>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Google Analytics Reporting API v4",
state: "collapse",
target: "gaBodyContainer",
expanded: "false"
} %>
<div id="gaBodyContainer" class="card-body collapse hide" aria-labelledby="gaBodyContainer">
<div id="mascotBodyContainer" class="card-body collapse hide" aria-labelledby="mascotBodyContainer">
<div class="form-group">
<%= f.label :ga_view_id, "View ID" %>
<%= f.text_field :ga_view_id,
<%= f.label :mascot_user_id, "Mascot user ID" %>
<%= f.text_field :mascot_user_id,
class: "form-control",
value: SiteConfig.ga_view_id %>
<div class="alert alert-info">Google Analytics Reporting API v4 - View ID</div>
value: SiteConfig.mascot_user_id,
min: 1,
placeholder: "1" %>
<div class="alert alert-info">User ID of the Mascot account</div>
</div>
<div class="form-group">
<%= f.label :ga_fetch_rate, "Fetch rate" %>
<%= f.number_field :ga_fetch_rate,
class: "form-control",
value: SiteConfig.ga_fetch_rate,
min: 1,
placeholder: 1 %>
<div class="alert alert-info">Determines how often the site updates its Google Analytics stats</div>
<%= f.label :mascot_image_url %>
<%= f.text_field :mascot_image_url,
class: "form-control",
value: SiteConfig.mascot_image_url,
placeholder: "https://image.url" %>
<div class="col-12">
<img alt="<%= SiteConfig.mascot_image_description %>" class="img-fluid" src="<%= SiteConfig.mascot_image_url %>" />
</div>
<div class="alert alert-info"> Used as the mascot image. </div>
</div>
<div class="form-group">
<%= f.label :mascot_image_description %>
<%= f.text_field :mascot_image_description,
class: "form-control",
value: SiteConfig.mascot_image_description %>
<div class="alert alert-info">Used as the alt text for the mascot image </div>
</div>
</div>
</div>
@ -478,12 +384,67 @@
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Mailchimp Lists IDs",
header: "Meta Keywords",
state: "collapse",
target: "mailchimpListBodyContainer",
target: "metaKeywordsBodyContainer",
expanded: "false"
} %>
<div id="mailchimpListBodyContainer" class="card-body collapse hide" aria-labelledby="mailchimpListBodyContainer">
<div id="metaKeywordsBodyContainer" class="card-body collapse hide" aria-labelledby="metaKeywordsBodyContainer">
<div class="form-group">
<%= f.fields_for :meta_keywords do |meta_keywords_field| %>
<% SiteConfig.meta_keywords.each do |area, keywords| %>
<div>
<%= meta_keywords_field.label area %>
<%= meta_keywords_field.text_field area,
class: "form-control",
value: SiteConfig.meta_keywords[area],
placeholder: "" %>
<div class="alert alert-info"><%= area.capitalize %><%= " page" unless area == "default" %> keywords</div>
</div>
<% end %>
<% end %>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Monetization",
state: "collapse",
target: "monetizationBodyContainer",
expanded: "false"
} %>
<div id="monetizationBodyContainer" class="card-body collapse hide" aria-labelledby="monetizationBodyContainer">
<div class="form-group">
<%= f.label :shop_url %>
<%= f.text_field :shop_url,
class: "form-control",
value: SiteConfig.shop_url,
placeholder: "Shop url" %>
<div class="alert alert-info">Used as the shop url of the community</div>
</div>
<div class="form-group">
<%= f.label :payment_pointer %>
<%= f.text_field :payment_pointer,
class: "form-control",
value: SiteConfig.payment_pointer,
placeholder: "$pay.somethinglikethis.co/value" %>
<div class="alert alert-info">Used for site-wide web monetization (<a href="https://github.com/thepracticaldev/dev.to/pull/6345">experimental</a>)</div>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Newsletter",
state: "collapse",
target: "newsletterBodyContainer",
expanded: "false"
} %>
<div id="newsletterBodyContainer" class="card-body collapse hide" aria-labelledby="newsletterBodyContainer">
<div class="form-group">
<%= f.label :mailchimp_newsletter_id, "Main Newsletter" %>
<%= f.text_field :mailchimp_newsletter_id,
@ -521,28 +482,103 @@
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Email digest frequency",
header: "Onboarding",
state: "collapse",
target: "emailDigestBodyContainer",
target: "onboardingBodyContainer",
expanded: "false"
} %>
<div id="emailDigestBodyContainer" class="card-body collapse hide" aria-labelledby="emailDigestBodyContainer">
<div id="onboardingBodyContainer" class="card-body collapse hide" aria-labelledby="onboardingBodyContainer">
<div class="form-group">
<%= f.label :periodic_email_digest_max %>
<%= f.number_field :periodic_email_digest_max,
class: "form-control",
value: SiteConfig.periodic_email_digest_max,
placeholder: 0 %>
<div class="alert alert-info">Determines the maximum for the periodic email digest</div>
<%= f.label :onboarding_taskcard_image %>
<%= f.text_field :onboarding_taskcard_image,
class: "form-control",
value: SiteConfig.onboarding_taskcard_image,
placeholder: "https://image.url" %>
<div class="row mt-2">
<div class="col-12">
<img alt="main social image" class="img-fluid" src="<%= SiteConfig.onboarding_taskcard_image %>" />
</div>
<div class="col-12">
<div class="alert alert-info"> Used as the onboarding task-card image </div>
</div>
</div>
</div>
<div class="form-group">
<%= f.label :periodic_email_digest_min %>
<%= f.number_field :periodic_email_digest_min,
class: "form-control",
value: SiteConfig.periodic_email_digest_min,
placeholder: 2 %>
<div class="alert alert-info">Determines the mininum for the periodic email digest</div>
<%= f.label :suggested_users %>
<%= f.text_field :suggested_users,
class: "form-control",
value: SiteConfig.suggested_users.join(","),
placeholder: "List of valid usernames: comma separated, letters only e.g. ben,jess,peter,maestromac,andy,liana" %>
<div class="alert alert-info">Determines which users are suggested to follow to new users during onboarding (comma
separated, letters only). Please note that these users will be shown as a fallback if no recently-active commenters or producers can be suggested.</div>
</div>
<div class="form-group">
<%= f.label :suggested_tags %>
<%= f.text_field :suggested_tags,
class: "form-control",
value: SiteConfig.suggested_tags.join(","),
placeholder: "List of valid tags: comma separated, letters only e.g. beginners,javascript,ruby,swift,kotlin" %>
<div class="alert alert-info">Determines which tags are suggested to new users during onboarding (comma
separated, letters only)</div>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Rate limits",
state: "collapse",
target: "rateLimitsBodyContainer",
expanded: "false"
} %>
<div id="rateLimitsBodyContainer" class="card-body collapse hide" aria-labelledby="rateLimitsBodyContainer">
<% configurable_rate_limits.each do |key, field_hash| %>
<div class="form-group">
<%= f.label key %>
<%= f.number_field key,
class: "form-control",
value: SiteConfig.send(key),
min: field_hash[:min],
placeholder: field_hash[:placeholder] %>
<div class="alert alert-info"><%= field_hash[:description] %></div>
</div>
<% end %>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Social Media",
state: "collapse",
target: "socialMediaBodyContainer",
expanded: "false"
} %>
<div id="socialMediaBodyContainer" class="card-body collapse hide" aria-labelledby="socialMediaBodyContainer">
<div class="form-group">
<%= f.label :twitter_hashtag %>
<%= f.text_field :twitter_hashtag,
class: "form-control",
value: SiteConfig.twitter_hashtag.to_s,
placeholder: "#DEVCommunity" %>
<div class="alert alert-info">Used as the twitter hashtag of the community</div>
</div>
<div class="form-group">
<%= f.fields_for :social_media_handles do |social_media_field| %>
<% SiteConfig.social_media_handles.each do |platform, username| %>
<div>
<%= social_media_field.label platform %>
<%= social_media_field.text_field platform,
class: "form-control",
value: SiteConfig.social_media_handles[platform],
placeholder: "" %>
<div class="alert alert-info"><%= platform.capitalize %> Username</div>
</div>
<% end %>
<% end %>
</div>
</div>
</div>
@ -567,55 +603,6 @@
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "Monetization",
state: "collapse",
target: "monetizationBodyContainer",
expanded: "false"
} %>
<div id="monetizationBodyContainer" class="card-body collapse hide" aria-labelledby="monetizationBodyContainer">
<div class="form-group">
<%= f.label :shop_url %>
<%= f.text_field :shop_url,
class: "form-control",
value: SiteConfig.shop_url,
placeholder: "Shop url" %>
<div class="alert alert-info">Used as the shop url of the community</div>
</div>
<div class="form-group">
<%= f.label :payment_pointer %>
<%= f.text_field :payment_pointer,
class: "form-control",
value: SiteConfig.payment_pointer,
placeholder: "$pay.somethinglikethis.co/value" %>
<div class="alert alert-info">Used for site-wide web monetization (<a href="https://github.com/thepracticaldev/dev.to/pull/6345">experimental</a>)</div>
</div>
</div>
</div>
<div class="card mt-3">
<%= render partial: "card_header",
locals: {
header: "API",
state: "collapse",
target: "apiBodyContainer",
expanded: "false"
} %>
<div id="apiBodyContainer" class="card-body collapse hide" aria-labelledby="apiBodyContainer">
<div class="form-group">
<%= f.label :health_check_token, "Health Check Token" %>
<%= f.text_field :health_check_token,
class: "form-control",
value: SiteConfig.health_check_token,
placeholder: "a secure token" %>
<div class="alert alert-info">Used to authenticate with your health check endpoints.</div>
</div>
</div>
</div>
<% if current_user.has_role?(:single_resource_admin, Config) %>
<div class="card mt-3">
<div class="card-header">Confirm and Submit</div>

View file

@ -39,7 +39,30 @@ RSpec.describe "/internal/config", type: :request do
sign_in(admin_plus_config)
end
describe "community content" do
describe "API tokens" do
it "updates the health_check_token" do
token = "#{rand(20)}"
post "/internal/config", params: { site_config: { health_check_token: token }, confirmation: confirmation_message }
expect(SiteConfig.health_check_token).to eq token
end
end
describe "Authentication" do
it "updates enabled authentication providers" do
enabled = Array.wrap(Authentication::Providers.available.first.to_s)
post "/internal/config", params: { site_config: { authentication_providers: enabled }, confirmation: confirmation_message }
expect(SiteConfig.authentication_providers).to eq(enabled)
end
it "strips empty elements" do
provider = Authentication::Providers.available.first.to_s
enabled = [provider, "", nil]
post "/internal/config", params: { site_config: { authentication_providers: enabled }, confirmation: confirmation_message }
expect(SiteConfig.authentication_providers).to eq([provider])
end
end
describe "Community Content" do
it "updates the community_description" do
description = "Hey hey #{rand(100)}"
post "/internal/config", params: { site_config: { community_description: description }, confirmation: confirmation_message }
@ -65,54 +88,7 @@ RSpec.describe "/internal/config", type: :request do
end
end
describe "mascot" do
it "updates the mascot_user_id" do
expected_mascot_user_id = 2
post "/internal/config", params: { site_config: { mascot_user_id: expected_mascot_user_id }, confirmation: confirmation_message }
expect(SiteConfig.mascot_user_id).to eq(expected_mascot_user_id)
end
it "updates mascot_image_url" do
expected_image_url = "https://dummyimage.com/300x300"
post "/internal/config", params: { site_config: { mascot_image_url: expected_image_url }, confirmation: confirmation_message }
expect(SiteConfig.mascot_image_url).to eq(expected_image_url)
end
it "updates mascot_image_description" do
description = "Hey hey #{rand(100)}"
post "/internal/config", params: { site_config: { mascot_image_description: description }, confirmation: confirmation_message }
expect(SiteConfig.mascot_image_description).to eq(description)
end
end
describe "social media" do
it "does not allow the staff_user_id to be updated" do
expect(SiteConfig.staff_user_id).to eq(1)
post "/internal/config", params: { site_config: { staff_user_id: 2 }, confirmation: confirmation_message }
expect(SiteConfig.staff_user_id).to eq(1)
end
it "updates social_media_handles" do
expected_handle = { "facebook" => "tpd", "github" => "", "instagram" => "", "twitch" => "", "twitter" => "" }
post "/internal/config", params: { site_config: { social_media_handles: expected_handle },
confirmation: confirmation_message }
expect(SiteConfig.social_media_handles[:facebook]).to eq("tpd")
expect(SiteConfig.social_media_handles[:github]).to eq("")
end
end
describe "meta keywords" do
it "updates meta keywords" do
expected_keywords = { "default" => "software, people", "article" => "user, experience", "tag" => "bye" }
post "/internal/config", params: { site_config: { meta_keywords: expected_keywords },
confirmation: confirmation_message }
expect(SiteConfig.meta_keywords[:default]).to eq("software, people")
expect(SiteConfig.meta_keywords[:article]).to eq("user, experience")
expect(SiteConfig.meta_keywords[:tag]).to eq("bye")
end
end
describe "emails" do
describe "Emails" do
it "updates email_addresses" do
expected_email_addresses = {
default: "foo@bar.to",
@ -129,35 +105,36 @@ RSpec.describe "/internal/config", type: :request do
end
end
describe "onboarding" do
it "updates onboarding_taskcard_image" do
expected_image_url = "https://dummyimage.com/300x300"
post "/internal/config", params: { site_config: { onboarding_taskcard_image: expected_image_url }, confirmation: confirmation_message }
expect(SiteConfig.onboarding_taskcard_image).to eq(expected_image_url)
describe "Email digest frequency" do
it "updates periodic_email_digest_max" do
post "/internal/config", params: { site_config: { periodic_email_digest_max: 1 }, confirmation: confirmation_message }
expect(SiteConfig.periodic_email_digest_max).to eq(1)
end
it "removes space suggested_tags" do
post "/internal/config", params: { site_config: { suggested_tags: "hey, haha,hoho, bobo fofo" }, confirmation: confirmation_message }
expect(SiteConfig.suggested_tags).to eq(%w[hey haha hoho bobofofo])
it "updates periodic_email_digest_min" do
post "/internal/config", params: { site_config: { periodic_email_digest_min: 3 }, confirmation: confirmation_message }
expect(SiteConfig.periodic_email_digest_min).to eq(3)
end
it "downcases suggested_tags" do
post "/internal/config", params: { site_config: { suggested_tags: "hey, haha,hoHo, Bobo Fofo" }, confirmation: confirmation_message }
expect(SiteConfig.suggested_tags).to eq(%w[hey haha hoho bobofofo])
end
it "removes space suggested_users" do
post "/internal/config", params: { site_config: { suggested_users: "piglet, tigger,eeyore, Christopher Robin, kanga,roo" }, confirmation: confirmation_message }
expect(SiteConfig.suggested_users).to eq(%w[piglet tigger eeyore christopherrobin kanga roo])
end
it "downcases suggested_users" do
post "/internal/config", params: { site_config: { suggested_users: "piglet, tigger,EEYORE, Christopher Robin, KANGA,RoO" }, confirmation: confirmation_message }
expect(SiteConfig.suggested_users).to eq(%w[piglet tigger eeyore christopherrobin kanga roo])
it "rejects update without proper confirmation" do
expect { post "/internal/config", params: { site_config: { periodic_email_digest_min: 6 }, confirmation: "Incorrect yo!" } }.to raise_error Pundit::NotAuthorizedError
expect(SiteConfig.periodic_email_digest_min).not_to eq(6)
end
end
describe "images" do
describe "Google Analytics Reporting API v4" do
it "updates ga_view_id" do
post "/internal/config", params: { site_config: { ga_view_id: "abc" }, confirmation: confirmation_message }
expect(SiteConfig.ga_view_id).to eq("abc")
end
it "updates ga_fetch_rate" do
post "/internal/config", params: { site_config: { ga_fetch_rate: 3 }, confirmation: confirmation_message }
expect(SiteConfig.ga_fetch_rate).to eq(3)
end
end
describe "Images" do
it "updates main_social_image" do
expected_image_url = "https://dummyimage.com/300x300"
post "/internal/config", params: { site_config: { main_social_image: expected_image_url }, confirmation: confirmation_message }
@ -194,14 +171,126 @@ RSpec.describe "/internal/config", type: :request do
end
end
describe "monetization" do
describe "Mascot" do
it "updates the mascot_user_id" do
expected_mascot_user_id = 2
post "/internal/config", params: { site_config: { mascot_user_id: expected_mascot_user_id }, confirmation: confirmation_message }
expect(SiteConfig.mascot_user_id).to eq(expected_mascot_user_id)
end
it "updates mascot_image_url" do
expected_image_url = "https://dummyimage.com/300x300"
post "/internal/config", params: { site_config: { mascot_image_url: expected_image_url }, confirmation: confirmation_message }
expect(SiteConfig.mascot_image_url).to eq(expected_image_url)
end
it "updates mascot_image_description" do
description = "Hey hey #{rand(100)}"
post "/internal/config", params: { site_config: { mascot_image_description: description }, confirmation: confirmation_message }
expect(SiteConfig.mascot_image_description).to eq(description)
end
end
describe "Meta Keywords" do
it "updates meta keywords" do
expected_keywords = { "default" => "software, people", "article" => "user, experience", "tag" => "bye" }
post "/internal/config", params: { site_config: { meta_keywords: expected_keywords },
confirmation: confirmation_message }
expect(SiteConfig.meta_keywords[:default]).to eq("software, people")
expect(SiteConfig.meta_keywords[:article]).to eq("user, experience")
expect(SiteConfig.meta_keywords[:tag]).to eq("bye")
end
end
describe "Monetization" do
it "updates payment pointer" do
post "/internal/config", params: { site_config: { payment_pointer: "$pay.yo" }, confirmation: confirmation_message }
expect(SiteConfig.payment_pointer).to eq("$pay.yo")
end
describe "Shop" do
it "rejects update to shop_url without proper confirmation" do
expected_shop_url = "https://qshop.dev.to"
expect do
params = { site_config: { shop_url: expected_shop_url }, confirmation: "Incorrect confirmation" }
post "/internal/config", params: params
end.to raise_error(Pundit::NotAuthorizedError)
expect(SiteConfig.shop_url).not_to eq(expected_shop_url)
end
it "sets shop_url to nil" do
previous_shop_url = SiteConfig.shop_url
post "/internal/config", params: { site_config: { shop_url: "" }, confirmation: confirmation_message }
expect(SiteConfig.shop_url).to eq("")
get "/privacy"
expect(response.body).not_to include(previous_shop_url)
expect(response.body).not_to include("#{ApplicationConfig['COMMUNITY_NAME']} Shop")
end
it "updates shop url" do
expected_shop_url = "https://qshop.dev.to"
post "/internal/config", params: { site_config: { shop_url: expected_shop_url }, confirmation: confirmation_message }
expect(SiteConfig.shop_url).to eq(expected_shop_url)
get "/privacy"
expect(response.body).to include(expected_shop_url)
expect(response.body).to include("#{ApplicationConfig['COMMUNITY_NAME']} Shop")
end
end
end
describe "rate limits" do
describe "Newsletter" do
it "updates mailchimp_newsletter_id" do
post "/internal/config", params: { site_config: { mailchimp_newsletter_id: "abc" }, confirmation: confirmation_message }
expect(SiteConfig.mailchimp_newsletter_id).to eq("abc")
end
it "updates mailchimp_sustaining_members_id" do
post "/internal/config", params: { site_config: { mailchimp_sustaining_members_id: "abc" }, confirmation: confirmation_message }
expect(SiteConfig.mailchimp_sustaining_members_id).to eq("abc")
end
it "updates mailchimp_tag_moderators_id" do
post "/internal/config", params: { site_config: { mailchimp_tag_moderators_id: "abc" }, confirmation: confirmation_message }
expect(SiteConfig.mailchimp_tag_moderators_id).to eq("abc")
end
it "updates mailchimp_community_moderators_id" do
post "/internal/config", params: { site_config: { mailchimp_community_moderators_id: "abc" }, confirmation: confirmation_message }
expect(SiteConfig.mailchimp_community_moderators_id).to eq("abc")
end
end
describe "Onboarding" do
it "updates onboarding_taskcard_image" do
expected_image_url = "https://dummyimage.com/300x300"
post "/internal/config", params: { site_config: { onboarding_taskcard_image: expected_image_url }, confirmation: confirmation_message }
expect(SiteConfig.onboarding_taskcard_image).to eq(expected_image_url)
end
it "removes space suggested_tags" do
post "/internal/config", params: { site_config: { suggested_tags: "hey, haha,hoho, bobo fofo" }, confirmation: confirmation_message }
expect(SiteConfig.suggested_tags).to eq(%w[hey haha hoho bobofofo])
end
it "downcases suggested_tags" do
post "/internal/config", params: { site_config: { suggested_tags: "hey, haha,hoHo, Bobo Fofo" }, confirmation: confirmation_message }
expect(SiteConfig.suggested_tags).to eq(%w[hey haha hoho bobofofo])
end
it "removes space suggested_users" do
post "/internal/config", params: { site_config: { suggested_users: "piglet, tigger,eeyore, Christopher Robin, kanga,roo" }, confirmation: confirmation_message }
expect(SiteConfig.suggested_users).to eq(%w[piglet tigger eeyore christopherrobin kanga roo])
end
it "downcases suggested_users" do
post "/internal/config", params: { site_config: { suggested_users: "piglet, tigger,EEYORE, Christopher Robin, KANGA,RoO" }, confirmation: confirmation_message }
expect(SiteConfig.suggested_users).to eq(%w[piglet tigger eeyore christopherrobin kanga roo])
end
end
describe "Rate Limits" do
it "updates rate_limit_follow_count_daily" do
expect do
post "/internal/config", params: { site_config: { rate_limit_follow_count_daily: 3 }, confirmation: confirmation_message }
@ -239,54 +328,34 @@ RSpec.describe "/internal/config", type: :request do
end
end
describe "Google Analytics Reporting API v4" do
it "updates ga_view_id" do
post "/internal/config", params: { site_config: { ga_view_id: "abc" }, confirmation: confirmation_message }
expect(SiteConfig.ga_view_id).to eq("abc")
describe "Social Media" do
it "does not allow the staff_user_id to be updated" do
expect(SiteConfig.staff_user_id).to eq(1)
post "/internal/config", params: { site_config: { staff_user_id: 2 }, confirmation: confirmation_message }
expect(SiteConfig.staff_user_id).to eq(1)
end
it "updates ga_fetch_rate" do
post "/internal/config", params: { site_config: { ga_fetch_rate: 3 }, confirmation: confirmation_message }
expect(SiteConfig.ga_fetch_rate).to eq(3)
end
end
describe "Mailchimp lists IDs" do
it "updates mailchimp_newsletter_id" do
post "/internal/config", params: { site_config: { mailchimp_newsletter_id: "abc" }, confirmation: confirmation_message }
expect(SiteConfig.mailchimp_newsletter_id).to eq("abc")
it "updates social_media_handles" do
expected_handle = { "facebook" => "tpd", "github" => "", "instagram" => "", "twitch" => "", "twitter" => "" }
post "/internal/config", params: { site_config: { social_media_handles: expected_handle },
confirmation: confirmation_message }
expect(SiteConfig.social_media_handles[:facebook]).to eq("tpd")
expect(SiteConfig.social_media_handles[:github]).to eq("")
end
it "updates mailchimp_sustaining_members_id" do
post "/internal/config", params: { site_config: { mailchimp_sustaining_members_id: "abc" }, confirmation: confirmation_message }
expect(SiteConfig.mailchimp_sustaining_members_id).to eq("abc")
end
describe "twitter_hashtag" do
twitter_hashtag = "#DEVCommunity"
params = { site_config: { twitter_hashtag: twitter_hashtag }, confirmation: "Incorrect confirmation" }
it "updates mailchimp_tag_moderators_id" do
post "/internal/config", params: { site_config: { mailchimp_tag_moderators_id: "abc" }, confirmation: confirmation_message }
expect(SiteConfig.mailchimp_tag_moderators_id).to eq("abc")
end
it "does not update the twitter hashtag" do
expect { post "/internal/config", params: params }.to raise_error Pundit::NotAuthorizedError
end
it "updates mailchimp_community_moderators_id" do
post "/internal/config", params: { site_config: { mailchimp_community_moderators_id: "abc" }, confirmation: confirmation_message }
expect(SiteConfig.mailchimp_community_moderators_id).to eq("abc")
end
end
describe "Email digest frequency" do
it "updates periodic_email_digest_max" do
post "/internal/config", params: { site_config: { periodic_email_digest_max: 1 }, confirmation: confirmation_message }
expect(SiteConfig.periodic_email_digest_max).to eq(1)
end
it "updates periodic_email_digest_min" do
post "/internal/config", params: { site_config: { periodic_email_digest_min: 3 }, confirmation: confirmation_message }
expect(SiteConfig.periodic_email_digest_min).to eq(3)
end
it "rejects update without proper confirmation" do
expect { post "/internal/config", params: { site_config: { periodic_email_digest_min: 6 }, confirmation: "Incorrect yo!" } }.to raise_error Pundit::NotAuthorizedError
expect(SiteConfig.periodic_email_digest_min).not_to eq(6)
it "updates the twitter hashtag" do
params["confirmation"] = confirmation_message
post "/internal/config", params: params
expect(SiteConfig.twitter_hashtag.to_s).to eq twitter_hashtag
end
end
end
@ -302,66 +371,6 @@ RSpec.describe "/internal/config", type: :request do
end
end
describe "Shop" do
it "rejects update to shop_url without proper confirmation" do
expected_shop_url = "https://qshop.dev.to"
expect do
params = { site_config: { shop_url: expected_shop_url }, confirmation: "Incorrect confirmation" }
post "/internal/config", params: params
end.to raise_error(Pundit::NotAuthorizedError)
expect(SiteConfig.shop_url).not_to eq(expected_shop_url)
end
it "sets shop_url to nil" do
previous_shop_url = SiteConfig.shop_url
post "/internal/config", params: { site_config: { shop_url: "" }, confirmation: confirmation_message }
expect(SiteConfig.shop_url).to eq("")
get "/privacy"
expect(response.body).not_to include(previous_shop_url)
expect(response.body).not_to include("#{ApplicationConfig['COMMUNITY_NAME']} Shop")
end
it "updates shop url" do
expected_shop_url = "https://qshop.dev.to"
post "/internal/config", params: { site_config: { shop_url: expected_shop_url }, confirmation: confirmation_message }
expect(SiteConfig.shop_url).to eq(expected_shop_url)
get "/privacy"
expect(response.body).to include(expected_shop_url)
expect(response.body).to include("#{ApplicationConfig['COMMUNITY_NAME']} Shop")
end
end
describe "Authentication" do
it "updates enabled authentication providers" do
enabled = Array.wrap(Authentication::Providers.available.first.to_s)
post "/internal/config", params: { site_config: { authentication_providers: enabled }, confirmation: confirmation_message }
expect(SiteConfig.authentication_providers).to eq(enabled)
end
it "strips empty elements" do
provider = Authentication::Providers.available.first.to_s
enabled = [provider, "", nil]
post "/internal/config", params: { site_config: { authentication_providers: enabled }, confirmation: confirmation_message }
expect(SiteConfig.authentication_providers).to eq([provider])
end
end
describe "twitter_hashtag" do
twitter_hashtag = "#DEVCommunity"
params = { site_config: { twitter_hashtag: twitter_hashtag }, confirmation: "Incorrect confirmation" }
it "does not update the twitter hashtag" do
expect { post "/internal/config", params: params }.to raise_error Pundit::NotAuthorizedError
end
it "updates the twitter hashtag" do
params["confirmation"] = confirmation_message
post "/internal/config", params: params
expect(SiteConfig.twitter_hashtag.to_s).to eq twitter_hashtag
end
end
end
end
# rubocop:enable RSpec/NestedGroups