diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb index 359d60b60e2..e5fbb1500e9 100644 --- a/app/helpers/admin/action_logs_helper.rb +++ b/app/helpers/admin/action_logs_helper.rb @@ -9,42 +9,6 @@ module Admin::ActionLogsHelper end end - def linkable_log_target(record) - case record.class.name - when 'Account' - link_to record.acct, admin_account_path(record.id) - when 'User' - link_to record.account.acct, admin_account_path(record.account_id) - when 'CustomEmoji' - record.shortcode - when 'Report' - link_to "##{record.id}", admin_report_path(record) - when 'DomainBlock', 'EmailDomainBlock' - link_to record.domain, "https://#{record.domain}" - when 'Status' - link_to record.account.acct, TagManager.instance.url_for(record) - when 'AccountWarning' - link_to record.target_account.acct, admin_account_path(record.target_account_id) - end - end - - def log_target_from_history(type, attributes) - case type - when 'CustomEmoji' - attributes['shortcode'] - when 'DomainBlock', 'EmailDomainBlock' - link_to attributes['domain'], "https://#{attributes['domain']}" - when 'Status' - tmp_status = Status.new(attributes.except('reblogs_count', 'favourites_count')) - - if tmp_status.account - link_to tmp_status.account&.acct || "##{tmp_status.account_id}", admin_account_path(tmp_status.account_id) - else - I18n.t('admin.action_logs.deleted_status') - end - end - end - def relevant_log_changes(log) if log.target_type == 'CustomEmoji' && [:enable, :disable, :destroy].include?(log.action) log.recorded_changes.slice('domain') @@ -111,4 +75,40 @@ module Admin::ActionLogsHelper def opposite_verbs?(log) %w(DomainBlock EmailDomainBlock AccountWarning).include?(log.target_type) end + + def linkable_log_target(record) + case record.class.name + when 'Account' + link_to record.acct, admin_account_path(record.id) + when 'User' + link_to record.account.acct, admin_account_path(record.account_id) + when 'CustomEmoji' + record.shortcode + when 'Report' + link_to "##{record.id}", admin_report_path(record) + when 'DomainBlock', 'EmailDomainBlock' + link_to record.domain, "https://#{record.domain}" + when 'Status' + link_to record.account.acct, TagManager.instance.url_for(record) + when 'AccountWarning' + link_to record.target_account.acct, admin_account_path(record.target_account_id) + end + end + + def log_target_from_history(type, attributes) + case type + when 'CustomEmoji' + attributes['shortcode'] + when 'DomainBlock', 'EmailDomainBlock' + link_to attributes['domain'], "https://#{attributes['domain']}" + when 'Status' + tmp_status = Status.new(attributes.except('reblogs_count', 'favourites_count')) + + if tmp_status.account + link_to tmp_status.account&.acct || "##{tmp_status.account_id}", admin_account_path(tmp_status.account_id) + else + I18n.t('admin.action_logs.deleted_status') + end + end + end end diff --git a/spec/helpers/admin/action_log_helper_spec.rb b/spec/helpers/admin/action_log_helper_spec.rb new file mode 100644 index 00000000000..d7af6b939e6 --- /dev/null +++ b/spec/helpers/admin/action_log_helper_spec.rb @@ -0,0 +1,272 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Admin::ActionLogsHelper, type: :helper do + klass = Class.new do + include ActionView::Helpers + include Admin::ActionLogsHelper + end + + let(:hoge) { klass.new } + + describe '#log_target' do + after do + hoge.log_target(log) + end + + context 'log.target' do + let(:log) { double(target: true) } + + it 'calls linkable_log_target' do + expect(hoge).to receive(:linkable_log_target).with(log.target) + end + end + + context '!log.target' do + let(:log) { double(target: false, target_type: :type, recorded_changes: :change) } + + it 'calls log_target_from_history' do + expect(hoge).to receive(:log_target_from_history).with(log.target_type, log.recorded_changes) + end + end + end + + describe '#relevant_log_changes' do + let(:log) { double(target_type: target_type, action: log_action, recorded_changes: recorded_changes) } + let(:recorded_changes) { double } + + after do + hoge.relevant_log_changes(log) + end + + context "log.target_type == 'CustomEmoji' && [:enable, :disable, :destroy].include?(log.action)" do + let(:target_type) { 'CustomEmoji' } + let(:log_action) { :enable } + + it "calls log.recorded_changes.slice('domain')" do + expect(recorded_changes).to receive(:slice).with('domain') + end + end + + context "log.target_type == 'CustomEmoji' && log.action == :update" do + let(:target_type) { 'CustomEmoji' } + let(:log_action) { :update } + + it "calls log.recorded_changes.slice('domain', 'visible_in_picker')" do + expect(recorded_changes).to receive(:slice).with('domain', 'visible_in_picker') + end + end + + context "log.target_type == 'User' && [:promote, :demote].include?(log.action)" do + let(:target_type) { 'User' } + let(:log_action) { :promote } + + it "calls log.recorded_changes.slice('moderator', 'admin')" do + expect(recorded_changes).to receive(:slice).with('moderator', 'admin') + end + end + + context "log.target_type == 'User' && [:change_email].include?(log.action)" do + let(:target_type) { 'User' } + let(:log_action) { :change_email } + + it "calls log.recorded_changes.slice('email', 'unconfirmed_email')" do + expect(recorded_changes).to receive(:slice).with('email', 'unconfirmed_email') + end + end + + context "log.target_type == 'DomainBlock'" do + let(:target_type) { 'DomainBlock' } + let(:log_action) { nil } + + it "calls log.recorded_changes.slice('severity', 'reject_media')" do + expect(recorded_changes).to receive(:slice).with('severity', 'reject_media') + end + end + + context "log.target_type == 'Status' && log.action == :update" do + let(:target_type) { 'Status' } + let(:log_action) { :update } + + it "log.recorded_changes.slice('sensitive')" do + expect(recorded_changes).to receive(:slice).with('sensitive') + end + end + end + + describe '#log_extra_attributes' do + after do + hoge.log_extra_attributes(hoge: 'hoge') + end + + it "calls content_tag(:span, key, class: 'diff-key')" do + allow(hoge).to receive(:log_change).with(anything) + expect(hoge).to receive(:content_tag).with(:span, :hoge, class: 'diff-key') + end + + it 'calls safe_join twice' do + expect(hoge).to receive(:safe_join).with( + ['hoge', + '=', + 'hoge'] + ) + + expect(hoge).to receive(:safe_join).with([nil], ' ') + end + end + + describe '#log_change' do + after do + hoge.log_change(val) + end + + context '!val.is_a?(Array)' do + let(:val) { 'hoge' } + + it "calls content_tag(:span, val, class: 'diff-neutral')" do + expect(hoge).to receive(:content_tag).with(:span, val, class: 'diff-neutral') + end + end + + context 'val.is_a?(Array)' do + let(:val) { %w(foo bar) } + + it 'calls #content_tag twice and #safe_join' do + expect(hoge).to receive(:content_tag).with(:span, 'foo', class: 'diff-old') + expect(hoge).to receive(:content_tag).with(:span, 'bar', class: 'diff-new') + expect(hoge).to receive(:safe_join).with([nil, nil], '→') + end + end + end + + describe '#icon_for_log' do + subject { hoge.icon_for_log(log) } + + context "log.target_type == 'Account'" do + let(:log) { double(target_type: 'Account') } + + it 'returns "user"' do + expect(subject).to be 'user' + end + end + + context "log.target_type == 'User'" do + let(:log) { double(target_type: 'User') } + + it 'returns "user"' do + expect(subject).to be 'user' + end + end + + context "log.target_type == 'CustomEmoji'" do + let(:log) { double(target_type: 'CustomEmoji') } + + it 'returns "file"' do + expect(subject).to be 'file' + end + end + + context "log.target_type == 'Report'" do + let(:log) { double(target_type: 'Report') } + + it 'returns "flag"' do + expect(subject).to be 'flag' + end + end + + context "log.target_type == 'DomainBlock'" do + let(:log) { double(target_type: 'DomainBlock') } + + it 'returns "lock"' do + expect(subject).to be 'lock' + end + end + + context "log.target_type == 'EmailDomainBlock'" do + let(:log) { double(target_type: 'EmailDomainBlock') } + + it 'returns "envelope"' do + expect(subject).to be 'envelope' + end + end + + context "log.target_type == 'Status'" do + let(:log) { double(target_type: 'Status') } + + it 'returns "pencil"' do + expect(subject).to be 'pencil' + end + end + end + + describe '#class_for_log_icon' do + subject { hoge.class_for_log_icon(log) } + + %i(enable unsuspend unsilence confirm promote resolve).each do |action| + context "log.action == #{action}" do + let(:log) { double(action: action) } + + it 'returns "positive"' do + expect(subject).to be 'positive' + end + end + end + + context 'log.action == :create' do + context 'opposite_verbs?(log)' do + let(:log) { double(action: :create, target_type: 'DomainBlock') } + + it 'returns "negative"' do + expect(subject).to be 'negative' + end + end + + context '!opposite_verbs?(log)' do + let(:log) { double(action: :create, target_type: '') } + + it 'returns "positive"' do + expect(subject).to be 'positive' + end + end + end + + %i(update reset_password disable_2fa memorialize change_email).each do |action| + context "log.action == #{action}" do + let(:log) { double(action: action) } + + it 'returns "neutral"' do + expect(subject).to be 'neutral' + end + end + end + + %i(demote silence disable suspend remove_avatar remove_header reopen).each do |action| + context "log.action == #{action}" do + let(:log) { double(action: action) } + + it 'returns "negative"' do + expect(subject).to be 'negative' + end + end + end + + context 'log.action == :destroy' do + context 'opposite_verbs?(log)' do + let(:log) { double(action: :destroy, target_type: 'DomainBlock') } + + it 'returns "positive"' do + expect(subject).to be 'positive' + end + end + + context '!opposite_verbs?(log)' do + let(:log) { double(action: :destroy, target_type: '') } + + it 'returns "negative"' do + expect(subject).to be 'negative' + end + end + end + end +end