Merge remote-tracking branch 'parent/main' into upstream-20240218

This commit is contained in:
KMY 2024-02-18 14:39:40 +09:00
commit a1f88f6001
27 changed files with 131 additions and 169 deletions

View file

@ -108,12 +108,6 @@ Rails/FilePath:
Rails/HttpStatus: Rails/HttpStatus:
EnforcedStyle: numeric EnforcedStyle: numeric
# Reason: Allowed in boot ENV checker
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsexit
Rails/Exit:
Exclude:
- 'config/boot.rb'
# Reason: Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions # Reason: Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railslexicallyscopedactionfilter # https://docs.rubocop.org/rubocop-rails/cops_rails.html#railslexicallyscopedactionfilter
Rails/LexicallyScopedActionFilter: Rails/LexicallyScopedActionFilter:

View file

@ -219,7 +219,7 @@ GEM
docile (1.4.0) docile (1.4.0)
domain_name (0.5.20190701) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.6.8) doorkeeper (5.6.9)
railties (>= 5) railties (>= 5)
dotenv (2.8.1) dotenv (2.8.1)
dotenv-rails (2.8.1) dotenv-rails (2.8.1)
@ -813,7 +813,7 @@ GEM
xorcist (1.1.3) xorcist (1.1.3)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.6.12) zeitwerk (2.6.13)
PLATFORMS PLATFORMS
ruby ruby

View file

@ -92,9 +92,9 @@ class Account < ApplicationRecord
include DomainNormalizable include DomainNormalizable
include Paginable include Paginable
enum protocol: { ostatus: 0, activitypub: 1 } enum :protocol, { ostatus: 0, activitypub: 1 }
enum suspension_origin: { local: 0, remote: 1 }, _prefix: true enum :suspension_origin, { local: 0, remote: 1 }, prefix: true
enum searchability: { public: 0, private: 1, direct: 2, limited: 3, unsupported: 4, public_unlisted: 10 }, _suffix: :searchability enum :searchability, { public: 0, private: 1, direct: 2, limited: 3, unsupported: 4, public_unlisted: 10 }, suffix: :searchability
validates :username, presence: true validates :username, presence: true
validates_with UniqueUsernameValidator, if: -> { will_save_change_to_username? } validates_with UniqueUsernameValidator, if: -> { will_save_change_to_username? }

View file

@ -17,7 +17,7 @@
# #
class AccountWarning < ApplicationRecord class AccountWarning < ApplicationRecord
enum action: { enum :action, {
none: 0, none: 0,
disable: 1_000, disable: 1_000,
force_cw: 1_200, force_cw: 1_200,
@ -26,7 +26,7 @@ class AccountWarning < ApplicationRecord
sensitive: 2_000, sensitive: 2_000,
silence: 3_000, silence: 3_000,
suspend: 4_000, suspend: 4_000,
}, _suffix: :action }, suffix: :action
normalizes :text, with: ->(text) { text.to_s }, apply_to_nil: true normalizes :text, with: ->(text) { text.to_s }, apply_to_nil: true

View file

