Merge branch 'main' into glitch-soc/merge-upstream
Conflicts: - `.github/dependabot.yml`: Updated upstream, removed in glitch-soc to disable noise. Kept removed. - `CODE_OF_CONDUCT.md`: Upstream updated to a new version of the covenant, but I have not read it yet, so kept unchanged. - `Gemfile.lock`: Not a real conflict, one upstream dependency updated textually too close to the glitch-soc only `hcaptcha` dependency. Applied upstream changes. - `app/controllers/admin/base_controller.rb`: Minor conflict due to glitch-soc's theming system. Applied upstream changes. - `app/controllers/application_controller.rb`: Minor conflict due to glitch-soc's theming system. Applied upstream changes. - `app/controllers/disputes/base_controller.rb`: Minor conflict due to glitch-soc's theming system. Applied upstream changes. - `app/controllers/relationships_controller.rb`: Minor conflict due to glitch-soc's theming system. Applied upstream changes. - `app/controllers/statuses_cleanup_controller.rb`: Minor conflict due to glitch-soc's theming system. Applied upstream changes. - `app/helpers/application_helper.rb`: Minor conflict due to glitch-soc's theming system. Applied upstream changes. - `app/javascript/mastodon/features/compose/components/compose_form.jsx`: Upstream added a highlight animation for onboarding, while we changed the max character limit. Applied our local changes on top of upstream's new version. - `app/views/layouts/application.html.haml`: Minor conflict due to glitch-soc's theming system. Applied upstream changes. - `stylelint.config.js`: Upstream added ignore paths, glitch-soc had extra ignore paths. Added the same paths as upstream.
This commit is contained in:
@@ -17,6 +17,10 @@ RSpec.describe AccountsController, type: :controller do
|
||||
expect(session).to be_empty
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to include 'Accept'
|
||||
end
|
||||
|
||||
it 'returns public Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'public'
|
||||
end
|
||||
@@ -214,8 +218,8 @@ RSpec.describe AccountsController, type: :controller do
|
||||
expect(response.media_type).to eq 'application/activity+json'
|
||||
end
|
||||
|
||||
it 'returns public Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'public'
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders account' do
|
||||
|
||||
@@ -50,7 +50,7 @@ RSpec.describe ActivityPub::FollowersSynchronizationsController, type: :controll
|
||||
|
||||
it 'returns orderedItems with followers from example.com' do
|
||||
expect(body[:orderedItems]).to be_an Array
|
||||
expect(body[:orderedItems]).to match_array([follower_4.uri, follower_1.uri, follower_2.uri])
|
||||
expect(body[:orderedItems]).to contain_exactly(follower_4.uri, follower_1.uri, follower_2.uri)
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
|
||||
@@ -18,6 +18,14 @@ describe Admin::BaseController, type: :controller do
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
routes.draw { get 'success' => 'admin/base#success' }
|
||||
sign_in(Fabricate(:user, role: UserRole.find_by(name: 'Moderator')))
|
||||
get :success
|
||||
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
|
||||
it 'renders admin layout as a moderator' do
|
||||
routes.draw { get 'success' => 'admin/base#success' }
|
||||
sign_in(Fabricate(:user, role: UserRole.find_by(name: 'Moderator')))
|
||||
|
||||
@@ -29,7 +29,7 @@ RSpec.describe Admin::ExportDomainBlocksController, type: :controller do
|
||||
end
|
||||
|
||||
it 'renders page with expected domain blocks' do
|
||||
expect(assigns(:domain_blocks).map { |block| [block.domain, block.severity.to_sym] }).to match_array [['bad.domain', :silence], ['worse.domain', :suspend], ['reject.media', :noop]]
|
||||
expect(assigns(:domain_blocks).map { |block| [block.domain, block.severity.to_sym] }).to contain_exactly(['bad.domain', :silence], ['worse.domain', :suspend], ['reject.media', :noop])
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
@@ -43,7 +43,7 @@ RSpec.describe Admin::ExportDomainBlocksController, type: :controller do
|
||||
end
|
||||
|
||||
it 'renders page with expected domain blocks' do
|
||||
expect(assigns(:domain_blocks).map { |block| [block.domain, block.severity.to_sym] }).to match_array [['bad.domain', :suspend], ['worse.domain', :suspend], ['reject.media', :suspend]]
|
||||
expect(assigns(:domain_blocks).map { |block| [block.domain, block.severity.to_sym] }).to contain_exactly(['bad.domain', :suspend], ['worse.domain', :suspend], ['reject.media', :suspend])
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
|
||||
@@ -15,6 +15,12 @@ describe Api::BaseController do
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns private cache control headers by default' do
|
||||
routes.draw { get 'success' => 'api/base#success' }
|
||||
get :success
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
|
||||
describe 'forgery protection' do
|
||||
before do
|
||||
routes.draw { post 'success' => 'api/base#success' }
|
||||
|
||||
@@ -17,5 +17,9 @@ RSpec.describe Api::OEmbedController, type: :controller do
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,7 +28,7 @@ describe Api::V1::Accounts::FollowerAccountsController do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
|
||||
expect(body_as_json.size).to eq 2
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s])
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
|
||||
end
|
||||
|
||||
it 'does not return blocked users' do
|
||||
@@ -58,7 +58,7 @@ describe Api::V1::Accounts::FollowerAccountsController do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
|
||||
expect(body_as_json.size).to eq 2
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s])
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,7 +28,7 @@ describe Api::V1::Accounts::FollowingAccountsController do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
|
||||
expect(body_as_json.size).to eq 2
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s])
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
|
||||
end
|
||||
|
||||
it 'does not return blocked users' do
|
||||
@@ -58,7 +58,7 @@ describe Api::V1::Accounts::FollowingAccountsController do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
|
||||
expect(body_as_json.size).to eq 2
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s])
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -99,7 +99,7 @@ describe Api::V1::Accounts::StatusesController do
|
||||
it 'lists both the public and the private statuses' do
|
||||
get :index, params: { account_id: account.id, pinned: true }
|
||||
json = body_as_json
|
||||
expect(json.map { |item| item[:id].to_i }).to match_array([status.id, private_status.id])
|
||||
expect(json.map { |item| item[:id].to_i }).to contain_exactly(status.id, private_status.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -57,7 +57,7 @@ RSpec.describe Api::V1::BookmarksController, type: :controller do
|
||||
|
||||
get :index
|
||||
|
||||
expect(assigns(:statuses)).to match_array [bookmarked_by_user.status]
|
||||
expect(assigns(:statuses)).to contain_exactly(bookmarked_by_user.status)
|
||||
end
|
||||
|
||||
it 'adds pagination headers if necessary' do
|
||||
|
||||
@@ -57,7 +57,7 @@ RSpec.describe Api::V1::FavouritesController, type: :controller do
|
||||
|
||||
get :index
|
||||
|
||||
expect(assigns(:statuses)).to match_array [favourite_by_user.status]
|
||||
expect(assigns(:statuses)).to contain_exactly(favourite_by_user.status)
|
||||
end
|
||||
|
||||
it 'adds pagination headers if necessary' do
|
||||
|
||||
@@ -69,7 +69,7 @@ RSpec.describe Api::V1::ReportsController, type: :controller do
|
||||
end
|
||||
|
||||
it 'saves rule_ids' do
|
||||
expect(target_account.targeted_reports.first.rule_ids).to match_array([rule.id])
|
||||
expect(target_account.targeted_reports.first.rule_ids).to contain_exactly(rule.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -33,7 +33,7 @@ RSpec.describe Api::V1::Statuses::FavouritedByAccountsController, type: :control
|
||||
it 'returns accounts who favorited the status' do
|
||||
get :index, params: { status_id: status.id, limit: 2 }
|
||||
expect(body_as_json.size).to eq 2
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s])
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
|
||||
end
|
||||
|
||||
it 'does not return blocked users' do
|
||||
|
||||
@@ -33,7 +33,7 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController, type: :controll
|
||||
it 'returns accounts who reblogged the status' do
|
||||
get :index, params: { status_id: status.id, limit: 2 }
|
||||
expect(body_as_json.size).to eq 2
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to match_array([alice.id.to_s, bob.id.to_s])
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
|
||||
end
|
||||
|
||||
it 'does not return blocked users' do
|
||||
|
||||
@@ -139,25 +139,6 @@ describe ApplicationController, type: :controller do
|
||||
include_examples 'respond_with_error', 422
|
||||
end
|
||||
|
||||
describe 'before_action :store_current_location' do
|
||||
it 'stores location for user if it is not devise controller' do
|
||||
routes.draw { get 'success' => 'anonymous#success' }
|
||||
get 'success'
|
||||
expect(controller.stored_location_for(:user)).to eq '/success'
|
||||
end
|
||||
|
||||
context do
|
||||
controller Devise::SessionsController do
|
||||
end
|
||||
|
||||
it 'does not store location for user if it is devise controller' do
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
get 'create'
|
||||
expect(controller.stored_location_for(:user)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'before_action :check_suspension' do
|
||||
before do
|
||||
routes.draw { get 'success' => 'anonymous#success' }
|
||||
|
||||
@@ -33,27 +33,42 @@ RSpec.describe Auth::RegistrationsController, type: :controller do
|
||||
end
|
||||
|
||||
describe 'GET #edit' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
sign_in(Fabricate(:user))
|
||||
get :edit
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control header' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #update' do
|
||||
it 'returns http success' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
sign_in(Fabricate(:user), scope: :user)
|
||||
sign_in(user, scope: :user)
|
||||
post :update
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
|
||||
context 'when suspended' do
|
||||
let(:user) { Fabricate(:user, account_attributes: { username: 'test', suspended_at: Time.now.utc }) }
|
||||
|
||||
it 'returns http forbidden' do
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
sign_in(Fabricate(:user, account_attributes: { username: 'test', suspended_at: Time.now.utc }), scope: :user)
|
||||
post :update
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,9 +6,25 @@ describe CustomCssController do
|
||||
render_views
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns public cache control header' do
|
||||
expect(response.headers['Cache-Control']).to include('public')
|
||||
end
|
||||
|
||||
it 'does not set cookies' do
|
||||
expect(response.cookies).to be_empty
|
||||
expect(response.headers['Set-Cookies']).to be_nil
|
||||
end
|
||||
|
||||
it 'does not set sessions' do
|
||||
expect(session).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,21 +18,27 @@ describe Filters::StatusesController do
|
||||
|
||||
context 'with a signed in user' do
|
||||
context 'with the filter user signed in' do
|
||||
before { sign_in(filter.account.user) }
|
||||
before do
|
||||
sign_in(filter.account.user)
|
||||
get :index, params: { filter_id: filter }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: { filter_id: filter }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with another user signed in' do
|
||||
before { sign_in(Fabricate(:user)) }
|
||||
before do
|
||||
sign_in(Fabricate(:user))
|
||||
get :index, params: { filter_id: filter }
|
||||
end
|
||||
|
||||
it 'returns http not found' do
|
||||
get :index, params: { filter_id: filter }
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,21 +7,28 @@ describe FiltersController do
|
||||
|
||||
describe 'GET #index' do
|
||||
context 'with signed out user' do
|
||||
it 'redirects' do
|
||||
before do
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'redirects' do
|
||||
expect(response).to be_redirect
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a signed in user' do
|
||||
before { sign_in(Fabricate(:user)) }
|
||||
before do
|
||||
sign_in(Fabricate(:user))
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,7 +41,7 @@ describe FollowerAccountsController do
|
||||
context 'when format is json' do
|
||||
subject(:response) { get :index, params: { account_username: alice.username, page: page, format: :json } }
|
||||
|
||||
subject(:body) { JSON.parse(response.body) }
|
||||
subject(:body) { response.parsed_body }
|
||||
|
||||
context 'with page' do
|
||||
let(:page) { 1 }
|
||||
|
||||
@@ -41,7 +41,7 @@ describe FollowingAccountsController do
|
||||
context 'when format is json' do
|
||||
subject(:response) { get :index, params: { account_username: alice.username, page: page, format: :json } }
|
||||
|
||||
subject(:body) { JSON.parse(response.body) }
|
||||
subject(:body) { response.parsed_body }
|
||||
|
||||
context 'with page' do
|
||||
let(:page) { 1 }
|
||||
|
||||
@@ -5,35 +5,40 @@ require 'rails_helper'
|
||||
describe InvitesController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
sign_in user
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
subject { get :index }
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let!(:invite) { Fabricate(:invite, user: user) }
|
||||
before do
|
||||
Fabricate(:invite, user: user)
|
||||
end
|
||||
|
||||
context 'when everyone can invite' do
|
||||
before do
|
||||
UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'renders index page' do
|
||||
expect(subject).to render_template :index
|
||||
expect(assigns(:invites)).to include invite
|
||||
expect(assigns(:invites).count).to eq 1
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not everyone can invite' do
|
||||
before do
|
||||
UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns 403' do
|
||||
expect(subject).to have_http_status 403
|
||||
it 'returns http forbidden' do
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -42,8 +47,6 @@ describe InvitesController do
|
||||
subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
|
||||
|
||||
context 'when everyone can invite' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
|
||||
end
|
||||
@@ -56,26 +59,28 @@ describe InvitesController do
|
||||
end
|
||||
|
||||
context 'when not everyone can invite' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
|
||||
end
|
||||
|
||||
it 'returns 403' do
|
||||
expect(subject).to have_http_status 403
|
||||
it 'returns http forbidden' do
|
||||
expect(subject).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #create' do
|
||||
subject { delete :destroy, params: { id: invite.id } }
|
||||
let(:invite) { Fabricate(:invite, user: user, expires_at: nil) }
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let!(:invite) { Fabricate(:invite, user: user, expires_at: nil) }
|
||||
before do
|
||||
delete :destroy, params: { id: invite.id }
|
||||
end
|
||||
|
||||
it 'redirects' do
|
||||
expect(response).to redirect_to invites_path
|
||||
end
|
||||
|
||||
it 'expires invite' do
|
||||
expect(subject).to redirect_to invites_path
|
||||
expect(invite.reload).to be_expired
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,11 +7,24 @@ describe ManifestsController do
|
||||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
get :show, format: :json
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns public cache control header' do
|
||||
expect(response.headers['Cache-Control']).to include('public')
|
||||
end
|
||||
|
||||
it 'does not set cookies' do
|
||||
expect(response.cookies).to be_empty
|
||||
expect(response.headers['Set-Cookies']).to be_nil
|
||||
end
|
||||
|
||||
it 'does not set sessions' do
|
||||
expect(session).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,6 +31,11 @@ RSpec.describe Oauth::AuthorizationsController, type: :controller do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
subject
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
|
||||
it 'gives options to authorize and deny' do
|
||||
subject
|
||||
expect(response.body).to match(/Authorize/)
|
||||
|
||||
@@ -27,6 +27,11 @@ describe Oauth::AuthorizedApplicationsController do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
subject
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
|
||||
include_examples 'stores location for user'
|
||||
end
|
||||
|
||||
|
||||
@@ -7,42 +7,39 @@ describe RelationshipsController do
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
shared_examples 'authenticate user' do
|
||||
it 'redirects when not signed in' do
|
||||
expect(subject).to redirect_to '/auth/sign_in'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
subject { get :show, params: { page: 2, relationship: 'followed_by' } }
|
||||
context 'when signed in' do
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
get :show, params: { page: 2, relationship: 'followed_by' }
|
||||
end
|
||||
|
||||
it 'assigns @accounts' do
|
||||
Fabricate(:account, domain: 'old').follow!(user.account)
|
||||
Fabricate(:account, domain: 'recent').follow!(user.account)
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
sign_in user, scope: :user
|
||||
subject
|
||||
|
||||
assigned = assigns(:accounts).per(1).to_a
|
||||
expect(assigned.size).to eq 1
|
||||
expect(assigned[0].domain).to eq 'old'
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
sign_in user, scope: :user
|
||||
subject
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
context 'when not signed in' do
|
||||
before do
|
||||
get :show, params: { page: 2, relationship: 'followed_by' }
|
||||
end
|
||||
|
||||
include_examples 'authenticate user'
|
||||
it 'redirects when not signed in' do
|
||||
expect(response).to redirect_to '/auth/sign_in'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH #update' do
|
||||
let(:poopfeast) { Fabricate(:account, username: 'poopfeast', domain: 'example.com') }
|
||||
let(:alice) { Fabricate(:account, username: 'alice', domain: 'example.com') }
|
||||
|
||||
shared_examples 'redirects back to followers page' do
|
||||
it 'redirects back to followers page' do
|
||||
poopfeast.follow!(user.account)
|
||||
alice.follow!(user.account)
|
||||
|
||||
sign_in user, scope: :user
|
||||
subject
|
||||
@@ -58,27 +55,36 @@ describe RelationshipsController do
|
||||
end
|
||||
|
||||
context 'when select parameter is provided' do
|
||||
subject { patch :update, params: { form_account_batch: { account_ids: [poopfeast.id] }, remove_domains_from_followers: '' } }
|
||||
subject { patch :update, params: { form_account_batch: { account_ids: [alice.id] }, remove_domains_from_followers: '' } }
|
||||
|
||||
it 'soft-blocks followers from selected domains' do
|
||||
poopfeast.follow!(user.account)
|
||||
alice.follow!(user.account)
|
||||
|
||||
sign_in user, scope: :user
|
||||
subject
|
||||
|
||||
expect(poopfeast.following?(user.account)).to be false
|
||||
expect(alice.following?(user.account)).to be false
|
||||
end
|
||||
|
||||
it 'does not unfollow users from selected domains' do
|
||||
user.account.follow!(poopfeast)
|
||||
user.account.follow!(alice)
|
||||
|
||||
sign_in user, scope: :user
|
||||
subject
|
||||
|
||||
expect(user.account.following?(poopfeast)).to be true
|
||||
expect(user.account.following?(alice)).to be true
|
||||
end
|
||||
|
||||
context 'when not signed in' do
|
||||
before do
|
||||
subject
|
||||
end
|
||||
|
||||
it 'redirects when not signed in' do
|
||||
expect(response).to redirect_to '/auth/sign_in'
|
||||
end
|
||||
end
|
||||
|
||||
include_examples 'authenticate user'
|
||||
include_examples 'redirects back to followers page'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,10 +13,17 @@ describe Settings::AliasesController do
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
|
||||
@@ -13,13 +13,17 @@ describe Settings::ApplicationsController do
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let!(:other_app) { Fabricate(:application) }
|
||||
|
||||
it 'shows apps' do
|
||||
before do
|
||||
Fabricate(:application)
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(assigns(:applications)).to include(app)
|
||||
expect(assigns(:applications)).to_not include(other_app)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -11,20 +11,27 @@ describe Settings::DeletesController do
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'renders confirmation page' do
|
||||
get :show
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
|
||||
context 'when suspended' do
|
||||
let(:user) { Fabricate(:user, account_attributes: { suspended_at: Time.now.utc }) }
|
||||
|
||||
it 'returns http forbidden' do
|
||||
get :show
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -11,16 +11,16 @@ describe Settings::ExportsController do
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'renders export' do
|
||||
get :show
|
||||
|
||||
export = assigns(:export)
|
||||
expect(export).to be_instance_of Export
|
||||
expect(export.account).to eq user.account
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not signed in' do
|
||||
|
||||
@@ -10,10 +10,17 @@ RSpec.describe Settings::ImportsController, type: :controller do
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
|
||||
@@ -12,9 +12,16 @@ describe Settings::LoginActivitiesController do
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,10 +12,17 @@ describe Settings::Migration::RedirectsController do
|
||||
end
|
||||
|
||||
describe 'GET #new' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
get :new
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
|
||||
@@ -12,11 +12,17 @@ describe Settings::Preferences::AppearanceController do
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
|
||||
@@ -12,10 +12,17 @@ describe Settings::Preferences::NotificationsController do
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
|
||||
@@ -12,10 +12,17 @@ describe Settings::Preferences::OtherController do
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
|
||||
@@ -13,10 +13,17 @@ RSpec.describe Settings::ProfilesController, type: :controller do
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
|
||||
it 'includes existing credentials in list of excluded credentials' do
|
||||
get :options
|
||||
|
||||
excluded_credentials_ids = JSON.parse(response.body)['excludeCredentials'].pluck('id')
|
||||
excluded_credentials_ids = response.parsed_body['excludeCredentials'].pluck('id')
|
||||
expect(excluded_credentials_ids).to match_array(user.webauthn_credentials.pluck(:external_id))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,23 +26,25 @@ describe Settings::TwoFactorAuthenticationMethodsController do
|
||||
describe 'when user has enabled otp' do
|
||||
before do
|
||||
user.update(otp_required_for_login: true)
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when user has not enabled otp' do
|
||||
before do
|
||||
user.update(otp_required_for_login: false)
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'redirects to enable otp' do
|
||||
get :index
|
||||
|
||||
expect(response).to redirect_to(settings_otp_authentication_path)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ describe SharesController do
|
||||
|
||||
before { sign_in user }
|
||||
|
||||
describe 'GTE #show' do
|
||||
describe 'GET #show' do
|
||||
subject(:body_classes) { assigns(:body_classes) }
|
||||
|
||||
before { get :show, params: { title: 'test title', text: 'test text', url: 'url1 url2' } }
|
||||
|
||||
@@ -11,19 +11,32 @@ RSpec.describe StatusesCleanupController, type: :controller do
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
before do
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns private cache control headers' do
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
it 'updates the account status cleanup policy' do
|
||||
before do
|
||||
put :update, params: { account_statuses_cleanup_policy: { enabled: true, min_status_age: 2.weeks.seconds, keep_direct: false, keep_polls: true } }
|
||||
expect(response).to redirect_to(statuses_cleanup_path)
|
||||
end
|
||||
|
||||
it 'updates the account status cleanup policy' do
|
||||
expect(@user.account.statuses_cleanup_policy.enabled).to be true
|
||||
expect(@user.account.statuses_cleanup_policy.keep_direct).to be false
|
||||
expect(@user.account.statuses_cleanup_policy.keep_polls).to be true
|
||||
end
|
||||
|
||||
it 'redirects' do
|
||||
expect(response).to redirect_to(statuses_cleanup_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,6 +15,10 @@ describe StatusesController do
|
||||
expect(session).to be_empty
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to include 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns public Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'public'
|
||||
end
|
||||
@@ -80,7 +84,7 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns public Cache-Control header' do
|
||||
@@ -105,7 +109,7 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it_behaves_like 'cacheable response'
|
||||
@@ -204,11 +208,11 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns no Cache-Control header' do
|
||||
expect(response.headers).to_not include 'Cache-Control'
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
@@ -229,11 +233,11 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns public Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'public'
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'returns Content-Type header' do
|
||||
@@ -268,11 +272,11 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns no Cache-Control header' do
|
||||
expect(response.headers).to_not include 'Cache-Control'
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
@@ -293,7 +297,7 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
@@ -355,11 +359,11 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns no Cache-Control header' do
|
||||
expect(response.headers).to_not include 'Cache-Control'
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
@@ -380,7 +384,7 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
@@ -468,11 +472,11 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns no Cache-Control header' do
|
||||
expect(response.headers).to_not include 'Cache-Control'
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
@@ -493,7 +497,7 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it_behaves_like 'cacheable response'
|
||||
@@ -530,11 +534,11 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns no Cache-Control header' do
|
||||
expect(response.headers).to_not include 'Cache-Control'
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
@@ -555,7 +559,7 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
@@ -617,11 +621,11 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns no Cache-Control header' do
|
||||
expect(response.headers).to_not include 'Cache-Control'
|
||||
it 'returns private Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'private'
|
||||
end
|
||||
|
||||
it 'renders status' do
|
||||
@@ -642,7 +646,7 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns private Cache-Control header' do
|
||||
@@ -823,7 +827,7 @@ describe StatusesController do
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept'
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns public Cache-Control header' do
|
||||
|
||||
@@ -6,21 +6,50 @@ RSpec.describe TagsController, type: :controller do
|
||||
render_views
|
||||
|
||||
describe 'GET #show' do
|
||||
let!(:tag) { Fabricate(:tag, name: 'test') }
|
||||
let!(:local) { Fabricate(:status, tags: [tag], text: 'local #test') }
|
||||
let!(:remote) { Fabricate(:status, tags: [tag], text: 'remote #test', account: Fabricate(:account, domain: 'remote')) }
|
||||
let!(:late) { Fabricate(:status, tags: [tag], text: 'late #test') }
|
||||
let(:format) { 'html' }
|
||||
let(:tag) { Fabricate(:tag, name: 'test') }
|
||||
let(:tag_name) { tag&.name }
|
||||
|
||||
before do
|
||||
get :show, params: { id: tag_name, format: format }
|
||||
end
|
||||
|
||||
context 'when tag exists' do
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: 'test', max_id: late.id }
|
||||
expect(response).to have_http_status(200)
|
||||
context 'when requested as HTML' do
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns public Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'public'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when requested as JSON' do
|
||||
let(:format) { 'json' }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns Vary header' do
|
||||
expect(response.headers['Vary']).to eq 'Accept, Accept-Language, Cookie'
|
||||
end
|
||||
|
||||
it 'returns public Cache-Control header' do
|
||||
expect(response.headers['Cache-Control']).to include 'public'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when tag does not exist' do
|
||||
let(:tag_name) { 'hoge' }
|
||||
|
||||
it 'returns http not found' do
|
||||
get :show, params: { id: 'none' }
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Using OAuth from an external app' do
|
||||
let(:client_app) { Doorkeeper::Application.create!(name: 'test', redirect_uri: 'http://localhost/', scopes: 'read') }
|
||||
|
||||
context 'when the user is already logged in' do
|
||||
let!(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
it 'when accepting the authorization request' do
|
||||
params = { client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' }
|
||||
visit "/oauth/authorize?#{params.to_query}"
|
||||
|
||||
# It presents the user with an authorization page
|
||||
expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize'))
|
||||
|
||||
# Upon authorizing, it redirects to the apps' callback URL
|
||||
click_on I18n.t('doorkeeper.authorizations.buttons.authorize')
|
||||
expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true)
|
||||
|
||||
# It grants the app access to the account
|
||||
expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be true
|
||||
end
|
||||
|
||||
it 'when rejecting the authorization request' do
|
||||
params = { client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' }
|
||||
visit "/oauth/authorize?#{params.to_query}"
|
||||
|
||||
# It presents the user with an authorization page
|
||||
expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.deny'))
|
||||
|
||||
# Upon denying, it redirects to the apps' callback URL
|
||||
click_on I18n.t('doorkeeper.authorizations.buttons.deny')
|
||||
expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true)
|
||||
|
||||
# It does not grant the app access to the account
|
||||
expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user is not already logged in' do
|
||||
let(:email) { 'test@example.com' }
|
||||
let(:password) { 'testpassword' }
|
||||
let(:user) { Fabricate(:user, email: email, password: password) }
|
||||
|
||||
before do
|
||||
user.confirm!
|
||||
user.approve!
|
||||
end
|
||||
|
||||
it 'when accepting the authorization request' do
|
||||
params = { client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' }
|
||||
visit "/oauth/authorize?#{params.to_query}"
|
||||
|
||||
# It presents the user with a log-in page
|
||||
expect(page).to have_content(I18n.t('auth.login'))
|
||||
|
||||
# Failing to log-in presents the form again
|
||||
fill_in 'user_email', with: email
|
||||
fill_in 'user_password', with: 'wrong password'
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('auth.login'))
|
||||
|
||||
# Logging in redirects to an authorization page
|
||||
fill_in 'user_email', with: email
|
||||
fill_in 'user_password', with: password
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize'))
|
||||
|
||||
# Upon authorizing, it redirects to the apps' callback URL
|
||||
click_on I18n.t('doorkeeper.authorizations.buttons.authorize')
|
||||
expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true)
|
||||
|
||||
# It grants the app access to the account
|
||||
expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be true
|
||||
end
|
||||
|
||||
it 'when rejecting the authorization request' do
|
||||
params = { client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' }
|
||||
visit "/oauth/authorize?#{params.to_query}"
|
||||
|
||||
# It presents the user with a log-in page
|
||||
expect(page).to have_content(I18n.t('auth.login'))
|
||||
|
||||
# Failing to log-in presents the form again
|
||||
fill_in 'user_email', with: email
|
||||
fill_in 'user_password', with: 'wrong password'
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('auth.login'))
|
||||
|
||||
# Logging in redirects to an authorization page
|
||||
fill_in 'user_email', with: email
|
||||
fill_in 'user_password', with: password
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize'))
|
||||
|
||||
# Upon denying, it redirects to the apps' callback URL
|
||||
click_on I18n.t('doorkeeper.authorizations.buttons.deny')
|
||||
expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true)
|
||||
|
||||
# It does not grant the app access to the account
|
||||
expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be false
|
||||
end
|
||||
|
||||
context 'when the user has set up TOTP' do
|
||||
let(:user) { Fabricate(:user, email: email, password: password, otp_required_for_login: true, otp_secret: User.generate_otp_secret(32)) }
|
||||
|
||||
it 'when accepting the authorization request' do
|
||||
params = { client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' }
|
||||
visit "/oauth/authorize?#{params.to_query}"
|
||||
|
||||
# It presents the user with a log-in page
|
||||
expect(page).to have_content(I18n.t('auth.login'))
|
||||
|
||||
# Failing to log-in presents the form again
|
||||
fill_in 'user_email', with: email
|
||||
fill_in 'user_password', with: 'wrong password'
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('auth.login'))
|
||||
|
||||
# Logging in redirects to a two-factor authentication page
|
||||
fill_in 'user_email', with: email
|
||||
fill_in 'user_password', with: password
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('simple_form.hints.sessions.otp'))
|
||||
|
||||
# Filling in an incorrect two-factor authentication code presents the form again
|
||||
fill_in 'user_otp_attempt', with: 'wrong'
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('simple_form.hints.sessions.otp'))
|
||||
|
||||
# Filling in the correct TOTP code redirects to an app authorization page
|
||||
fill_in 'user_otp_attempt', with: user.current_otp
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize'))
|
||||
|
||||
# Upon authorizing, it redirects to the apps' callback URL
|
||||
click_on I18n.t('doorkeeper.authorizations.buttons.authorize')
|
||||
expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true)
|
||||
|
||||
# It grants the app access to the account
|
||||
expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be true
|
||||
end
|
||||
|
||||
it 'when rejecting the authorization request' do
|
||||
params = { client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' }
|
||||
visit "/oauth/authorize?#{params.to_query}"
|
||||
|
||||
# It presents the user with a log-in page
|
||||
expect(page).to have_content(I18n.t('auth.login'))
|
||||
|
||||
# Failing to log-in presents the form again
|
||||
fill_in 'user_email', with: email
|
||||
fill_in 'user_password', with: 'wrong password'
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('auth.login'))
|
||||
|
||||
# Logging in redirects to a two-factor authentication page
|
||||
fill_in 'user_email', with: email
|
||||
fill_in 'user_password', with: password
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('simple_form.hints.sessions.otp'))
|
||||
|
||||
# Filling in an incorrect two-factor authentication code presents the form again
|
||||
fill_in 'user_otp_attempt', with: 'wrong'
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('simple_form.hints.sessions.otp'))
|
||||
|
||||
# Filling in the correct TOTP code redirects to an app authorization page
|
||||
fill_in 'user_otp_attempt', with: user.current_otp
|
||||
click_on I18n.t('auth.login')
|
||||
expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize'))
|
||||
|
||||
# Upon denying, it redirects to the apps' callback URL
|
||||
click_on I18n.t('doorkeeper.authorizations.buttons.deny')
|
||||
expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true)
|
||||
|
||||
# It does not grant the app access to the account
|
||||
expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: external auth
|
||||
end
|
||||
end
|
||||
@@ -27,6 +27,22 @@ describe ApplicationHelper do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'body_classes' do
|
||||
context 'with a body class string from a controller' do
|
||||
before do
|
||||
without_partial_double_verification do
|
||||
allow(helper).to receive(:body_class_string).and_return('modal-layout compose-standalone')
|
||||
allow(helper).to receive(:current_theme).and_return('default')
|
||||
allow(helper).to receive(:current_account).and_return(Fabricate(:account))
|
||||
end
|
||||
end
|
||||
|
||||
it 'uses the controller body classes in the result' do
|
||||
expect(helper.body_classes).to match(/modal-layout compose-standalone/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'locale_direction' do
|
||||
around do |example|
|
||||
current_locale = I18n.locale
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe MediaComponentHelper do
|
||||
describe 'render_video_component' do
|
||||
let(:media) { Fabricate(:media_attachment, type: :video, status: Fabricate(:status)) }
|
||||
let(:result) { helper.render_video_component(media.status) }
|
||||
|
||||
before do
|
||||
without_partial_double_verification do
|
||||
allow(helper).to receive(:current_account).and_return(media.account)
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders a react component for the video' do
|
||||
expect(parsed_html.div['data-component']).to eq('Video')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'render_audio_component' do
|
||||
let(:media) { Fabricate(:media_attachment, type: :audio, status: Fabricate(:status)) }
|
||||
let(:result) { helper.render_audio_component(media.status) }
|
||||
|
||||
before do
|
||||
without_partial_double_verification do
|
||||
allow(helper).to receive(:current_account).and_return(media.account)
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders a react component for the audio' do
|
||||
expect(parsed_html.div['data-component']).to eq('Audio')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'render_media_gallery_component' do
|
||||
let(:media) { Fabricate(:media_attachment, type: :audio, status: Fabricate(:status)) }
|
||||
let(:result) { helper.render_media_gallery_component(media.status) }
|
||||
|
||||
before do
|
||||
without_partial_double_verification do
|
||||
allow(helper).to receive(:current_account).and_return(media.account)
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders a react component for the media gallery' do
|
||||
expect(parsed_html.div['data-component']).to eq('MediaGallery')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'render_card_component' do
|
||||
let(:status) { Fabricate(:status, preview_cards: [Fabricate(:preview_card)]) }
|
||||
let(:result) { helper.render_card_component(status) }
|
||||
|
||||
before do
|
||||
without_partial_double_verification do
|
||||
allow(helper).to receive(:current_account).and_return(status.account)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the correct react component markup' do
|
||||
expect(parsed_html.div['data-component']).to eq('Card')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'render_poll_component' do
|
||||
let(:status) { Fabricate(:status, poll: Fabricate(:poll)) }
|
||||
let(:result) { helper.render_poll_component(status) }
|
||||
|
||||
before do
|
||||
without_partial_double_verification do
|
||||
allow(helper).to receive(:current_account).and_return(status.account)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the correct react component markup' do
|
||||
expect(parsed_html.div['data-component']).to eq('Poll')
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parsed_html
|
||||
Nokogiri::Slop(result)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ReactComponentHelper do
|
||||
describe 'react_component' do
|
||||
context 'with no block passed in' do
|
||||
let(:result) { helper.react_component('name', { one: :two }) }
|
||||
|
||||
it 'returns a tag with data attributes' do
|
||||
expect(parsed_html.div['data-component']).to eq('Name')
|
||||
expect(parsed_html.div['data-props']).to eq('{"one":"two"}')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a block passed in' do
|
||||
let(:result) do
|
||||
helper.react_component('name', { one: :two }) do
|
||||
helper.content_tag(:nav, 'ok')
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns a tag with data attributes' do
|
||||
expect(parsed_html.div['data-component']).to eq('Name')
|
||||
expect(parsed_html.div['data-props']).to eq('{"one":"two"}')
|
||||
expect(parsed_html.div.nav.content).to eq('ok')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'react_admin_component' do
|
||||
let(:result) { helper.react_admin_component('name', { one: :two }) }
|
||||
|
||||
it 'returns a tag with data attributes' do
|
||||
expect(parsed_html.div['data-admin-component']).to eq('Name')
|
||||
expect(parsed_html.div['data-props']).to eq('{"locale":"en","one":"two"}')
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parsed_html
|
||||
Nokogiri::Slop(result)
|
||||
end
|
||||
end
|
||||
@@ -26,22 +26,22 @@ describe AccountFilter do
|
||||
|
||||
it 'works with domain first and origin remote' do
|
||||
filter = described_class.new(by_domain: 'example.org', origin: 'remote')
|
||||
expect(filter.results).to match_array [remote_account_one]
|
||||
expect(filter.results).to contain_exactly(remote_account_one)
|
||||
end
|
||||
|
||||
it 'works with domain last and origin remote' do
|
||||
filter = described_class.new(origin: 'remote', by_domain: 'example.org')
|
||||
expect(filter.results).to match_array [remote_account_one]
|
||||
expect(filter.results).to contain_exactly(remote_account_one)
|
||||
end
|
||||
|
||||
it 'works with domain first and origin local' do
|
||||
filter = described_class.new(by_domain: 'example.org', origin: 'local')
|
||||
expect(filter.results).to match_array [local_account]
|
||||
expect(filter.results).to contain_exactly(local_account)
|
||||
end
|
||||
|
||||
it 'works with domain last and origin local' do
|
||||
filter = described_class.new(origin: 'local', by_domain: 'example.org')
|
||||
expect(filter.results).to match_array [remote_account_one]
|
||||
expect(filter.results).to contain_exactly(remote_account_one)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -50,17 +50,17 @@ describe AccountFilter do
|
||||
|
||||
it 'works with @ at the beginning of the username' do
|
||||
filter = described_class.new(username: '@validUserName')
|
||||
expect(filter.results).to match_array [local_account]
|
||||
expect(filter.results).to contain_exactly(local_account)
|
||||
end
|
||||
|
||||
it 'does not work with more than one @ at the beginning of the username' do
|
||||
filter = described_class.new(username: '@@validUserName')
|
||||
expect(filter.results).to_not match_array [local_account]
|
||||
expect(filter.results).to_not contain_exactly(local_account)
|
||||
end
|
||||
|
||||
it 'does not work with @ outside the beginning of the username' do
|
||||
filter = described_class.new(username: 'validUserName@')
|
||||
expect(filter.results).to_not match_array [local_account]
|
||||
expect(filter.results).to_not contain_exactly(local_account)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -339,7 +339,7 @@ RSpec.describe Account, type: :model do
|
||||
it 'returns the domains blocked by the account' do
|
||||
account = Fabricate(:account)
|
||||
account.block_domain!('domain')
|
||||
expect(account.excluded_from_timeline_domains).to match_array ['domain']
|
||||
expect(account.excluded_from_timeline_domains).to contain_exactly('domain')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -877,7 +877,7 @@ RSpec.describe Account, type: :model do
|
||||
it 'returns an array of accounts who have a domain' do
|
||||
account_1 = Fabricate(:account, domain: nil)
|
||||
account_2 = Fabricate(:account, domain: 'example.com')
|
||||
expect(Account.remote).to match_array([account_2])
|
||||
expect(Account.remote).to contain_exactly(account_2)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -885,7 +885,7 @@ RSpec.describe Account, type: :model do
|
||||
it 'returns an array of accounts who do not have a domain' do
|
||||
account_1 = Fabricate(:account, domain: nil)
|
||||
account_2 = Fabricate(:account, domain: 'example.com')
|
||||
expect(Account.where('id > 0').local).to match_array([account_1])
|
||||
expect(Account.where('id > 0').local).to contain_exactly(account_1)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -911,7 +911,7 @@ RSpec.describe Account, type: :model do
|
||||
it 'returns an array of accounts who are silenced' do
|
||||
account_1 = Fabricate(:account, silenced: true)
|
||||
account_2 = Fabricate(:account, silenced: false)
|
||||
expect(Account.silenced).to match_array([account_1])
|
||||
expect(Account.silenced).to contain_exactly(account_1)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -919,7 +919,7 @@ RSpec.describe Account, type: :model do
|
||||
it 'returns an array of accounts who are suspended' do
|
||||
account_1 = Fabricate(:account, suspended: true)
|
||||
account_2 = Fabricate(:account, suspended: false)
|
||||
expect(Account.suspended).to match_array([account_1])
|
||||
expect(Account.suspended).to contain_exactly(account_1)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -941,11 +941,11 @@ RSpec.describe Account, type: :model do
|
||||
end
|
||||
|
||||
it 'returns every usable non-suspended account' do
|
||||
expect(Account.searchable).to match_array([silenced_local, silenced_remote, local_account, remote_account])
|
||||
expect(Account.searchable).to contain_exactly(silenced_local, silenced_remote, local_account, remote_account)
|
||||
end
|
||||
|
||||
it 'does not mess with previously-applied scopes' do
|
||||
expect(Account.where.not(id: remote_account.id).searchable).to match_array([silenced_local, silenced_remote, local_account])
|
||||
expect(Account.where.not(id: remote_account.id).searchable).to contain_exactly(silenced_local, silenced_remote, local_account)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -496,7 +496,7 @@ RSpec.describe AccountStatusesCleanupPolicy, type: :model do
|
||||
end
|
||||
|
||||
it 'returns only normal statuses for deletion' do
|
||||
expect(subject.pluck(:id)).to match_array([very_old_status.id, faved4.id, faved5.id, reblogged4.id, reblogged5.id])
|
||||
expect(subject.pluck(:id)).to contain_exactly(very_old_status.id, faved4.id, faved5.id, reblogged4.id, reblogged5.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ RSpec.describe CustomEmojiFilter do
|
||||
|
||||
it 'returns ActiveRecord::Relation' do
|
||||
expect(subject).to be_a(ActiveRecord::Relation)
|
||||
expect(subject).to match_array([custom_emoji_2])
|
||||
expect(subject).to contain_exactly(custom_emoji_2)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,7 +25,7 @@ RSpec.describe CustomEmojiFilter do
|
||||
|
||||
it 'returns ActiveRecord::Relation' do
|
||||
expect(subject).to be_a(ActiveRecord::Relation)
|
||||
expect(subject).to match_array([custom_emoji_0, custom_emoji_1])
|
||||
expect(subject).to contain_exactly(custom_emoji_0, custom_emoji_1)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ RSpec.describe CustomEmojiFilter do
|
||||
|
||||
it 'returns ActiveRecord::Relation' do
|
||||
expect(subject).to be_a(ActiveRecord::Relation)
|
||||
expect(subject).to match_array([custom_emoji_0])
|
||||
expect(subject).to contain_exactly(custom_emoji_0)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -43,7 +43,7 @@ RSpec.describe CustomEmojiFilter do
|
||||
|
||||
it 'returns ActiveRecord::Relation' do
|
||||
expect(subject).to be_a(ActiveRecord::Relation)
|
||||
expect(subject).to match_array([custom_emoji_2])
|
||||
expect(subject).to contain_exactly(custom_emoji_2)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -63,7 +63,7 @@ RSpec.describe CustomEmojiFilter do
|
||||
|
||||
it 'returns ActiveRecord::Relation' do
|
||||
expect(subject).to be_a(ActiveRecord::Relation)
|
||||
expect(subject).to match_array([custom_emoji_0, custom_emoji_1, custom_emoji_2])
|
||||
expect(subject).to contain_exactly(custom_emoji_0, custom_emoji_1, custom_emoji_2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
+16
-16
@@ -352,17 +352,17 @@ RSpec.describe Status, type: :model do
|
||||
|
||||
context 'when given one tag' do
|
||||
it 'returns the expected statuses' do
|
||||
expect(Status.tagged_with([tag1.id]).reorder(:id).pluck(:id).uniq).to match_array([status1.id, status5.id])
|
||||
expect(Status.tagged_with([tag2.id]).reorder(:id).pluck(:id).uniq).to match_array([status2.id, status5.id])
|
||||
expect(Status.tagged_with([tag3.id]).reorder(:id).pluck(:id).uniq).to match_array([status3.id, status5.id])
|
||||
expect(Status.tagged_with([tag1.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status5.id)
|
||||
expect(Status.tagged_with([tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status2.id, status5.id)
|
||||
expect(Status.tagged_with([tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status3.id, status5.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when given multiple tags' do
|
||||
it 'returns the expected statuses' do
|
||||
expect(Status.tagged_with([tag1.id, tag2.id]).reorder(:id).pluck(:id).uniq).to match_array([status1.id, status2.id, status5.id])
|
||||
expect(Status.tagged_with([tag1.id, tag3.id]).reorder(:id).pluck(:id).uniq).to match_array([status1.id, status3.id, status5.id])
|
||||
expect(Status.tagged_with([tag2.id, tag3.id]).reorder(:id).pluck(:id).uniq).to match_array([status2.id, status3.id, status5.id])
|
||||
expect(Status.tagged_with([tag1.id, tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status2.id, status5.id)
|
||||
expect(Status.tagged_with([tag1.id, tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status3.id, status5.id)
|
||||
expect(Status.tagged_with([tag2.id, tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status2.id, status3.id, status5.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -379,15 +379,15 @@ RSpec.describe Status, type: :model do
|
||||
|
||||
context 'when given one tag' do
|
||||
it 'returns the expected statuses' do
|
||||
expect(Status.tagged_with_all([tag1.id]).reorder(:id).pluck(:id).uniq).to match_array([status1.id, status5.id])
|
||||
expect(Status.tagged_with_all([tag2.id]).reorder(:id).pluck(:id).uniq).to match_array([status2.id, status5.id])
|
||||
expect(Status.tagged_with_all([tag3.id]).reorder(:id).pluck(:id).uniq).to match_array([status3.id])
|
||||
expect(Status.tagged_with_all([tag1.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status5.id)
|
||||
expect(Status.tagged_with_all([tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status2.id, status5.id)
|
||||
expect(Status.tagged_with_all([tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status3.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when given multiple tags' do
|
||||
it 'returns the expected statuses' do
|
||||
expect(Status.tagged_with_all([tag1.id, tag2.id]).reorder(:id).pluck(:id).uniq).to match_array([status5.id])
|
||||
expect(Status.tagged_with_all([tag1.id, tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status5.id)
|
||||
expect(Status.tagged_with_all([tag1.id, tag3.id]).reorder(:id).pluck(:id).uniq).to eq []
|
||||
expect(Status.tagged_with_all([tag2.id, tag3.id]).reorder(:id).pluck(:id).uniq).to eq []
|
||||
end
|
||||
@@ -406,17 +406,17 @@ RSpec.describe Status, type: :model do
|
||||
|
||||
context 'when given one tag' do
|
||||
it 'returns the expected statuses' do
|
||||
expect(Status.tagged_with_none([tag1.id]).reorder(:id).pluck(:id).uniq).to match_array([status2.id, status3.id, status4.id])
|
||||
expect(Status.tagged_with_none([tag2.id]).reorder(:id).pluck(:id).uniq).to match_array([status1.id, status3.id, status4.id])
|
||||
expect(Status.tagged_with_none([tag3.id]).reorder(:id).pluck(:id).uniq).to match_array([status1.id, status2.id, status4.id])
|
||||
expect(Status.tagged_with_none([tag1.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status2.id, status3.id, status4.id)
|
||||
expect(Status.tagged_with_none([tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status3.id, status4.id)
|
||||
expect(Status.tagged_with_none([tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status2.id, status4.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when given multiple tags' do
|
||||
it 'returns the expected statuses' do
|
||||
expect(Status.tagged_with_none([tag1.id, tag2.id]).reorder(:id).pluck(:id).uniq).to match_array([status3.id, status4.id])
|
||||
expect(Status.tagged_with_none([tag1.id, tag3.id]).reorder(:id).pluck(:id).uniq).to match_array([status2.id, status4.id])
|
||||
expect(Status.tagged_with_none([tag2.id, tag3.id]).reorder(:id).pluck(:id).uniq).to match_array([status1.id, status4.id])
|
||||
expect(Status.tagged_with_none([tag1.id, tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status3.id, status4.id)
|
||||
expect(Status.tagged_with_none([tag1.id, tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status2.id, status4.id)
|
||||
expect(Status.tagged_with_none([tag2.id, tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status4.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -65,7 +65,7 @@ RSpec.describe User, type: :model do
|
||||
it 'returns an array of users who are confirmed' do
|
||||
user_1 = Fabricate(:user, confirmed_at: nil)
|
||||
user_2 = Fabricate(:user, confirmed_at: Time.zone.now)
|
||||
expect(User.confirmed).to match_array([user_2])
|
||||
expect(User.confirmed).to contain_exactly(user_2)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -74,7 +74,7 @@ RSpec.describe User, type: :model do
|
||||
specified = Fabricate(:user, current_sign_in_at: 15.days.ago)
|
||||
Fabricate(:user, current_sign_in_at: 6.days.ago)
|
||||
|
||||
expect(User.inactive).to match_array([specified])
|
||||
expect(User.inactive).to contain_exactly(specified)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -83,7 +83,7 @@ RSpec.describe User, type: :model do
|
||||
specified = Fabricate(:user, email: 'specified@spec')
|
||||
Fabricate(:user, email: 'unspecified@spec')
|
||||
|
||||
expect(User.matches_email('specified')).to match_array([specified])
|
||||
expect(User.matches_email('specified')).to contain_exactly(specified)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -96,7 +96,7 @@ RSpec.describe User, type: :model do
|
||||
Fabricate(:session_activation, user: user2, ip: '2160:8888::24', session_id: '3')
|
||||
Fabricate(:session_activation, user: user2, ip: '2160:8888::25', session_id: '4')
|
||||
|
||||
expect(User.matches_ip('2160:2160::/32')).to match_array([user1])
|
||||
expect(User.matches_ip('2160:2160::/32')).to contain_exactly(user1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,7 +24,7 @@ RSpec.describe FamiliarFollowersPresenter do
|
||||
|
||||
expect(result).to_not be_nil
|
||||
expect(result.id).to eq requested_accounts.first.id
|
||||
expect(result.accounts).to match_array([familiar_follower])
|
||||
expect(result.accounts).to contain_exactly(familiar_follower)
|
||||
end
|
||||
|
||||
context 'when requested account hides followers' do
|
||||
|
||||
@@ -43,7 +43,9 @@ RSpec.configure do |config|
|
||||
config.filter_rails_from_backtrace!
|
||||
|
||||
config.include Devise::Test::ControllerHelpers, type: :controller
|
||||
config.include Devise::Test::ControllerHelpers, type: :helper
|
||||
config.include Devise::Test::ControllerHelpers, type: :view
|
||||
config.include Devise::Test::IntegrationHelpers, type: :feature
|
||||
config.include Paperclip::Shoulda::Matchers
|
||||
config.include ActiveSupport::Testing::TimeHelpers
|
||||
config.include Chewy::Rspec::Helpers
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
context 'when visited anonymously' do
|
||||
around do |example|
|
||||
old = ActionController::Base.allow_forgery_protection
|
||||
ActionController::Base.allow_forgery_protection = true
|
||||
|
||||
example.run
|
||||
|
||||
ActionController::Base.allow_forgery_protection = old
|
||||
end
|
||||
|
||||
describe 'account pages' do
|
||||
it 'do not set cookies' do
|
||||
alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
|
||||
_status = Fabricate(:status, account: alice, text: 'Hello World')
|
||||
|
||||
get '/@alice'
|
||||
|
||||
expect(response.cookies).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe 'status pages' do
|
||||
it 'do not set cookies' do
|
||||
alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
|
||||
status = Fabricate(:status, account: alice, text: 'Hello World')
|
||||
|
||||
get short_account_status_url(alice, status)
|
||||
|
||||
expect(response.cookies).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe 'the /about page' do
|
||||
it 'does not set cookies' do
|
||||
get '/about'
|
||||
|
||||
expect(response.cookies).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -71,7 +71,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do
|
||||
end
|
||||
|
||||
it 'sets expected posts as pinned posts' do
|
||||
expect(actor.pinned_statuses.pluck(:uri)).to match_array ['https://example.com/account/pinned/1', 'https://example.com/account/pinned/2', 'https://example.com/account/pinned/4']
|
||||
expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly('https://example.com/account/pinned/1', 'https://example.com/account/pinned/2', 'https://example.com/account/pinned/4')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ RSpec.describe UpdateStatusService, type: :service do
|
||||
end
|
||||
|
||||
it 'keeps old mentions as silent mentions' do
|
||||
expect(status.mentions.pluck(:account_id)).to match_array([alice.id, bob.id])
|
||||
expect(status.mentions.pluck(:account_id)).to contain_exactly(alice.id, bob.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -9,11 +9,13 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
|
||||
let!(:account2) { Fabricate(:account, domain: nil) }
|
||||
let!(:account3) { Fabricate(:account, domain: nil) }
|
||||
let!(:account4) { Fabricate(:account, domain: nil) }
|
||||
let!(:account5) { Fabricate(:account, domain: nil) }
|
||||
let!(:remote) { Fabricate(:account) }
|
||||
|
||||
let!(:policy1) { Fabricate(:account_statuses_cleanup_policy, account: account1) }
|
||||
let!(:policy2) { Fabricate(:account_statuses_cleanup_policy, account: account3) }
|
||||
let!(:policy3) { Fabricate(:account_statuses_cleanup_policy, account: account4, enabled: false) }
|
||||
let!(:policy4) { Fabricate(:account_statuses_cleanup_policy, account: account5) }
|
||||
|
||||
let(:queue_size) { 0 }
|
||||
let(:queue_latency) { 0 }
|
||||
@@ -42,6 +44,7 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
|
||||
Fabricate(:status, account: account2, created_at: 3.years.ago)
|
||||
Fabricate(:status, account: account3, created_at: 3.years.ago)
|
||||
Fabricate(:status, account: account4, created_at: 3.years.ago)
|
||||
Fabricate(:status, account: account5, created_at: 3.years.ago)
|
||||
Fabricate(:status, account: remote, created_at: 3.years.ago)
|
||||
end
|
||||
|
||||
@@ -111,8 +114,21 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
|
||||
expect { subject.perform }.to_not change { account4.statuses.count }
|
||||
end
|
||||
|
||||
it 'eventually deletes every deletable toot' do
|
||||
expect { subject.perform; subject.perform; subject.perform; subject.perform }.to change { Status.count }.by(-20)
|
||||
it 'eventually deletes every deletable toot given enough runs' do
|
||||
stub_const 'Scheduler::AccountsStatusesCleanupScheduler::MAX_BUDGET', 4
|
||||
|
||||
expect { 10.times { subject.perform } }.to change { Status.count }.by(-30)
|
||||
end
|
||||
|
||||
it 'correctly round-trips between users across several runs' do
|
||||
stub_const 'Scheduler::AccountsStatusesCleanupScheduler::MAX_BUDGET', 3
|
||||
stub_const 'Scheduler::AccountsStatusesCleanupScheduler::PER_ACCOUNT_BUDGET', 2
|
||||
|
||||
expect { 3.times { subject.perform } }
|
||||
.to change { Status.count }.by(-3 * 3)
|
||||
.and change { account1.statuses.count }
|
||||
.and change { account3.statuses.count }
|
||||
.and change { account5.statuses.count }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user