discourse/spec/models/admin_dashboard_problem_spec.rb
David Taylor 0e303c7f5d
FEATURE: Automatically generate optimized site metadata icons (#7372)
This change automatically resizes icons for various purposes. Admins can now upload `logo` and `logo_small`, and everything else will be auto-generated. Specific icons can still be uploaded separately if required.

## Core

- Adds an SiteIconManager module which manages automatic resizing and fallback

- Icons are looked up in the OptimizedImage table at runtime, and then cached in Redis. If the resized version is missing for some reason, then most icons will fall back to the original files. Some icons (e.g. PWA Manifest) will return `nil` (because an incorrectly sized icon is worse than a missing icon). 

- `SiteSetting.site_large_icon_url` will return the optimized version, including any fallback. `SiteSetting.large_icon` continues to return the upload object. This means that (almost) no changes are required in core/plugins to support this new system.

- Icons are resized whenever a relevant site setting is changed, and during post-deploy migrations

## Wizard

- Allows `requiresRefresh` wizard steps to reload data via AJAX instead of a full page reload

- Add placeholders to the **icons** step of the wizard, which automatically update from the "Square Logo"

- Various copy updates to support the changes

- Remove the "upload-time" resizing for `large_icon`. This is no longer required.

## Site Settings UX

- Move logo/icon settings under a new "Branding" tab

- Various copy changes to support the changes

- Adds placeholder support to the `image-uploader` component

- Automatically reloads site settings after saving. This allows setting placeholders to change based on changes to other settings

- Upload site settings will be assigned a placeholder if SiteIconManager `responds_to?` an icon of the same name

## Dashboard Warnings

- Remove PWA icon and PWA title warnings. Both are now handled automatically.

## Bonus

- Updated the sketch logos to use @awesomerobot's new high-res designs
2019-05-01 14:44:45 +01:00

384 lines
12 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
describe AdminDashboardData do
describe "adding new checks" do
after do
AdminDashboardData.reset_problem_checks
end
it 'calls the passed block' do
called = false
AdminDashboardData.add_problem_check do
called = true
end
AdminDashboardData.fetch_problems
expect(called).to eq(true)
AdminDashboardData.fetch_problems(check_force_https: true)
expect(called).to eq(true)
end
it 'calls the passed method' do
$test_AdminDashboardData_global = false
class AdminDashboardData
def my_test_method
$test_AdminDashboardData_global = true
end
end
AdminDashboardData.add_problem_check :my_test_method
AdminDashboardData.fetch_problems
expect($test_AdminDashboardData_global).to eq(true)
$test_AdminDashboardData_global = nil
end
end
describe "rails_env_check" do
subject { described_class.new.rails_env_check }
it 'returns nil when running in production mode' do
Rails.stubs(env: ActiveSupport::StringInquirer.new('production'))
expect(subject).to be_nil
end
it 'returns a string when running in development mode' do
Rails.stubs(env: ActiveSupport::StringInquirer.new('development'))
expect(subject).to_not be_nil
end
it 'returns a string when running in test mode' do
Rails.stubs(env: ActiveSupport::StringInquirer.new('test'))
expect(subject).to_not be_nil
end
end
describe 'host_names_check' do
subject { described_class.new.host_names_check }
it 'returns nil when host_names is set' do
Discourse.stubs(:current_hostname).returns('something.com')
expect(subject).to be_nil
end
it 'returns a string when host_name is localhost' do
Discourse.stubs(:current_hostname).returns('localhost')
expect(subject).to_not be_nil
end
it 'returns a string when host_name is production.localhost' do
Discourse.stubs(:current_hostname).returns('production.localhost')
expect(subject).to_not be_nil
end
end
describe 'sidekiq_check' do
subject { described_class.new.sidekiq_check }
it 'returns nil when sidekiq processed a job recently' do
Jobs.stubs(:last_job_performed_at).returns(1.minute.ago)
Jobs.stubs(:queued).returns(0)
expect(subject).to be_nil
end
it 'returns nil when last job processed was a long time ago, but no jobs are queued' do
Jobs.stubs(:last_job_performed_at).returns(7.days.ago)
Jobs.stubs(:queued).returns(0)
expect(subject).to be_nil
end
it 'returns nil when no jobs have ever been processed, but no jobs are queued' do
Jobs.stubs(:last_job_performed_at).returns(nil)
Jobs.stubs(:queued).returns(0)
expect(subject).to be_nil
end
it 'returns a string when no jobs were processed recently and some jobs are queued' do
Jobs.stubs(:last_job_performed_at).returns(20.minutes.ago)
Jobs.stubs(:queued).returns(1)
expect(subject).to_not be_nil
end
it 'returns a string when no jobs have ever been processed, and some jobs are queued' do
Jobs.stubs(:last_job_performed_at).returns(nil)
Jobs.stubs(:queued).returns(1)
expect(subject).to_not be_nil
end
end
describe 'ram_check' do
subject { described_class.new.ram_check }
it 'returns nil when total ram is 1 GB' do
MemInfo.any_instance.stubs(:mem_total).returns(1025272)
expect(subject).to be_nil
end
it 'returns nil when total ram cannot be determined' do
MemInfo.any_instance.stubs(:mem_total).returns(nil)
expect(subject).to be_nil
end
it 'returns a string when total ram is less than 1 GB' do
MemInfo.any_instance.stubs(:mem_total).returns(512636)
expect(subject).to_not be_nil
end
end
describe 'auth_config_checks' do
shared_examples 'problem detection for login providers' do
context 'when disabled' do
it 'returns nil' do
SiteSetting.public_send("#{enable_setting}=", false)
expect(subject).to be_nil
end
end
context 'when enabled' do
before do
SiteSetting.public_send("#{enable_setting}=", true)
end
it 'returns nil when key and secret are set' do
SiteSetting.public_send("#{key}=", '12313213')
SiteSetting.public_send("#{secret}=", '12312313123')
expect(subject).to be_nil
end
it 'returns a string when key is not set' do
SiteSetting.public_send("#{key}=", '')
SiteSetting.public_send("#{secret}=", '12312313123')
expect(subject).to_not be_nil
end
it 'returns a string when secret is not set' do
SiteSetting.public_send("#{key}=", '123123')
SiteSetting.public_send("#{secret}=", '')
expect(subject).to_not be_nil
end
it 'returns a string when key and secret are not set' do
SiteSetting.public_send("#{key}=", '')
SiteSetting.public_send("#{secret}=", '')
expect(subject).to_not be_nil
end
end
end
describe 'facebook' do
subject { described_class.new.facebook_config_check }
let(:enable_setting) { :enable_facebook_logins }
let(:key) { :facebook_app_id }
let(:secret) { :facebook_app_secret }
include_examples 'problem detection for login providers'
end
describe 'twitter' do
subject { described_class.new.twitter_config_check }
let(:enable_setting) { :enable_twitter_logins }
let(:key) { :twitter_consumer_key }
let(:secret) { :twitter_consumer_secret }
include_examples 'problem detection for login providers'
end
describe 'github' do
subject { described_class.new.github_config_check }
let(:enable_setting) { :enable_github_logins }
let(:key) { :github_client_id }
let(:secret) { :github_client_secret }
include_examples 'problem detection for login providers'
end
end
describe 's3_config_check' do
shared_examples 'problem detection for s3-dependent setting' do
subject { described_class.new.s3_config_check }
let(:access_keys) { [:s3_access_key_id, :s3_secret_access_key] }
let(:all_cred_keys) { access_keys + [:s3_use_iam_profile] }
let(:all_setting_keys) { all_cred_keys + [bucket_key] }
def all_setting_permutations(keys)
['a', ''].repeated_permutation(keys.size) do |*values|
hash = Hash[keys.zip(values)]
hash.each do |key, value|
SiteSetting.public_send("#{key}=", value)
end
yield hash
end
end
context 'when setting is enabled' do
before do
all_setting_keys.each { |key| SiteSetting.public_send("#{key}=", 'foo') }
SiteSetting.public_send("#{setting[:key]}=", setting[:enabled_value])
SiteSetting.public_send("#{bucket_key}=", bucket_value)
end
context 'when bucket is blank' do
let(:bucket_value) { '' }
it "always returns a string" do
all_setting_permutations(all_cred_keys) do
expect(subject).to_not be_nil
end
end
end
context 'when bucket is filled in' do
let(:bucket_value) { 'a' }
before do
SiteSetting.s3_use_iam_profile = use_iam_profile
end
context 'when using iam profile' do
let(:use_iam_profile) { true }
it 'always returns nil' do
all_setting_permutations(access_keys) do
expect(subject).to be_nil
end
end
end
context 'when not using iam profile' do
let(:use_iam_profile) { false }
it 'returns nil only if both access key fields are filled in' do
all_setting_permutations(access_keys) do |settings|
if settings.values.all?
expect(subject).to be_nil
else
expect(subject).to_not be_nil
end
end
end
end
end
end
context 'when setting is not enabled' do
before do
SiteSetting.public_send("#{setting[:key]}=", setting[:disabled_value])
end
it "always returns nil" do
all_setting_permutations(all_setting_keys) do
expect(subject).to be_nil
end
end
end
end
describe 'uploads' do
let(:setting) do
{
key: :enable_s3_uploads,
enabled_value: true,
disabled_value: false
}
end
let(:bucket_key) { :s3_upload_bucket }
include_examples 'problem detection for s3-dependent setting'
end
describe 'backups' do
let(:setting) do
{
key: :backup_location,
enabled_value: BackupLocationSiteSetting::S3,
disabled_value: BackupLocationSiteSetting::LOCAL
}
end
let(:bucket_key) { :s3_backup_bucket }
include_examples 'problem detection for s3-dependent setting'
end
end
describe 'force_https_check' do
subject { described_class.new(check_force_https: true).force_https_check }
it 'returns nil if force_https site setting enabled' do
SiteSetting.force_https = true
expect(subject).to be_nil
end
it 'returns nil if force_https site setting not enabled' do
SiteSetting.force_https = false
expect(subject).to eq(I18n.t('dashboard.force_https_warning', base_path: Discourse.base_path))
end
end
describe 'ignore force_https_check' do
subject { described_class.new(check_force_https: false).force_https_check }
it 'returns nil' do
SiteSetting.force_https = true
expect(subject).to be_nil
SiteSetting.force_https = false
expect(subject).to be_nil
end
end
describe 'stats cache' do
include_examples 'stats cachable'
end
describe '#problem_message_check' do
let(:key) { AdminDashboardData.problem_messages.first }
before do
described_class.clear_problem_message(key)
end
it 'returns nil if message has not been added' do
expect(described_class.problem_message_check(key)).to be_nil
end
it 'returns a message if it was added' do
described_class.add_problem_message(key)
expect(described_class.problem_message_check(key)).to eq(I18n.t(key, base_path: Discourse.base_path))
end
it 'returns a message if it was added with an expiry' do
described_class.add_problem_message(key, 300)
expect(described_class.problem_message_check(key)).to eq(I18n.t(key, base_path: Discourse.base_path))
end
end
describe '#out_of_date_themes' do
let(:remote) { RemoteTheme.create!(remote_url: "https://github.com/org/testtheme") }
let!(:theme) { Fabricate(:theme, remote_theme: remote, name: "Test< Theme") }
it "outputs correctly formatted html" do
remote.update!(local_version: "old version", remote_version: "new version", commits_behind: 2)
dashboard_data = described_class.new
expect(dashboard_data.out_of_date_themes).to eq(
I18n.t("dashboard.out_of_date_themes") + "<ul><li><a href=\"/admin/customize/themes/#{theme.id}\">Test&lt; Theme</a></li></ul>"
)
remote.update!(local_version: "new version", commits_behind: 0)
expect(dashboard_data.out_of_date_themes).to eq(nil)
end
end
describe '#unreachable_themes' do
let(:remote) { RemoteTheme.create!(remote_url: "https://github.com/org/testtheme", last_error_text: "can't reach repo :'(") }
let!(:theme) { Fabricate(:theme, remote_theme: remote, name: "Test< Theme") }
it "outputs correctly formatted html" do
dashboard_data = described_class.new
expect(dashboard_data.unreachable_themes).to eq(
I18n.t("dashboard.unreachable_themes") + "<ul><li><a href=\"/admin/customize/themes/#{theme.id}\">Test&lt; Theme</a></li></ul>"
)
remote.update!(last_error_text: nil)
expect(dashboard_data.out_of_date_themes).to eq(nil)
end
end
end