@ -24,7 +24,7 @@ class BulkImport < ApplicationRecord
belongs_to :account belongs_to :account
has_many :rows, class_name: 'BulkImportRow', inverse_of: :bulk_import, dependent: :delete_all has_many :rows, class_name: 'BulkImportRow', inverse_of: :bulk_import, dependent: :delete_all
enum type: { enum :type, {
following: 0, following: 0,
blocking: 1, blocking: 1,
muting: 2, muting: 2,
@ -33,7 +33,7 @@ class BulkImport < ApplicationRecord
lists: 5, lists: 5,
} }
enum state: { enum :state, {
unconfirmed: 0, unconfirmed: 0,
scheduled: 1, scheduled: 1,
in_progress: 2, in_progress: 2,

View file

@ -35,7 +35,7 @@ class CustomFilter < ApplicationRecord
include Expireable include Expireable
include Redisable include Redisable
enum action: { warn: 0, hide: 1, half_warn: 2 }, _suffix: :action enum :action, { warn: 0, hide: 1, half_warn: 2 }, suffix: :action
belongs_to :account belongs_to :account
has_many :keywords, class_name: 'CustomFilterKeyword', inverse_of: :custom_filter, dependent: :destroy has_many :keywords, class_name: 'CustomFilterKeyword', inverse_of: :custom_filter, dependent: :destroy

View file

@ -32,7 +32,7 @@ class DomainBlock < ApplicationRecord
include DomainNormalizable include DomainNormalizable
include DomainMaterializable include DomainMaterializable
enum severity: { silence: 0, suspend: 1, noop: 2 } enum :severity, { silence: 0, suspend: 1, noop: 2 }
validates :domain, presence: true, uniqueness: true, domain: true validates :domain, presence: true, uniqueness: true, domain: true

View file

@ -23,8 +23,8 @@ class FriendDomain < ApplicationRecord
validates :domain, presence: true, uniqueness: true, if: :will_save_change_to_domain? validates :domain, presence: true, uniqueness: true, if: :will_save_change_to_domain?
validates :inbox_url, presence: true, uniqueness: true, if: :will_save_change_to_inbox_url? validates :inbox_url, presence: true, uniqueness: true, if: :will_save_change_to_inbox_url?
enum active_state: { idle: 0, pending: 1, accepted: 2, rejected: 3 }, _prefix: :i_am enum :active_state, { idle: 0, pending: 1, accepted: 2, rejected: 3 }, prefix: :i_am
enum passive_state: { idle: 0, pending: 1, accepted: 2, rejected: 3 }, _prefix: :they_are enum :passive_state, { idle: 0, pending: 1, accepted: 2, rejected: 3 }, prefix: :they_are
scope :by_domain_and_subdomains, ->(domain) { where(domain: Instance.by_domain_and_subdomains(domain).select(:domain)) } scope :by_domain_and_subdomains, ->(domain) { where(domain: Instance.by_domain_and_subdomains(domain).select(:domain)) }
scope :enabled, -> { where(active_state: :accepted).or(FriendDomain.where(passive_state: :accepted)).where(available: true) } scope :enabled, -> { where(active_state: :accepted).or(FriendDomain.where(passive_state: :accepted)).where(available: true) }

View file

@ -28,7 +28,7 @@ class Import < ApplicationRecord
belongs_to :account belongs_to :account
enum type: { following: 0, blocking: 1, muting: 2, domain_blocking: 3, bookmarks: 4 } enum :type, { following: 0, blocking: 1, muting: 2, domain_blocking: 3, bookmarks: 4 }
validates :type, presence: true validates :type, presence: true

View file

@ -19,7 +19,7 @@ class IpBlock < ApplicationRecord
include Expireable include Expireable
include Paginable include Paginable
enum severity: { enum :severity, {
sign_up_requires_approval: 5000, sign_up_requires_approval: 5000,
sign_up_block: 5500, sign_up_block: 5500,
no_access: 9999, no_access: 9999,

View file

@ -19,7 +19,7 @@ class List < ApplicationRecord
PER_ACCOUNT_LIMIT = 50 PER_ACCOUNT_LIMIT = 50
enum replies_policy: { list: 0, followed: 1, none: 2 }, _prefix: :show enum :replies_policy, { list: 0, followed: 1, none: 2 }, prefix: :show
belongs_to :account, optional: true belongs_to :account, optional: true

View file

@ -16,7 +16,7 @@
# #
class LoginActivity < ApplicationRecord class LoginActivity < ApplicationRecord
enum authentication_method: { password: 'password', otp: 'otp', webauthn: 'webauthn', sign_in_token: 'sign_in_token', omniauth: 'omniauth' } enum :authentication_method, { password: 'password', otp: 'otp', webauthn: 'webauthn', sign_in_token: 'sign_in_token', omniauth: 'omniauth' }
belongs_to :user belongs_to :user

View file

@ -39,8 +39,8 @@ class MediaAttachment < ApplicationRecord
LOCAL_STATUS_ATTACHMENT_MAX_WITH_POLL = 4 LOCAL_STATUS_ATTACHMENT_MAX_WITH_POLL = 4
ACTIVITYPUB_STATUS_ATTACHMENT_MAX = 16 ACTIVITYPUB_STATUS_ATTACHMENT_MAX = 16
enum type: { image: 0, gifv: 1, video: 2, unknown: 3, audio: 4 } enum :type, { image: 0, gifv: 1, video: 2, unknown: 3, audio: 4 }
enum processing: { queued: 0, in_progress: 1, complete: 2, failed: 3 }, _prefix: true enum :processing, { queued: 0, in_progress: 1, complete: 2, failed: 3 }, prefix: true
MAX_DESCRIPTION_LENGTH = 1_500 MAX_DESCRIPTION_LENGTH = 1_500

View file

@ -17,6 +17,6 @@
class NgwordHistory < ApplicationRecord class NgwordHistory < ApplicationRecord
include Paginable include Paginable
enum target_type: { status: 0, account_note: 1, account_name: 2 }, _suffix: :blocked enum :target_type, { status: 0, account_note: 1, account_name: 2 }, suffix: :blocked
enum reason: { ng_words: 0, ng_words_for_stranger_mention: 1, hashtag_count: 2, mention_count: 3, stranger_mention_count: 4 }, _prefix: :within enum :reason, { ng_words: 0, ng_words_for_stranger_mention: 1, hashtag_count: 2, mention_count: 3, stranger_mention_count: 4 }, prefix: :within
end end

View file

@ -47,8 +47,8 @@ class PreviewCard < ApplicationRecord
self.inheritance_column = false self.inheritance_column = false
enum type: { link: 0, photo: 1, video: 2, rich: 3 } enum :type, { link: 0, photo: 1, video: 2, rich: 3 }
enum link_type: { unknown: 0, article: 1 } enum :link_type, { unknown: 0, article: 1 }
has_many :preview_cards_statuses, dependent: :delete_all, inverse_of: :preview_card has_many :preview_cards_statuses, dependent: :delete_all, inverse_of: :preview_card
has_many :statuses, through: :preview_cards_statuses has_many :statuses, through: :preview_cards_statuses

View file

@ -15,7 +15,7 @@
class Relay < ApplicationRecord class Relay < ApplicationRecord
validates :inbox_url, presence: true, uniqueness: true, url: true, if: :will_save_change_to_inbox_url? validates :inbox_url, presence: true, uniqueness: true, url: true, if: :will_save_change_to_inbox_url?
enum state: { idle: 0, pending: 1, accepted: 2, rejected: 3 } enum :state, { idle: 0, pending: 1, accepted: 2, rejected: 3 }
scope :enabled, -> { accepted } scope :enabled, -> { accepted }

View file

@ -55,7 +55,7 @@ class Report < ApplicationRecord
# - app/javascript/mastodon/features/notifications/components/report.jsx # - app/javascript/mastodon/features/notifications/components/report.jsx
# - app/javascript/mastodon/features/report/category.jsx # - app/javascript/mastodon/features/report/category.jsx
# - app/javascript/mastodon/components/admin/ReportReasonSelector.jsx # - app/javascript/mastodon/components/admin/ReportReasonSelector.jsx
enum category: { enum :category, {
other: 0, other: 0,
spam: 1_000, spam: 1_000,
legal: 1_500, legal: 1_500,

View file

@ -16,7 +16,7 @@
class SoftwareUpdate < ApplicationRecord class SoftwareUpdate < ApplicationRecord
self.inheritance_column = nil self.inheritance_column = nil
enum type: { patch: 0, minor: 1, major: 2 }, _suffix: :type enum :type, { patch: 0, minor: 1, major: 2 }, suffix: :type
def gem_version def gem_version
Gem::Version.new(version) Gem::Version.new(version)

View file

@ -58,9 +58,9 @@ class Status < ApplicationRecord
update_index('statuses', :proper) update_index('statuses', :proper)
update_index('public_statuses', :proper) update_index('public_statuses', :proper)
enum visibility: { public: 0, unlisted: 1, private: 2, direct: 3, limited: 4, public_unlisted: 10, login: 11 }, _suffix: :visibility enum :visibility, { public: 0, unlisted: 1, private: 2, direct: 3, limited: 4, public_unlisted: 10, login: 11 }, suffix: :visibility
enum searchability: { public: 0, private: 1, direct: 2, limited: 3, unsupported: 4, public_unlisted: 10 }, _suffix: :searchability enum :searchability, { public: 0, private: 1, direct: 2, limited: 3, unsupported: 4, public_unlisted: 10 }, suffix: :searchability
enum limited_scope: { none: 0, mutual: 1, circle: 2, personal: 3, reply: 4 }, _suffix: :limited enum :limited_scope, { none: 0, mutual: 1, circle: 2, personal: 3, reply: 4 }, suffix: :limited
belongs_to :application, class_name: 'Doorkeeper::Application', optional: true belongs_to :application, class_name: 'Doorkeeper::Application', optional: true

View file

@ -1,8 +1,15 @@
# frozen_string_literal: true # frozen_string_literal: true
unless ENV.key?('RAILS_ENV') unless ENV.key?('RAILS_ENV')
warn 'ERROR: Missing RAILS_ENV environment variable, please set it to "production", "development", or "test".' abort <<~ERROR
exit 1 The RAILS_ENV environment variable is not set.
Please set it correctly depending on context:
- Use "production" for a live deployment of the application
- Use "development" for local feature work
- Use "test" when running the automated spec suite
ERROR
end end
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)

View file

@ -30,21 +30,19 @@ RSpec.describe Admin::Disputes::AppealsController do
end end
describe 'POST #approve' do describe 'POST #approve' do
subject { post :approve, params: { id: appeal.id } }
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do it 'redirects back to the strike page and notifies target account about approved appeal', :sidekiq_inline do
post :approve, params: { id: appeal.id } subject
end
it 'unsuspends a suspended account' do expect(response)
expect(target_account.reload.suspended?).to be false .to redirect_to(disputes_strike_path(appeal.strike))
end
it 'redirects back to the strike page' do expect(target_account.reload)
expect(response).to redirect_to(disputes_strike_path(appeal.strike)) .to_not be_suspended
end
it 'notifies target account about approved appeal', :sidekiq_inline do
expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.size).to eq(1)
expect(UserMailer.deliveries.first.to.first).to eq(target_account.user.email) expect(UserMailer.deliveries.first.to.first).to eq(target_account.user.email)
expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.appeal_approved.subject', date: I18n.l(appeal.created_at))) expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.appeal_approved.subject', date: I18n.l(appeal.created_at)))
@ -52,17 +50,16 @@ RSpec.describe Admin::Disputes::AppealsController do
end end
describe 'POST #reject' do describe 'POST #reject' do
subject { post :reject, params: { id: appeal.id } }
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do it 'redirects back to the strike page and notifies target account about rejected appeal', :sidekiq_inline do
post :reject, params: { id: appeal.id } subject
end
it 'redirects back to the strike page' do expect(response)
expect(response).to redirect_to(disputes_strike_path(appeal.strike)) .to redirect_to(disputes_strike_path(appeal.strike))
end
it 'notifies target account about rejected appeal', :sidekiq_inline do
expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.size).to eq(1)
expect(UserMailer.deliveries.first.to.first).to eq(target_account.user.email) expect(UserMailer.deliveries.first.to.first).to eq(target_account.user.email)
expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.appeal_rejected.subject', date: I18n.l(appeal.created_at))) expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.appeal_rejected.subject', date: I18n.l(appeal.created_at)))

