mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-28 21:56:36 +00:00
Merge commit '5dfdec645313e556413147597138a8008bc35996' into glitch-soc/merge-upstream
This commit is contained in:
@@ -69,9 +69,10 @@ RSpec.describe ActivityPub::OutboxesController do
|
||||
|
||||
expect(response.parsed_body)
|
||||
.to include(
|
||||
orderedItems: be_an(Array).and(have_attributes(size: 2))
|
||||
orderedItems: be_an(Array)
|
||||
.and(have_attributes(size: 2))
|
||||
.and(all(satisfy { |item| targets_public_collection?(item) }))
|
||||
)
|
||||
expect(response.parsed_body[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true
|
||||
end
|
||||
|
||||
context 'when account is permanently suspended' do
|
||||
@@ -113,9 +114,10 @@ RSpec.describe ActivityPub::OutboxesController do
|
||||
|
||||
expect(response.parsed_body)
|
||||
.to include(
|
||||
orderedItems: be_an(Array).and(have_attributes(size: 2))
|
||||
orderedItems: be_an(Array)
|
||||
.and(have_attributes(size: 2))
|
||||
.and(all(satisfy { |item| targets_public_collection?(item) }))
|
||||
)
|
||||
expect(response.parsed_body[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -132,9 +134,10 @@ RSpec.describe ActivityPub::OutboxesController do
|
||||
|
||||
expect(response.parsed_body)
|
||||
.to include(
|
||||
orderedItems: be_an(Array).and(have_attributes(size: 3))
|
||||
orderedItems: be_an(Array)
|
||||
.and(have_attributes(size: 3))
|
||||
.and(all(satisfy { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) }))
|
||||
)
|
||||
expect(response.parsed_body[:orderedItems].all? { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) }).to be true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Settings::ApplicationsController do
|
||||
render_views
|
||||
|
||||
let!(:user) { Fabricate(:user) }
|
||||
let!(:app) { Fabricate(:application, owner: user) }
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
before do
|
||||
Fabricate(:application)
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success with private cache control headers', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Cache-Control']).to include('private, no-store')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: app.id }
|
||||
expect(response).to have_http_status(200)
|
||||
expect(assigns[:application]).to eql(app)
|
||||
end
|
||||
|
||||
it 'returns 404 if you dont own app' do
|
||||
app.update!(owner: nil)
|
||||
|
||||
get :show, params: { id: app.id }
|
||||
expect(response).to have_http_status 404
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #new' do
|
||||
it 'returns http success' do
|
||||
get :new
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
context 'when success (passed scopes as a String)' do
|
||||
subject do
|
||||
post :create, params: {
|
||||
doorkeeper_application: {
|
||||
name: 'My New App',
|
||||
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
||||
website: 'http://google.com',
|
||||
scopes: 'read write follow',
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates an entry in the database', :aggregate_failures do
|
||||
expect { subject }.to change(Doorkeeper::Application, :count)
|
||||
expect(response).to redirect_to(settings_applications_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when success (passed scopes as an Array)' do
|
||||
subject do
|
||||
post :create, params: {
|
||||
doorkeeper_application: {
|
||||
name: 'My New App',
|
||||
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
||||
website: 'http://google.com',
|
||||
scopes: %w(read write follow),
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates an entry in the database', :aggregate_failures do
|
||||
expect { subject }.to change(Doorkeeper::Application, :count)
|
||||
expect(response).to redirect_to(settings_applications_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with failure request' do
|
||||
before do
|
||||
post :create, params: {
|
||||
doorkeeper_application: {
|
||||
name: '',
|
||||
redirect_uri: '',
|
||||
website: '',
|
||||
scopes: [],
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns http success and renders form', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response).to render_template(:new)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH #update' do
|
||||
context 'when success' do
|
||||
subject do
|
||||
patch :update, params: {
|
||||
id: app.id,
|
||||
doorkeeper_application: opts,
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
let(:opts) do
|
||||
{
|
||||
website: 'https://foo.bar/',
|
||||
}
|
||||
end
|
||||
|
||||
it 'updates existing application' do
|
||||
subject
|
||||
|
||||
expect(app.reload.website).to eql(opts[:website])
|
||||
expect(response).to redirect_to(settings_application_path(app))
|
||||
end
|
||||
end
|
||||
|
||||
context 'with failure request' do
|
||||
before do
|
||||
patch :update, params: {
|
||||
id: app.id,
|
||||
doorkeeper_application: {
|
||||
name: '',
|
||||
redirect_uri: '',
|
||||
website: '',
|
||||
scopes: [],
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns http success and renders form', :aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response).to render_template(:show)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'destroy' do
|
||||
let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) }
|
||||
let!(:access_token) { Fabricate(:accessible_access_token, application: app) }
|
||||
|
||||
before do
|
||||
allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub)
|
||||
post :destroy, params: { id: app.id }
|
||||
end
|
||||
|
||||
it 'redirects back to applications page removes the app' do
|
||||
expect(response).to redirect_to(settings_applications_path)
|
||||
expect(Doorkeeper::Application.find_by(id: app.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'sends a session kill payload to the streaming server' do
|
||||
expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'regenerate' do
|
||||
let(:token) { user.token_for_app(app) }
|
||||
|
||||
it 'creates new token' do
|
||||
expect(token).to_not be_nil
|
||||
post :regenerate, params: { id: app.id }
|
||||
|
||||
expect(user.token_for_app(app)).to_not eql(token)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -252,88 +252,83 @@ RSpec.describe Notification do
|
||||
]
|
||||
end
|
||||
|
||||
context 'with a preloaded target status' do
|
||||
it 'preloads mention' do
|
||||
expect(subject[0].type).to eq :mention
|
||||
expect(subject[0].association(:mention)).to be_loaded
|
||||
expect(subject[0].mention.association(:status)).to be_loaded
|
||||
context 'with a preloaded target status and a cached status' do
|
||||
it 'preloads association records and replaces association records' do
|
||||
expect(subject)
|
||||
.to contain_exactly(
|
||||
mention_attributes,
|
||||
status_attributes,
|
||||
reblog_attributes,
|
||||
follow_attributes,
|
||||
follow_request_attributes,
|
||||
favourite_attributes,
|
||||
poll_attributes
|
||||
)
|
||||
end
|
||||
|
||||
it 'preloads status' do
|
||||
expect(subject[1].type).to eq :status
|
||||
expect(subject[1].association(:status)).to be_loaded
|
||||
def mention_attributes
|
||||
have_attributes(
|
||||
type: :mention,
|
||||
target_status: eq(mention.status).and(have_loaded_association(:account)),
|
||||
mention: have_loaded_association(:status)
|
||||
).and(have_loaded_association(:mention))
|
||||
end
|
||||
|
||||
it 'preloads reblog' do
|
||||
expect(subject[2].type).to eq :reblog
|
||||
expect(subject[2].association(:status)).to be_loaded
|
||||
expect(subject[2].status.association(:reblog)).to be_loaded
|
||||
def status_attributes
|
||||
have_attributes(
|
||||
type: :status,
|
||||
target_status: eq(status).and(have_loaded_association(:account))
|
||||
).and(have_loaded_association(:status))
|
||||
end
|
||||
|
||||
it 'preloads follow as nil' do
|
||||
expect(subject[3].type).to eq :follow
|
||||
expect(subject[3].target_status).to be_nil
|
||||
def reblog_attributes
|
||||
have_attributes(
|
||||
type: :reblog,
|
||||
status: have_loaded_association(:reblog),
|
||||
target_status: eq(reblog.reblog).and(have_loaded_association(:account))
|
||||
).and(have_loaded_association(:status))
|
||||
end
|
||||
|
||||
it 'preloads follow_request as nill' do
|
||||
expect(subject[4].type).to eq :follow_request
|
||||
expect(subject[4].target_status).to be_nil
|
||||
def follow_attributes
|
||||
have_attributes(
|
||||
type: :follow,
|
||||
target_status: be_nil
|
||||
)
|
||||
end
|
||||
|
||||
it 'preloads favourite' do
|
||||
expect(subject[5].type).to eq :favourite
|
||||
expect(subject[5].association(:favourite)).to be_loaded
|
||||
expect(subject[5].favourite.association(:status)).to be_loaded
|
||||
def follow_request_attributes
|
||||
have_attributes(
|
||||
type: :follow_request,
|
||||
target_status: be_nil
|
||||
)
|
||||
end
|
||||
|
||||
it 'preloads poll' do
|
||||
expect(subject[6].type).to eq :poll
|
||||
expect(subject[6].association(:poll)).to be_loaded
|
||||
expect(subject[6].poll.association(:status)).to be_loaded
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a cached status' do
|
||||
it 'replaces mention' do
|
||||
expect(subject[0].type).to eq :mention
|
||||
expect(subject[0].target_status.association(:account)).to be_loaded
|
||||
expect(subject[0].target_status).to eq mention.status
|
||||
def favourite_attributes
|
||||
have_attributes(
|
||||
type: :favourite,
|
||||
favourite: have_loaded_association(:status),
|
||||
target_status: eq(favourite.status).and(have_loaded_association(:account))
|
||||
).and(have_loaded_association(:favourite))
|
||||
end
|
||||
|
||||
it 'replaces status' do
|
||||
expect(subject[1].type).to eq :status
|
||||
expect(subject[1].target_status.association(:account)).to be_loaded
|
||||
expect(subject[1].target_status).to eq status
|
||||
end
|
||||
|
||||
it 'replaces reblog' do
|
||||
expect(subject[2].type).to eq :reblog
|
||||
expect(subject[2].target_status.association(:account)).to be_loaded
|
||||
expect(subject[2].target_status).to eq reblog.reblog
|
||||
end
|
||||
|
||||
it 'replaces follow' do
|
||||
expect(subject[3].type).to eq :follow
|
||||
expect(subject[3].target_status).to be_nil
|
||||
end
|
||||
|
||||
it 'replaces follow_request' do
|
||||
expect(subject[4].type).to eq :follow_request
|
||||
expect(subject[4].target_status).to be_nil
|
||||
end
|
||||
|
||||
it 'replaces favourite' do
|
||||
expect(subject[5].type).to eq :favourite
|
||||
expect(subject[5].target_status.association(:account)).to be_loaded
|
||||
expect(subject[5].target_status).to eq favourite.status
|
||||
end
|
||||
|
||||
it 'replaces poll' do
|
||||
expect(subject[6].type).to eq :poll
|
||||
expect(subject[6].target_status.association(:account)).to be_loaded
|
||||
expect(subject[6].target_status).to eq poll.status
|
||||
def poll_attributes
|
||||
have_attributes(
|
||||
type: :poll,
|
||||
poll: have_loaded_association(:status),
|
||||
target_status: eq(poll.status).and(have_loaded_association(:account))
|
||||
).and(have_loaded_association(:poll))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec::Matchers.define :have_loaded_association do |association|
|
||||
match do |record|
|
||||
record.association(association).loaded?
|
||||
end
|
||||
|
||||
failure_message do |record|
|
||||
"expected #{record} to have loaded association #{association} but it did not."
|
||||
end
|
||||
end
|
||||
|
||||
@@ -434,7 +434,9 @@ RSpec.describe User do
|
||||
end
|
||||
|
||||
describe '#reset_password!' do
|
||||
subject(:user) { Fabricate(:user, password: 'foobar12345') }
|
||||
subject(:user) { Fabricate(:user, password: original_password) }
|
||||
|
||||
let(:original_password) { 'foobar12345' }
|
||||
|
||||
let!(:session_activation) { Fabricate(:session_activation, user: user) }
|
||||
let!(:access_token) { Fabricate(:access_token, resource_owner_id: user.id) }
|
||||
@@ -442,31 +444,40 @@ RSpec.describe User do
|
||||
|
||||
let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) }
|
||||
|
||||
before do
|
||||
allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub)
|
||||
user.reset_password!
|
||||
before { stub_redis }
|
||||
|
||||
it 'changes the password immediately and revokes related access' do
|
||||
expect { user.reset_password! }
|
||||
.to remove_activated_sessions
|
||||
.and remove_active_user_tokens
|
||||
.and remove_user_web_subscriptions
|
||||
|
||||
expect(user)
|
||||
.to_not be_external_or_valid_password(original_password)
|
||||
expect { session_activation.reload }
|
||||
.to raise_error(ActiveRecord::RecordNotFound)
|
||||
expect { web_push_subscription.reload }
|
||||
.to raise_error(ActiveRecord::RecordNotFound)
|
||||
expect(redis_pipeline_stub)
|
||||
.to have_received(:publish).with("timeline:access_token:#{access_token.id}", Oj.dump(event: :kill)).once
|
||||
end
|
||||
|
||||
it 'changes the password immediately' do
|
||||
expect(user.external_or_valid_password?('foobar12345')).to be false
|
||||
def remove_activated_sessions
|
||||
change(user.session_activations, :count).to(0)
|
||||
end
|
||||
|
||||
it 'deactivates all sessions' do
|
||||
expect(user.session_activations.count).to eq 0
|
||||
expect { session_activation.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
def remove_active_user_tokens
|
||||
change { Doorkeeper::AccessToken.active_for(user).count }.to(0)
|
||||
end
|
||||
|
||||
it 'revokes all access tokens' do
|
||||
expect(Doorkeeper::AccessToken.active_for(user).count).to eq 0
|
||||
def remove_user_web_subscriptions
|
||||
change { Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count }.to(0)
|
||||
end
|
||||
|
||||
it 'revokes streaming access for all access tokens' do
|
||||
expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", Oj.dump(event: :kill)).once
|
||||
end
|
||||
|
||||
it 'removes push subscriptions' do
|
||||
expect(Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count).to eq 0
|
||||
expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
def stub_redis
|
||||
allow(redis)
|
||||
.to receive(:pipelined)
|
||||
.and_yield(redis_pipeline_stub)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -46,21 +46,6 @@ RSpec.describe 'Accounts show response' do
|
||||
|
||||
describe 'GET to short username paths' do
|
||||
context 'with existing statuses' do
|
||||
let!(:status) { Fabricate(:status, account: account) }
|
||||
let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) }
|
||||
let!(:status_self_reply) { Fabricate(:status, account: account, thread: status) }
|
||||
let!(:status_media) { Fabricate(:status, account: account) }
|
||||
let!(:status_pinned) { Fabricate(:status, account: account) }
|
||||
let!(:status_private) { Fabricate(:status, account: account, visibility: :private) }
|
||||
let!(:status_direct) { Fabricate(:status, account: account, visibility: :direct) }
|
||||
let!(:status_reblog) { Fabricate(:status, account: account, reblog: Fabricate(:status)) }
|
||||
|
||||
before do
|
||||
status_media.media_attachments << Fabricate(:media_attachment, account: account, type: :image)
|
||||
account.pinned_statuses << status_pinned
|
||||
account.pinned_statuses << status_private
|
||||
end
|
||||
|
||||
context 'with HTML' do
|
||||
let(:format) { 'html' }
|
||||
|
||||
@@ -207,6 +192,21 @@ RSpec.describe 'Accounts show response' do
|
||||
context 'with RSS' do
|
||||
let(:format) { 'rss' }
|
||||
|
||||
let!(:status) { Fabricate(:status, account: account) }
|
||||
let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) }
|
||||
let!(:status_self_reply) { Fabricate(:status, account: account, thread: status) }
|
||||
let!(:status_media) { Fabricate(:status, account: account) }
|
||||
let!(:status_pinned) { Fabricate(:status, account: account) }
|
||||
let!(:status_private) { Fabricate(:status, account: account, visibility: :private) }
|
||||
let!(:status_direct) { Fabricate(:status, account: account, visibility: :direct) }
|
||||
let!(:status_reblog) { Fabricate(:status, account: account, reblog: Fabricate(:status)) }
|
||||
|
||||
before do
|
||||
status_media.media_attachments << Fabricate(:media_attachment, account: account, type: :image)
|
||||
account.pinned_statuses << status_pinned
|
||||
account.pinned_statuses << status_private
|
||||
end
|
||||
|
||||
context 'with a normal account in an RSS request' do
|
||||
before do
|
||||
get short_account_path(username: account.username, format: format)
|
||||
|
||||
@@ -20,19 +20,16 @@ RSpec.describe 'Canonical Email Blocks' do
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
end
|
||||
|
||||
context 'when there is no canonical email block' do
|
||||
it 'returns an empty list' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body).to be_empty
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body)
|
||||
.to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
@@ -43,7 +40,12 @@ RSpec.describe 'Canonical Email Blocks' do
|
||||
it 'returns the correct canonical email hashes' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body.pluck(:canonical_email_hash)).to match_array(expected_email_hashes)
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body.pluck(:canonical_email_hash))
|
||||
.to match_array(expected_email_hashes)
|
||||
end
|
||||
|
||||
context 'with limit param' do
|
||||
|
||||
@@ -20,18 +20,14 @@ RSpec.describe 'Domain Allows' do
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
end
|
||||
|
||||
context 'when there is no allowed domains' do
|
||||
it 'returns an empty body' do
|
||||
subject
|
||||
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body).to be_empty
|
||||
end
|
||||
end
|
||||
@@ -51,7 +47,12 @@ RSpec.describe 'Domain Allows' do
|
||||
it 'returns the correct allowed domains' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body).to match_array(expected_response)
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body)
|
||||
.to match_array(expected_response)
|
||||
end
|
||||
|
||||
context 'with limit param' do
|
||||
|
||||
@@ -20,19 +20,16 @@ RSpec.describe 'Domain Blocks' do
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
end
|
||||
|
||||
context 'when there are no domain blocks' do
|
||||
it 'returns an empty list' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body).to be_empty
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body)
|
||||
.to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
@@ -66,7 +63,12 @@ RSpec.describe 'Domain Blocks' do
|
||||
it 'returns the expected domain blocks' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body).to match_array(expected_responde)
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body)
|
||||
.to match_array(expected_responde)
|
||||
end
|
||||
|
||||
context 'with limit param' do
|
||||
|
||||
@@ -21,19 +21,16 @@ RSpec.describe 'Email Domain Blocks' do
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
end
|
||||
|
||||
context 'when there is no email domain block' do
|
||||
it 'returns an empty list' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body).to be_empty
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body)
|
||||
.to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,7 +41,12 @@ RSpec.describe 'Email Domain Blocks' do
|
||||
it 'return the correct blocked email domains' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body.pluck(:domain)).to match_array(blocked_email_domains)
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body.pluck(:domain))
|
||||
.to match_array(blocked_email_domains)
|
||||
end
|
||||
|
||||
context 'with limit param' do
|
||||
|
||||
@@ -20,19 +20,16 @@ RSpec.describe 'IP Blocks' do
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
end
|
||||
|
||||
context 'when there is no ip block' do
|
||||
it 'returns an empty body' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body).to be_empty
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body)
|
||||
.to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
@@ -60,7 +57,12 @@ RSpec.describe 'IP Blocks' do
|
||||
it 'returns the correct blocked ips' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body).to match_array(expected_response)
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body)
|
||||
.to match_array(expected_response)
|
||||
end
|
||||
|
||||
context 'with limit param' do
|
||||
|
||||
@@ -19,19 +19,16 @@ RSpec.describe 'Reports' do
|
||||
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
end
|
||||
|
||||
context 'when there are no reports' do
|
||||
it 'returns an empty list' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body).to be_empty
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body)
|
||||
.to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
@@ -66,7 +63,12 @@ RSpec.describe 'Reports' do
|
||||
it 'returns all unresolved reports' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body).to match_array(expected_response)
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body)
|
||||
.to match_array(expected_response)
|
||||
end
|
||||
|
||||
context 'with resolved param' do
|
||||
|
||||
@@ -20,19 +20,16 @@ RSpec.describe 'Tags' do
|
||||
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||
it_behaves_like 'forbidden for wrong role', ''
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
end
|
||||
|
||||
context 'when there are no tags' do
|
||||
it 'returns an empty list' do
|
||||
subject
|
||||
|
||||
expect(response.parsed_body).to be_empty
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body)
|
||||
.to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,6 +45,11 @@ RSpec.describe 'Tags' do
|
||||
|
||||
it 'returns the expected tags' do
|
||||
subject
|
||||
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
tags.each do |tag|
|
||||
expect(response.parsed_body.find { |item| item[:id] == tag.id.to_s && item[:name] == tag.name }).to_not be_nil
|
||||
end
|
||||
@@ -82,8 +84,11 @@ RSpec.describe 'Tags' do
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
|
||||
expect(response.parsed_body[:id].to_i).to eq(tag.id)
|
||||
expect(response.parsed_body[:name]).to eq(tag.name)
|
||||
expect(response.parsed_body)
|
||||
.to include(
|
||||
id: tag.id.to_s,
|
||||
name: tag.name
|
||||
)
|
||||
end
|
||||
|
||||
context 'when the requested tag does not exist' do
|
||||
@@ -116,8 +121,11 @@ RSpec.describe 'Tags' do
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
|
||||
expect(response.parsed_body[:id].to_i).to eq(tag.id)
|
||||
expect(response.parsed_body[:name]).to eq(tag.name.upcase)
|
||||
expect(response.parsed_body)
|
||||
.to include(
|
||||
id: tag.id.to_s,
|
||||
name: tag.name.upcase
|
||||
)
|
||||
end
|
||||
|
||||
context 'when the updated display name is invalid' do
|
||||
|
||||
@@ -41,8 +41,9 @@ RSpec.describe 'Credentials' do
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
|
||||
expect(response.parsed_body[:client_id]).to_not be_present
|
||||
expect(response.parsed_body[:client_secret]).to_not be_present
|
||||
expect(response.parsed_body)
|
||||
.to not_include(client_id: be_present)
|
||||
.and not_include(client_secret: be_present)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -36,7 +36,10 @@ RSpec.describe 'API V2 Admin Accounts' do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(body_json_ids).to eq([admin_account.id])
|
||||
expect(response.parsed_body)
|
||||
.to contain_exactly(
|
||||
hash_including(id: admin_account.id.to_s)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,8 +50,11 @@ RSpec.describe 'API V2 Admin Accounts' do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(body_json_ids).to include(remote_account.id)
|
||||
expect(body_json_ids).to_not include(other_remote_account.id)
|
||||
expect(response.parsed_body)
|
||||
.to contain_exactly(
|
||||
hash_including(id: remote_account.id.to_s)
|
||||
)
|
||||
.and not_include(hash_including(id: other_remote_account.id.to_s))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -59,7 +65,11 @@ RSpec.describe 'API V2 Admin Accounts' do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(body_json_ids).to include(suspended_remote.id, suspended_account.id)
|
||||
expect(response.parsed_body)
|
||||
.to contain_exactly(
|
||||
hash_including(id: suspended_remote.id.to_s),
|
||||
hash_including(id: suspended_account.id.to_s)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -70,7 +80,10 @@ RSpec.describe 'API V2 Admin Accounts' do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(body_json_ids).to include(disabled_account.id)
|
||||
expect(response.parsed_body)
|
||||
.to contain_exactly(
|
||||
hash_including(id: disabled_account.id.to_s)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -81,14 +94,13 @@ RSpec.describe 'API V2 Admin Accounts' do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(body_json_ids).to include(pending_account.id)
|
||||
expect(response.parsed_body)
|
||||
.to contain_exactly(
|
||||
hash_including(id: pending_account.id.to_s)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def body_json_ids
|
||||
response.parsed_body.map { |a| a[:id].to_i }
|
||||
end
|
||||
|
||||
context 'with limit param' do
|
||||
let(:params) { { limit: 1 } }
|
||||
|
||||
|
||||
44
spec/requests/settings/applications_spec.rb
Normal file
44
spec/requests/settings/applications_spec.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Settings / Exports' do
|
||||
let(:user) { Fabricate :user }
|
||||
|
||||
before { sign_in user }
|
||||
|
||||
describe 'GET /settings/application/:id' do
|
||||
context 'when user does not own application' do
|
||||
let(:application) { Fabricate :application }
|
||||
|
||||
it 'returns http missing' do
|
||||
get settings_application_path(application)
|
||||
|
||||
expect(response)
|
||||
.to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /settings/applications' do
|
||||
subject { post '/settings/applications', params: params }
|
||||
|
||||
let(:params) do
|
||||
{
|
||||
doorkeeper_application: {
|
||||
name: 'My New App',
|
||||
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
|
||||
website: 'http://google.com',
|
||||
scopes: 'read write follow',
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
it 'supports passing scope values as string' do
|
||||
expect { subject }
|
||||
.to change(Doorkeeper::Application, :count).by(1)
|
||||
expect(response)
|
||||
.to redirect_to(settings_applications_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -168,10 +168,12 @@ RSpec.describe 'The /.well-known/webfinger endpoint' do
|
||||
it 'returns avatar in response' do
|
||||
perform_request!
|
||||
|
||||
avatar_link = get_avatar_link(response.parsed_body)
|
||||
expect(avatar_link).to_not be_nil
|
||||
expect(avatar_link[:type]).to eq alice.avatar.content_type
|
||||
expect(avatar_link[:href]).to eq Addressable::URI.new(host: Rails.configuration.x.local_domain, path: alice.avatar.to_s, scheme: 'https').to_s
|
||||
expect(response_avatar_link)
|
||||
.to be_present
|
||||
.and include(
|
||||
type: eq(alice.avatar.content_type),
|
||||
href: eq(Addressable::URI.new(host: Rails.configuration.x.local_domain, path: alice.avatar.to_s, scheme: 'https').to_s)
|
||||
)
|
||||
end
|
||||
|
||||
context 'with limited federation mode' do
|
||||
@@ -182,8 +184,8 @@ RSpec.describe 'The /.well-known/webfinger endpoint' do
|
||||
it 'does not return avatar in response' do
|
||||
perform_request!
|
||||
|
||||
avatar_link = get_avatar_link(response.parsed_body)
|
||||
expect(avatar_link).to be_nil
|
||||
expect(response_avatar_link)
|
||||
.to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -197,8 +199,8 @@ RSpec.describe 'The /.well-known/webfinger endpoint' do
|
||||
it 'does not return avatar in response' do
|
||||
perform_request!
|
||||
|
||||
avatar_link = get_avatar_link(response.parsed_body)
|
||||
expect(avatar_link).to be_nil
|
||||
expect(response_avatar_link)
|
||||
.to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -212,8 +214,8 @@ RSpec.describe 'The /.well-known/webfinger endpoint' do
|
||||
end
|
||||
|
||||
it 'does not return avatar in response' do
|
||||
avatar_link = get_avatar_link(response.parsed_body)
|
||||
expect(avatar_link).to be_nil
|
||||
expect(response_avatar_link)
|
||||
.to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -247,7 +249,9 @@ RSpec.describe 'The /.well-known/webfinger endpoint' do
|
||||
|
||||
private
|
||||
|
||||
def get_avatar_link(json)
|
||||
json[:links].find { |link| link[:rel] == 'http://webfinger.net/rel/avatar' }
|
||||
def response_avatar_link
|
||||
response
|
||||
.parsed_body[:links]
|
||||
.find { |link| link[:rel] == 'http://webfinger.net/rel/avatar' }
|
||||
end
|
||||
end
|
||||
|
||||
144
spec/system/settings/applications_spec.rb
Normal file
144
spec/system/settings/applications_spec.rb
Normal file
@@ -0,0 +1,144 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Settings applications page' do
|
||||
let!(:application) { Fabricate :application, owner: user }
|
||||
let(:user) { Fabricate :user }
|
||||
|
||||
before { sign_in user }
|
||||
|
||||
describe 'Viewing the list of applications' do
|
||||
it 'sees the applications' do
|
||||
visit settings_applications_path
|
||||
|
||||
expect(page)
|
||||
.to have_content(application.name)
|
||||
.and have_private_cache_control
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Viewing a single application' do
|
||||
it 'shows a page with application details' do
|
||||
visit settings_application_path(application)
|
||||
|
||||
expect(page)
|
||||
.to have_content(application.name)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Creating a new application' do
|
||||
it 'accepts form input to make an application' do
|
||||
visit new_settings_application_path
|
||||
|
||||
fill_in_form
|
||||
|
||||
expect { submit_form }
|
||||
.to change(Doorkeeper::Application, :count).by(1)
|
||||
expect(page)
|
||||
.to have_content(I18n.t('doorkeeper.applications.index.title'))
|
||||
.and have_content('My new app')
|
||||
end
|
||||
|
||||
it 'does not save with invalid form values' do
|
||||
visit new_settings_application_path
|
||||
|
||||
expect { submit_form }
|
||||
.to not_change(Doorkeeper::Application, :count)
|
||||
expect(page)
|
||||
.to have_content("can't be blank")
|
||||
end
|
||||
|
||||
def fill_in_form
|
||||
fill_in form_app_name_label,
|
||||
with: 'My new app'
|
||||
fill_in I18n.t('activerecord.attributes.doorkeeper/application.website'),
|
||||
with: 'http://google.com'
|
||||
fill_in I18n.t('activerecord.attributes.doorkeeper/application.redirect_uri'),
|
||||
with: 'urn:ietf:wg:oauth:2.0:oob'
|
||||
|
||||
check 'read', id: :doorkeeper_application_scopes_read
|
||||
check 'write', id: :doorkeeper_application_scopes_write
|
||||
check 'follow', id: :doorkeeper_application_scopes_follow
|
||||
end
|
||||
|
||||
def submit_form
|
||||
click_on I18n.t('doorkeeper.applications.buttons.submit')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Updating an application' do
|
||||
it 'successfully updates with valid values' do
|
||||
visit settings_application_path(application)
|
||||
|
||||
fill_in form_app_name_label,
|
||||
with: 'My new app name with a new value'
|
||||
submit_form
|
||||
|
||||
expect(page)
|
||||
.to have_content('My new app name with a new value')
|
||||
end
|
||||
|
||||
it 'does not update with wrong values' do
|
||||
visit settings_application_path(application)
|
||||
|
||||
fill_in form_app_name_label,
|
||||
with: ''
|
||||
submit_form
|
||||
|
||||
expect(page)
|
||||
.to have_content("can't be blank")
|
||||
end
|
||||
|
||||
def submit_form
|
||||
click_on I18n.t('generic.save_changes')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Destroying an application' do
|
||||
let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) }
|
||||
let!(:access_token) { Fabricate(:accessible_access_token, application: application) }
|
||||
|
||||
before { stub_redis_pipeline }
|
||||
|
||||
it 'destroys the record and tells the broader universe about that' do
|
||||
visit settings_applications_path
|
||||
|
||||
expect { destroy_application }
|
||||
.to change(Doorkeeper::Application, :count).by(-1)
|
||||
expect(page)
|
||||
.to have_no_content(application.name)
|
||||
expect(redis_pipeline_stub)
|
||||
.to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}')
|
||||
end
|
||||
|
||||
def destroy_application
|
||||
click_on I18n.t('doorkeeper.applications.index.delete')
|
||||
end
|
||||
|
||||
def stub_redis_pipeline
|
||||
allow(redis)
|
||||
.to receive(:pipelined)
|
||||
.and_yield(redis_pipeline_stub)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Regenerating an app token' do
|
||||
it 'updates the app token' do
|
||||
visit settings_application_path(application)
|
||||
|
||||
expect { regenerate_token }
|
||||
.to(change { user.token_for_app(application) })
|
||||
expect(page)
|
||||
.to have_content(I18n.t('applications.token_regenerated'))
|
||||
end
|
||||
|
||||
def regenerate_token
|
||||
click_on I18n.t('applications.regenerate_token')
|
||||
end
|
||||
end
|
||||
|
||||
def form_app_name_label
|
||||
I18n.t('activerecord.attributes.doorkeeper/application.name')
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user