View file

@ -57,11 +57,9 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { email: 'pam_user1', password: '123456' } } post :create, params: { user: { email: 'pam_user1', password: '123456' } }
end end
it 'redirects to home' do it 'redirects to home and logs the user in' do
expect(response).to redirect_to(root_path) expect(response).to redirect_to(root_path)
end
it 'logs the user in' do
expect(controller.current_user).to be_instance_of(User) expect(controller.current_user).to be_instance_of(User)
end end
end end
@ -71,11 +69,9 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { email: 'pam_user1', password: 'WRONGPW' } } post :create, params: { user: { email: 'pam_user1', password: 'WRONGPW' } }
end end
it 'shows a login error' do it 'shows a login error and does not log the user in' do
expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email')) expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email'))
end
it "doesn't log the user in" do
expect(controller.current_user).to be_nil expect(controller.current_user).to be_nil
end end
end end
@ -92,11 +88,9 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { email: user.email, password: '123456' } } post :create, params: { user: { email: user.email, password: '123456' } }
end end
it 'redirects to home' do it 'redirects to home and logs the user in' do
expect(response).to redirect_to(root_path) expect(response).to redirect_to(root_path)
end
it 'logs the user in' do
expect(controller.current_user).to eq user expect(controller.current_user).to eq user
end end
end end
@ -110,16 +104,16 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { email: user.email, password: user.password } } post :create, params: { user: { email: user.email, password: user.password } }
end end
it 'redirects to home' do it 'redirects to home and logs the user in' do
expect(response).to redirect_to(root_path) expect(response).to redirect_to(root_path)
end
it 'logs the user in' do
expect(controller.current_user).to eq user expect(controller.current_user).to eq user
end end
end end
context 'when using a valid password on a previously-used account with a new IP address' do context 'when using a valid password on a previously-used account with a new IP address' do
subject { post :create, params: { user: { email: user.email, password: user.password } } }
let(:previous_ip) { '1.2.3.4' } let(:previous_ip) { '1.2.3.4' }
let(:current_ip) { '4.3.2.1' } let(:current_ip) { '4.3.2.1' }
@ -127,18 +121,17 @@ RSpec.describe Auth::SessionsController do
Fabricate(:login_activity, user: user, ip: previous_ip) Fabricate(:login_activity, user: user, ip: previous_ip)
allow(controller.request).to receive(:remote_ip).and_return(current_ip) allow(controller.request).to receive(:remote_ip).and_return(current_ip)
user.update(current_sign_in_at: 1.month.ago) user.update(current_sign_in_at: 1.month.ago)
post :create, params: { user: { email: user.email, password: user.password } }
end end
it 'redirects to home' do it 'logs the user in and sends suspicious email and redirects home', :sidekiq_inline do
expect(response).to redirect_to(root_path) subject
end
it 'logs the user in' do expect(response)
expect(controller.current_user).to eq user .to redirect_to(root_path)
end
expect(controller.current_user)
.to eq user
it 'sends a suspicious sign-in mail', :sidekiq_inline do
expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.size).to eq(1)
expect(UserMailer.deliveries.first.to.first).to eq(user.email) expect(UserMailer.deliveries.first.to.first).to eq(user.email)
expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.suspicious_sign_in.subject')) expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.suspicious_sign_in.subject'))
@ -150,11 +143,9 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { email: user.email.upcase, password: user.password } } post :create, params: { user: { email: user.email.upcase, password: user.password } }
end end
it 'redirects to home' do it 'redirects to home and logs the user in' do
expect(response).to redirect_to(root_path) expect(response).to redirect_to(root_path)
end
it 'logs the user in' do
expect(controller.current_user).to eq user expect(controller.current_user).to eq user
end end
end end
@ -164,11 +155,9 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { email: user.email, password: 'wrongpw' } } post :create, params: { user: { email: user.email, password: 'wrongpw' } }
end end
it 'shows a login error' do it 'shows a login error and does not log the user in' do
expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email')) expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email'))
end
it "doesn't log the user in" do
expect(controller.current_user).to be_nil expect(controller.current_user).to be_nil
end end
end end
@ -270,7 +259,7 @@ RSpec.describe Auth::SessionsController do
travel_to '2023-12-20T10:00:00Z' travel_to '2023-12-20T10:00:00Z'
end end
it 'does not log the user in' do it 'does not log the user in, sets a flash message, and sends a suspicious sign in email', :sidekiq_inline do
Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do
post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
expect(controller.current_user).to be_nil expect(controller.current_user).to be_nil
@ -278,17 +267,10 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
expect(controller.current_user).to be_nil expect(controller.current_user)
expect(flash[:alert]).to match I18n.t('users.rate_limited') .to be_nil
end expect(flash[:alert])
.to match I18n.t('users.rate_limited')
it 'sends a suspicious sign-in mail', :sidekiq_inline do
Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do
post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
expect(controller.current_user).to be_nil
end
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
expect(UserMailer.deliveries.size).to eq(1) expect(UserMailer.deliveries.size).to eq(1)
expect(UserMailer.deliveries.first.to.first).to eq(user.email) expect(UserMailer.deliveries.first.to.first).to eq(user.email)
@ -301,11 +283,9 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
end end
it 'redirects to home' do it 'redirects to home and logs the user in' do
expect(response).to redirect_to(root_path) expect(response).to redirect_to(root_path)
end
it 'logs the user in' do
expect(controller.current_user).to eq user expect(controller.current_user).to eq user
end end
end end
@ -318,11 +298,9 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
end end
it 'shows a login error' do it 'shows a login error and does not log the user in' do
expect(flash[:alert]).to match I18n.t('users.invalid_otp_token') expect(flash[:alert]).to match I18n.t('users.invalid_otp_token')
end
it "doesn't log the user in" do
expect(controller.current_user).to be_nil expect(controller.current_user).to be_nil
end end
end end
@ -332,11 +310,9 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
end end
it 'redirects to home' do it 'redirects to home and logs the user in' do
expect(response).to redirect_to(root_path) expect(response).to redirect_to(root_path)
end
it 'logs the user in' do
expect(controller.current_user).to eq user expect(controller.current_user).to eq user
end end
end end
@ -346,11 +322,9 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
end end
it 'shows a login error' do it 'shows a login error and does not log the user in' do
expect(flash[:alert]).to match I18n.t('users.invalid_otp_token') expect(flash[:alert]).to match I18n.t('users.invalid_otp_token')
end
it "doesn't log the user in" do
expect(controller.current_user).to be_nil expect(controller.current_user).to be_nil
end end
end end
@ -417,15 +391,11 @@ RSpec.describe Auth::SessionsController do
post :create, params: { user: { credential: fake_credential } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } post :create, params: { user: { credential: fake_credential } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
end end
it 'instructs the browser to redirect to home' do it 'instructs the browser to redirect to home, logs the user in, and updates the sign count' do
expect(body_as_json[:redirect_path]).to eq(root_path) expect(body_as_json[:redirect_path]).to eq(root_path)
end
it 'logs the user in' do
expect(controller.current_user).to eq user expect(controller.current_user).to eq user
end
it 'updates the sign count' do
expect(webauthn_credential.reload.sign_count).to eq(sign_count) expect(webauthn_credential.reload.sign_count).to eq(sign_count)
end end
end end

View file

@ -10,19 +10,17 @@ RSpec.describe Disputes::AppealsController do
let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
describe '#create' do describe '#create' do
subject { post :create, params: params }
context 'with valid params' do context 'with valid params' do
let(:current_user) { Fabricate(:user) } let(:current_user) { Fabricate(:user) }
let(:strike) { Fabricate(:account_warning, target_account: current_user.account) } let(:strike) { Fabricate(:account_warning, target_account: current_user.account) }
let(:params) { { strike_id: strike.id, appeal: { text: 'Foo' } } }
before do it 'notifies staff about new appeal and redirects back to strike page', :sidekiq_inline do
post :create, params: { strike_id: strike.id, appeal: { text: 'Foo' } } subject
end
it 'notifies staff about new appeal', :sidekiq_inline do
expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email]) expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email])
end
it 'redirects back to the strike page' do
expect(response).to redirect_to(disputes_strike_path(strike.id)) expect(response).to redirect_to(disputes_strike_path(strike.id))
end end
end end
@ -30,16 +28,12 @@ RSpec.describe Disputes::AppealsController do
context 'with invalid params' do context 'with invalid params' do
let(:current_user) { Fabricate(:user) } let(:current_user) { Fabricate(:user) }
let(:strike) { Fabricate(:account_warning, target_account: current_user.account) } let(:strike) { Fabricate(:account_warning, target_account: current_user.account) }
let(:params) { { strike_id: strike.id, appeal: { text: '' } } }
before do it 'does not send email and renders strike show page', :sidekiq_inline do
post :create, params: { strike_id: strike.id, appeal: { text: '' } } subject
end
it 'does not send email', :sidekiq_inline do
expect(ActionMailer::Base.deliveries.size).to eq(0) expect(ActionMailer::Base.deliveries.size).to eq(0)
end
it 'renders the strike show page' do
expect(response).to render_template('disputes/strikes/show') expect(response).to render_template('disputes/strikes/show')
end end
end end

View file

@ -13,17 +13,19 @@ RSpec.describe InstanceActorsController do
end end
it 'returns http success with correct media type, headers, and session values' do it 'returns http success with correct media type, headers, and session values' do
expect(response).to have_http_status(200) expect(response)
.to have_http_status(200)
.and have_attributes(
media_type: eq('application/activity+json'),
cookies: be_empty
)
expect(response.media_type).to eq 'application/activity+json' expect(response.headers)
.to include('Cache-Control' => include('public'))
expect(response.cookies).to be_empty .and not_include('Set-Cookies')
expect(response.headers['Set-Cookies']).to be_nil
expect(session).to be_empty expect(session).to be_empty
expect(response.headers['Cache-Control']).to include 'public'
expect(body_as_json) expect(body_as_json)
.to include(:id, :type, :preferredUsername, :inbox, :publicKey, :inbox, :outbox, :url) .to include(:id, :type, :preferredUsername, :inbox, :publicKey, :inbox, :outbox, :url)
end end

View file

@ -91,20 +91,15 @@ RSpec.describe MediaAttachment, :paperclip_processing do
end end
it 'saves media attachment with correct file metadata' do it 'saves media attachment with correct file metadata' do
expect(media.persisted?).to be true expect(media)
expect(media.file).to_not be_nil .to be_persisted
.and be_processing_complete
# completes processing .and have_attributes(
expect(media.processing_complete?).to be true file: be_present,
type: eq('image'),
# sets type file_content_type: eq(content_type),
expect(media.type).to eq 'image' file_file_name: end_with(extension)
)
# sets content type
expect(media.file_content_type).to eq content_type
# sets file extension
expect(media.file_file_name).to end_with extension
# Rack::Mime (used by PublicFileServerMiddleware) recognizes file extension # Rack::Mime (used by PublicFileServerMiddleware) recognizes file extension
expect(Rack::Mime.mime_type(extension, nil)).to eq content_type expect(Rack::Mime.mime_type(extension, nil)).to eq content_type
@ -112,17 +107,23 @@ RSpec.describe MediaAttachment, :paperclip_processing do
it 'saves media attachment with correct size metadata' do it 'saves media attachment with correct size metadata' do
# strips original file name # strips original file name
expect(media.file_file_name).to_not start_with '600x400' expect(media.file_file_name)
.to_not start_with '600x400'
# sets meta for original # sets meta for original and thumbnail
expect(media.file.meta['original']['width']).to eq 600 expect(media.file.meta.deep_symbolize_keys)
expect(media.file.meta['original']['height']).to eq 400 .to include(
expect(media.file.meta['original']['aspect']).to eq 1.5 original: include(
width: eq(600),
# sets meta for thumbnail height: eq(400),
expect(media.file.meta['small']['width']).to eq 588 aspect: eq(1.5)
expect(media.file.meta['small']['height']).to eq 392 ),
expect(media.file.meta['small']['aspect']).to eq 1.5 small: include(
width: eq(588),
height: eq(392),
aspect: eq(1.5)
)
)
end end
end end

View file

@ -483,35 +483,32 @@ RSpec.describe User do
end end
describe '#mark_email_as_confirmed!' do describe '#mark_email_as_confirmed!' do
subject(:user) { Fabricate(:user, confirmed_at: confirmed_at) } subject { user.mark_email_as_confirmed! }
before do let!(:user) { Fabricate(:user, confirmed_at: confirmed_at) }
ActionMailer::Base.deliveries.clear
user.mark_email_as_confirmed! before { ActionMailer::Base.deliveries.clear }
end
after { ActionMailer::Base.deliveries.clear } after { ActionMailer::Base.deliveries.clear }
context 'when user is new' do context 'when user is new' do
let(:confirmed_at) { nil } let(:confirmed_at) { nil }
it 'confirms user' do it 'confirms user and delivers welcome email', :sidekiq_inline do
expect(user.confirmed_at).to be_present subject
end
it 'delivers mails', :sidekiq_inline do expect(user.confirmed_at).to be_present
expect(ActionMailer::Base.deliveries.count).to eq 2 expect(ActionMailer::Base.deliveries.count).to eq 1
end end
end end
context 'when user is not new' do context 'when user is not new' do
let(:confirmed_at) { Time.zone.now } let(:confirmed_at) { Time.zone.now }
it 'confirms user' do it 'confirms user but does not deliver welcome email' do
expect(user.confirmed_at).to be_present subject
end
it 'does not deliver mail' do expect(user.confirmed_at).to be_present
expect(ActionMailer::Base.deliveries.count).to eq 0 expect(ActionMailer::Base.deliveries.count).to eq 0
end end
end end

View file

@ -28,6 +28,6 @@ describe 'OCR', :paperclip_processing, :sidekiq_inline do
click_on('Detect text from picture') click_on('Detect text from picture')
expect(page).to have_css('#upload-modal__description', text: 'Hello Mastodon') expect(page).to have_css('#upload-modal__description', text: /Hello Mastodon\s*/, wait: 10)
end end
end end