Gab Social. All are welcome.
This commit is contained in:
51
spec/controllers/about_controller_spec.rb
Normal file
51
spec/controllers/about_controller_spec.rb
Normal file
@@ -0,0 +1,51 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe AboutController, type: :controller do
|
||||
render_views
|
||||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'assigns @instance_presenter' do
|
||||
expect(assigns(:instance_presenter)).to be_kind_of InstancePresenter
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #more' do
|
||||
before do
|
||||
get :more
|
||||
end
|
||||
|
||||
it 'assigns @instance_presenter' do
|
||||
expect(assigns(:instance_presenter)).to be_kind_of InstancePresenter
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #terms' do
|
||||
before do
|
||||
get :terms
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'helper_method :new_user' do
|
||||
it 'returns a new User' do
|
||||
user = @controller.view_context.new_user
|
||||
expect(user).to be_kind_of User
|
||||
expect(user.account).to be_kind_of Account
|
||||
end
|
||||
end
|
||||
end
|
||||
32
spec/controllers/account_follow_controller_spec.rb
Normal file
32
spec/controllers/account_follow_controller_spec.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe AccountFollowController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:alice) { Fabricate(:account, username: 'alice') }
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:service) { double }
|
||||
|
||||
subject { post :create, params: { account_username: alice.username } }
|
||||
|
||||
before do
|
||||
allow(FollowService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call)
|
||||
end
|
||||
|
||||
it 'does not create for user who is not signed in' do
|
||||
subject
|
||||
expect(FollowService).not_to receive(:new)
|
||||
end
|
||||
|
||||
it 'redirects to account path' do
|
||||
sign_in(user)
|
||||
subject
|
||||
|
||||
expect(service).to have_received(:call).with(user.account, 'alice')
|
||||
expect(response).to redirect_to(account_path(alice))
|
||||
end
|
||||
end
|
||||
end
|
||||
32
spec/controllers/account_unfollow_controller_spec.rb
Normal file
32
spec/controllers/account_unfollow_controller_spec.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe AccountUnfollowController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:alice) { Fabricate(:account, username: 'alice') }
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:service) { double }
|
||||
|
||||
subject { post :create, params: { account_username: alice.username } }
|
||||
|
||||
before do
|
||||
allow(UnfollowService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call)
|
||||
end
|
||||
|
||||
it 'does not create for user who is not signed in' do
|
||||
subject
|
||||
expect(UnfollowService).not_to receive(:new)
|
||||
end
|
||||
|
||||
it 'redirects to account path' do
|
||||
sign_in(user)
|
||||
subject
|
||||
|
||||
expect(service).to have_received(:call).with(user.account, alice)
|
||||
expect(response).to redirect_to(account_path(alice))
|
||||
end
|
||||
end
|
||||
end
|
||||
143
spec/controllers/accounts_controller_spec.rb
Normal file
143
spec/controllers/accounts_controller_spec.rb
Normal file
@@ -0,0 +1,143 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe AccountsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:alice) { Fabricate(:account, username: 'alice', user: Fabricate(:user)) }
|
||||
let(:eve) { Fabricate(:user) }
|
||||
|
||||
describe 'GET #show' do
|
||||
let!(:status1) { Status.create!(account: alice, text: 'Hello world') }
|
||||
let!(:status2) { Status.create!(account: alice, text: 'Boop', thread: status1) }
|
||||
let!(:status3) { Status.create!(account: alice, text: 'Picture!') }
|
||||
let!(:status4) { Status.create!(account: alice, text: 'Mentioning @alice') }
|
||||
let!(:status5) { Status.create!(account: alice, text: 'Kitsune') }
|
||||
let!(:status6) { Status.create!(account: alice, text: 'Neko') }
|
||||
let!(:status7) { Status.create!(account: alice, text: 'Tanuki') }
|
||||
|
||||
let!(:status_pin1) { StatusPin.create!(account: alice, status: status5, created_at: 5.days.ago) }
|
||||
let!(:status_pin2) { StatusPin.create!(account: alice, status: status6, created_at: 2.years.ago) }
|
||||
let!(:status_pin3) { StatusPin.create!(account: alice, status: status7, created_at: 10.minutes.ago) }
|
||||
|
||||
before do
|
||||
alice.block!(eve.account)
|
||||
status3.media_attachments.create!(account: alice, file: fixture_file_upload('files/attachment.jpg', 'image/jpeg'))
|
||||
end
|
||||
|
||||
shared_examples 'responses' do
|
||||
before do
|
||||
sign_in(current_user) if defined? current_user
|
||||
get :show, params: {
|
||||
username: alice.username,
|
||||
max_id: (max_id if defined? max_id),
|
||||
since_id: (since_id if defined? since_id),
|
||||
current_user: (current_user if defined? current_user),
|
||||
}, format: format
|
||||
end
|
||||
|
||||
it 'assigns @account' do
|
||||
expect(assigns(:account)).to eq alice
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns correct format' do
|
||||
expect(response.content_type).to eq content_type
|
||||
end
|
||||
end
|
||||
|
||||
context 'atom' do
|
||||
let(:format) { 'atom' }
|
||||
let(:content_type) { 'application/atom+xml' }
|
||||
|
||||
shared_examples 'responsed streams' do
|
||||
it 'assigns @entries' do
|
||||
entries = assigns(:entries).to_a
|
||||
expect(entries.size).to eq expected_statuses.size
|
||||
entries.each.zip(expected_statuses.each) do |entry, expected_status|
|
||||
expect(entry.status).to eq expected_status
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
include_examples 'responses'
|
||||
|
||||
context 'without max_id nor since_id' do
|
||||
let(:expected_statuses) { [status7, status6, status5, status4, status3, status2, status1] }
|
||||
|
||||
include_examples 'responsed streams'
|
||||
end
|
||||
|
||||
context 'with max_id and since_id' do
|
||||
let(:max_id) { status4.stream_entry.id }
|
||||
let(:since_id) { status1.stream_entry.id }
|
||||
let(:expected_statuses) { [status3, status2] }
|
||||
|
||||
include_examples 'responsed streams'
|
||||
end
|
||||
end
|
||||
|
||||
context 'activitystreams2' do
|
||||
let(:format) { 'json' }
|
||||
let(:content_type) { 'application/activity+json' }
|
||||
|
||||
include_examples 'responses'
|
||||
end
|
||||
|
||||
context 'html' do
|
||||
let(:format) { nil }
|
||||
let(:content_type) { 'text/html' }
|
||||
|
||||
shared_examples 'responsed statuses' do
|
||||
it 'assigns @pinned_statuses' do
|
||||
pinned_statuses = assigns(:pinned_statuses).to_a
|
||||
expect(pinned_statuses.size).to eq expected_pinned_statuses.size
|
||||
pinned_statuses.each.zip(expected_pinned_statuses.each) do |pinned_status, expected_pinned_status|
|
||||
expect(pinned_status).to eq expected_pinned_status
|
||||
end
|
||||
end
|
||||
|
||||
it 'assigns @statuses' do
|
||||
statuses = assigns(:statuses).to_a
|
||||
expect(statuses.size).to eq expected_statuses.size
|
||||
statuses.each.zip(expected_statuses.each) do |status, expected_status|
|
||||
expect(status).to eq expected_status
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
include_examples 'responses'
|
||||
|
||||
context 'with anonymous visitor' do
|
||||
context 'without since_id nor max_id' do
|
||||
let(:expected_statuses) { [status7, status6, status5, status4, status3, status2, status1] }
|
||||
let(:expected_pinned_statuses) { [status7, status5, status6] }
|
||||
|
||||
include_examples 'responsed statuses'
|
||||
end
|
||||
|
||||
context 'with since_id nor max_id' do
|
||||
let(:max_id) { status4.id }
|
||||
let(:since_id) { status1.id }
|
||||
let(:expected_statuses) { [status3, status2] }
|
||||
let(:expected_pinned_statuses) { [] }
|
||||
|
||||
include_examples 'responsed statuses'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with blocked visitor' do
|
||||
let(:current_user) { eve }
|
||||
|
||||
context 'without since_id nor max_id' do
|
||||
let(:expected_statuses) { [] }
|
||||
let(:expected_pinned_statuses) { [] }
|
||||
|
||||
include_examples 'responsed statuses'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
25
spec/controllers/activitypub/collections_controller_spec.rb
Normal file
25
spec/controllers/activitypub/collections_controller_spec.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::CollectionsController, type: :controller do
|
||||
describe 'POST #show' do
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
context 'id is "featured"' do
|
||||
it 'returns 200 with "application/activity+json"' do
|
||||
post :show, params: { id: 'featured', account_username: account.username }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type).to eq 'application/activity+json'
|
||||
end
|
||||
end
|
||||
|
||||
context 'id is not "featured"' do
|
||||
it 'returns 404' do
|
||||
post :show, params: { id: 'hoge', account_username: account.username }
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
29
spec/controllers/activitypub/inboxes_controller_spec.rb
Normal file
29
spec/controllers/activitypub/inboxes_controller_spec.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::InboxesController, type: :controller do
|
||||
describe 'POST #create' do
|
||||
context 'if signed_request_account' do
|
||||
it 'returns 202' do
|
||||
allow(controller).to receive(:signed_request_account) do
|
||||
Fabricate(:account)
|
||||
end
|
||||
|
||||
post :create, body: '{}'
|
||||
expect(response).to have_http_status(202)
|
||||
end
|
||||
end
|
||||
|
||||
context 'not signed_request_account' do
|
||||
it 'returns 401' do
|
||||
allow(controller).to receive(:signed_request_account) do
|
||||
false
|
||||
end
|
||||
|
||||
post :create, body: '{}'
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
23
spec/controllers/activitypub/outboxes_controller_spec.rb
Normal file
23
spec/controllers/activitypub/outboxes_controller_spec.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::OutboxesController, type: :controller do
|
||||
let!(:account) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
Fabricate(:status, account: account)
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
get :show, params: { account_username: account.username }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns application/activity+json' do
|
||||
expect(response.content_type).to eq 'application/activity+json'
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,46 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::AccountModerationNotesController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, admin: true) }
|
||||
let(:target_account) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
subject { post :create, params: params }
|
||||
|
||||
context 'when parameters are valid' do
|
||||
let(:params) { { account_moderation_note: { target_account_id: target_account.id, content: 'test content' } } }
|
||||
|
||||
it 'successfully creates a note' do
|
||||
expect { subject }.to change { AccountModerationNote.count }.by(1)
|
||||
expect(subject).to redirect_to admin_account_path(target_account.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parameters are invalid' do
|
||||
let(:params) { { account_moderation_note: { target_account_id: target_account.id, content: '' } } }
|
||||
|
||||
it 'falls to create a note' do
|
||||
expect { subject }.not_to change { AccountModerationNote.count }
|
||||
expect(subject).to render_template 'admin/accounts/show'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
subject { delete :destroy, params: { id: note.id } }
|
||||
|
||||
let!(:note) { Fabricate(:account_moderation_note, account: account, target_account: target_account) }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
it 'destroys note' do
|
||||
expect { subject }.to change { AccountModerationNote.count }.by(-1)
|
||||
expect(subject).to redirect_to admin_account_path(target_account.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
239
spec/controllers/admin/accounts_controller_spec.rb
Normal file
239
spec/controllers/admin/accounts_controller_spec.rb
Normal file
@@ -0,0 +1,239 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::AccountsController, type: :controller do
|
||||
render_views
|
||||
|
||||
before { sign_in current_user, scope: :user }
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:current_user) { Fabricate(:user, admin: true) }
|
||||
|
||||
around do |example|
|
||||
default_per_page = Account.default_per_page
|
||||
Account.paginates_per 1
|
||||
example.run
|
||||
Account.paginates_per default_per_page
|
||||
end
|
||||
|
||||
it 'filters with parameters' do
|
||||
new = AccountFilter.method(:new)
|
||||
|
||||
expect(AccountFilter).to receive(:new) do |params|
|
||||
h = params.to_h
|
||||
|
||||
expect(h[:local]).to eq '1'
|
||||
expect(h[:remote]).to eq '1'
|
||||
expect(h[:by_domain]).to eq 'domain'
|
||||
expect(h[:active]).to eq '1'
|
||||
expect(h[:silenced]).to eq '1'
|
||||
expect(h[:suspended]).to eq '1'
|
||||
expect(h[:username]).to eq 'username'
|
||||
expect(h[:display_name]).to eq 'display name'
|
||||
expect(h[:email]).to eq 'local-part@domain'
|
||||
expect(h[:ip]).to eq '0.0.0.42'
|
||||
|
||||
new.call({})
|
||||
end
|
||||
|
||||
get :index, params: {
|
||||
local: '1',
|
||||
remote: '1',
|
||||
by_domain: 'domain',
|
||||
active: '1',
|
||||
silenced: '1',
|
||||
suspended: '1',
|
||||
username: 'username',
|
||||
display_name: 'display name',
|
||||
email: 'local-part@domain',
|
||||
ip: '0.0.0.42'
|
||||
}
|
||||
end
|
||||
|
||||
it 'paginates accounts' do
|
||||
Fabricate(:account)
|
||||
|
||||
get :index, params: { page: 2 }
|
||||
|
||||
accounts = assigns(:accounts)
|
||||
expect(accounts.count).to eq 1
|
||||
expect(accounts.klass).to be Account
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:current_user) { Fabricate(:user, admin: true) }
|
||||
let(:account) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: account.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #subscribe' do
|
||||
subject { post :subscribe, params: { id: account.id } }
|
||||
|
||||
let(:current_user) { Fabricate(:user, admin: admin) }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
context 'when user is admin' do
|
||||
let(:admin) { true }
|
||||
|
||||
it { is_expected.to redirect_to admin_account_path(account.id) }
|
||||
end
|
||||
|
||||
context 'when user is not admin' do
|
||||
let(:admin) { false }
|
||||
|
||||
it { is_expected.to have_http_status :forbidden }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #unsubscribe' do
|
||||
subject { post :unsubscribe, params: { id: account.id } }
|
||||
|
||||
let(:current_user) { Fabricate(:user, admin: admin) }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
context 'when user is admin' do
|
||||
let(:admin) { true }
|
||||
|
||||
it { is_expected.to redirect_to admin_account_path(account.id) }
|
||||
end
|
||||
|
||||
context 'when user is not admin' do
|
||||
let(:admin) { false }
|
||||
|
||||
it { is_expected.to have_http_status :forbidden }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #memorialize' do
|
||||
subject { post :memorialize, params: { id: account.id } }
|
||||
|
||||
let(:current_user) { Fabricate(:user, admin: current_user_admin) }
|
||||
let(:account) { Fabricate(:account, user: user) }
|
||||
let(:user) { Fabricate(:user, admin: target_user_admin) }
|
||||
|
||||
context 'when user is admin' do
|
||||
let(:current_user_admin) { true }
|
||||
|
||||
context 'when target user is admin' do
|
||||
let(:target_user_admin) { true }
|
||||
|
||||
it 'fails to memorialize account' do
|
||||
is_expected.to have_http_status :forbidden
|
||||
expect(account.reload).not_to be_memorial
|
||||
end
|
||||
end
|
||||
|
||||
context 'when target user is not admin' do
|
||||
let(:target_user_admin) { false }
|
||||
|
||||
it 'succeeds in memorializing account' do
|
||||
is_expected.to redirect_to admin_account_path(account.id)
|
||||
expect(account.reload).to be_memorial
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is not admin' do
|
||||
let(:current_user_admin) { false }
|
||||
|
||||
context 'when target user is admin' do
|
||||
let(:target_user_admin) { true }
|
||||
|
||||
it 'fails to memorialize account' do
|
||||
is_expected.to have_http_status :forbidden
|
||||
expect(account.reload).not_to be_memorial
|
||||
end
|
||||
end
|
||||
|
||||
context 'when target user is not admin' do
|
||||
let(:target_user_admin) { false }
|
||||
|
||||
it 'fails to memorialize account' do
|
||||
is_expected.to have_http_status :forbidden
|
||||
expect(account.reload).not_to be_memorial
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #enable' do
|
||||
subject { post :enable, params: { id: account.id } }
|
||||
|
||||
let(:current_user) { Fabricate(:user, admin: admin) }
|
||||
let(:account) { Fabricate(:account, user: user) }
|
||||
let(:user) { Fabricate(:user, disabled: true) }
|
||||
|
||||
context 'when user is admin' do
|
||||
let(:admin) { true }
|
||||
|
||||
it 'succeeds in enabling account' do
|
||||
is_expected.to redirect_to admin_account_path(account.id)
|
||||
expect(user.reload).not_to be_disabled
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is not admin' do
|
||||
let(:admin) { false }
|
||||
|
||||
it 'fails to enable account' do
|
||||
is_expected.to have_http_status :forbidden
|
||||
expect(user.reload).to be_disabled
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #redownload' do
|
||||
subject { post :redownload, params: { id: account.id } }
|
||||
|
||||
let(:current_user) { Fabricate(:user, admin: admin) }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
context 'when user is admin' do
|
||||
let(:admin) { true }
|
||||
|
||||
it 'succeeds in redownloadin' do
|
||||
is_expected.to redirect_to admin_account_path(account.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is not admin' do
|
||||
let(:admin) { false }
|
||||
|
||||
it 'fails to redownload' do
|
||||
is_expected.to have_http_status :forbidden
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #remove_avatar' do
|
||||
subject { post :remove_avatar, params: { id: account.id } }
|
||||
|
||||
let(:current_user) { Fabricate(:user, admin: admin) }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
context 'when user is admin' do
|
||||
let(:admin) { true }
|
||||
|
||||
it 'succeeds in removing avatar' do
|
||||
is_expected.to redirect_to admin_account_path(account.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is not admin' do
|
||||
let(:admin) { false }
|
||||
|
||||
it 'fails to remove avatar' do
|
||||
is_expected.to have_http_status :forbidden
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
14
spec/controllers/admin/action_logs_controller_spec.rb
Normal file
14
spec/controllers/admin/action_logs_controller_spec.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::ActionLogsController, type: :controller do
|
||||
describe 'GET #index' do
|
||||
it 'returns 200' do
|
||||
sign_in Fabricate(:user, admin: true)
|
||||
get :index, params: { page: 1 }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
33
spec/controllers/admin/base_controller_spec.rb
Normal file
33
spec/controllers/admin/base_controller_spec.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::BaseController, type: :controller do
|
||||
controller do
|
||||
def success
|
||||
render 'admin/reports/show'
|
||||
end
|
||||
end
|
||||
|
||||
it 'requires administrator or moderator' do
|
||||
routes.draw { get 'success' => 'admin/base#success' }
|
||||
sign_in(Fabricate(:user, admin: false, moderator: false))
|
||||
get :success
|
||||
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
end
|
||||
|
||||
it 'renders admin layout as a moderator' do
|
||||
routes.draw { get 'success' => 'admin/base#success' }
|
||||
sign_in(Fabricate(:user, moderator: true))
|
||||
get :success
|
||||
expect(response).to render_template layout: 'admin'
|
||||
end
|
||||
|
||||
it 'renders admin layout as an admin' do
|
||||
routes.draw { get 'success' => 'admin/base#success' }
|
||||
sign_in(Fabricate(:user, admin: true))
|
||||
get :success
|
||||
expect(response).to render_template layout: 'admin'
|
||||
end
|
||||
end
|
||||
47
spec/controllers/admin/change_email_controller_spec.rb
Normal file
47
spec/controllers/admin/change_email_controller_spec.rb
Normal file
@@ -0,0 +1,47 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::ChangeEmailsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:admin) { Fabricate(:user, admin: true) }
|
||||
|
||||
before do
|
||||
sign_in admin
|
||||
end
|
||||
|
||||
describe "GET #show" do
|
||||
it "returns http success" do
|
||||
account = Fabricate(:account)
|
||||
user = Fabricate(:user, account: account)
|
||||
|
||||
get :show, params: { account_id: account.id }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET #update" do
|
||||
before do
|
||||
allow(UserMailer).to receive(:confirmation_instructions).and_return(double('email', deliver_later: nil))
|
||||
end
|
||||
|
||||
it "returns http success" do
|
||||
account = Fabricate(:account)
|
||||
user = Fabricate(:user, account: account)
|
||||
|
||||
previous_email = user.email
|
||||
|
||||
post :update, params: { account_id: account.id, user: { unconfirmed_email: 'test@example.com' } }
|
||||
|
||||
user.reload
|
||||
|
||||
expect(user.email).to eq previous_email
|
||||
expect(user.unconfirmed_email).to eq 'test@example.com'
|
||||
expect(user.confirmation_token).not_to be_nil
|
||||
|
||||
expect(UserMailer).to have_received(:confirmation_instructions).with(user, user.confirmation_token, { to: 'test@example.com' })
|
||||
|
||||
expect(response).to redirect_to(admin_account_path(account.id))
|
||||
end
|
||||
end
|
||||
end
|
||||
64
spec/controllers/admin/confirmations_controller_spec.rb
Normal file
64
spec/controllers/admin/confirmations_controller_spec.rb
Normal file
@@ -0,0 +1,64 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::ConfirmationsController, type: :controller do
|
||||
render_views
|
||||
|
||||
before do
|
||||
sign_in Fabricate(:user, admin: true), scope: :user
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
it 'confirms the user' do
|
||||
account = Fabricate(:account)
|
||||
user = Fabricate(:user, confirmed_at: false, account: account)
|
||||
post :create, params: { account_id: account.id }
|
||||
|
||||
expect(response).to redirect_to(admin_accounts_path)
|
||||
expect(user.reload).to be_confirmed
|
||||
end
|
||||
|
||||
it 'raises an error when there is no account' do
|
||||
post :create, params: { account_id: 'fake' }
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
|
||||
it 'raises an error when there is no user' do
|
||||
account = Fabricate(:account, user: nil)
|
||||
post :create, params: { account_id: account.id }
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #resernd' do
|
||||
subject { post :resend, params: { account_id: account.id } }
|
||||
|
||||
let(:account) { Fabricate(:account) }
|
||||
let!(:user) { Fabricate(:user, confirmed_at: confirmed_at, account: account) }
|
||||
|
||||
before do
|
||||
allow(UserMailer).to receive(:confirmation_instructions) { double(:email, deliver_later: nil) }
|
||||
end
|
||||
|
||||
context 'when email is not confirmed' do
|
||||
let(:confirmed_at) { nil }
|
||||
|
||||
it 'resends confirmation mail' do
|
||||
expect(subject).to redirect_to admin_accounts_path
|
||||
expect(flash[:notice]).to eq I18n.t('admin.accounts.resend_confirmation.success')
|
||||
expect(UserMailer).to have_received(:confirmation_instructions).once
|
||||
end
|
||||
end
|
||||
|
||||
context 'when email is confirmed' do
|
||||
let(:confirmed_at) { Time.zone.now }
|
||||
|
||||
it 'does not resend confirmation mail' do
|
||||
expect(subject).to redirect_to admin_accounts_path
|
||||
expect(flash[:error]).to eq I18n.t('admin.accounts.resend_confirmation.already_confirmed')
|
||||
expect(UserMailer).not_to have_received(:confirmation_instructions)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
115
spec/controllers/admin/custom_emojis_controller_spec.rb
Normal file
115
spec/controllers/admin/custom_emojis_controller_spec.rb
Normal file
@@ -0,0 +1,115 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::CustomEmojisController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, admin: true) }
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
subject { get :index }
|
||||
|
||||
before do
|
||||
Fabricate(:custom_emoji)
|
||||
end
|
||||
|
||||
it 'renders index page' do
|
||||
expect(subject).to have_http_status 200
|
||||
expect(subject).to render_template :index
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #new' do
|
||||
subject { get :new }
|
||||
|
||||
it 'renders new page' do
|
||||
expect(subject).to have_http_status 200
|
||||
expect(subject).to render_template :new
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
subject { post :create, params: { custom_emoji: params } }
|
||||
|
||||
let(:image) { fixture_file_upload(Rails.root.join('spec', 'fixtures', 'files', 'emojo.png'), 'image/png') }
|
||||
|
||||
context 'when parameter is valid' do
|
||||
let(:params) { { shortcode: 'test', image: image } }
|
||||
|
||||
it 'creates custom emoji' do
|
||||
expect { subject }.to change { CustomEmoji.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parameter is invalid' do
|
||||
let(:params) { { shortcode: 't', image: image } }
|
||||
|
||||
it 'renders new' do
|
||||
expect(subject).to render_template :new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'test') }
|
||||
let(:image) { fixture_file_upload(Rails.root.join('spec', 'fixtures', 'files', 'emojo.png'), 'image/png') }
|
||||
|
||||
before do
|
||||
put :update, params: { id: custom_emoji.id, custom_emoji: params }
|
||||
end
|
||||
|
||||
context 'when parameter is valid' do
|
||||
let(:params) { { shortcode: 'updated', image: image } }
|
||||
|
||||
it 'succeeds in updating custom emoji' do
|
||||
expect(flash[:notice]).to eq I18n.t('admin.custom_emojis.updated_msg')
|
||||
expect(custom_emoji.reload).to have_attributes(shortcode: 'updated')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parameter is invalid' do
|
||||
let(:params) { { shortcode: 'u', image: image } }
|
||||
|
||||
it 'fails to update custom emoji' do
|
||||
expect(flash[:alert]).to eq I18n.t('admin.custom_emojis.update_failed_msg')
|
||||
expect(custom_emoji.reload).to have_attributes(shortcode: 'test')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #copy' do
|
||||
subject { post :copy, params: { id: custom_emoji.id } }
|
||||
|
||||
let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'test') }
|
||||
|
||||
it 'copies custom emoji' do
|
||||
expect { subject }.to change { CustomEmoji.where(shortcode: 'test').count }.by(1)
|
||||
expect(flash[:notice]).to eq I18n.t('admin.custom_emojis.copied_msg')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #enable' do
|
||||
let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'test', disabled: true) }
|
||||
|
||||
before { post :enable, params: { id: custom_emoji.id } }
|
||||
|
||||
it 'enables custom emoji' do
|
||||
expect(response).to redirect_to admin_custom_emojis_path
|
||||
expect(custom_emoji.reload).to have_attributes(disabled: false)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #disable' do
|
||||
let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'test', disabled: false) }
|
||||
|
||||
before { post :disable, params: { id: custom_emoji.id } }
|
||||
|
||||
it 'enables custom emoji' do
|
||||
expect(response).to redirect_to admin_custom_emojis_path
|
||||
expect(custom_emoji.reload).to have_attributes(disabled: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
14
spec/controllers/admin/dashboard_controller_spec.rb
Normal file
14
spec/controllers/admin/dashboard_controller_spec.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::DashboardController, type: :controller do
|
||||
describe 'GET #index' do
|
||||
it 'returns 200' do
|
||||
sign_in Fabricate(:user, admin: true)
|
||||
get :index
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
73
spec/controllers/admin/domain_blocks_controller_spec.rb
Normal file
73
spec/controllers/admin/domain_blocks_controller_spec.rb
Normal file
@@ -0,0 +1,73 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::DomainBlocksController, type: :controller do
|
||||
render_views
|
||||
|
||||
before do
|
||||
sign_in Fabricate(:user, admin: true), scope: :user
|
||||
end
|
||||
|
||||
describe 'GET #new' do
|
||||
it 'assigns a new domain block' do
|
||||
get :new
|
||||
|
||||
expect(assigns(:domain_block)).to be_instance_of(DomainBlock)
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
domain_block = Fabricate(:domain_block)
|
||||
get :show, params: { id: domain_block.id }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
it 'blocks the domain when succeeded to save' do
|
||||
allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
|
||||
|
||||
post :create, params: { domain_block: { domain: 'example.com', severity: 'silence' } }
|
||||
|
||||
expect(DomainBlockWorker).to have_received(:perform_async)
|
||||
expect(flash[:notice]).to eq I18n.t('admin.domain_blocks.created_msg')
|
||||
expect(response).to redirect_to(admin_instances_path(limited: '1'))
|
||||
end
|
||||
|
||||
it 'renders new when failed to save' do
|
||||
Fabricate(:domain_block, domain: 'example.com', severity: 'suspend')
|
||||
allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
|
||||
|
||||
post :create, params: { domain_block: { domain: 'example.com', severity: 'silence' } }
|
||||
|
||||
expect(DomainBlockWorker).not_to have_received(:perform_async)
|
||||
expect(response).to render_template :new
|
||||
end
|
||||
|
||||
it 'allows upgrading a block' do
|
||||
Fabricate(:domain_block, domain: 'example.com', severity: 'silence')
|
||||
allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
|
||||
|
||||
post :create, params: { domain_block: { domain: 'example.com', severity: 'silence', reject_media: true, reject_reports: true } }
|
||||
|
||||
expect(DomainBlockWorker).to have_received(:perform_async)
|
||||
expect(flash[:notice]).to eq I18n.t('admin.domain_blocks.created_msg')
|
||||
expect(response).to redirect_to(admin_instances_path(limited: '1'))
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
it 'unblocks the domain' do
|
||||
service = double(call: true)
|
||||
allow(UnblockDomainService).to receive(:new).and_return(service)
|
||||
domain_block = Fabricate(:domain_block)
|
||||
delete :destroy, params: { id: domain_block.id }
|
||||
|
||||
expect(service).to have_received(:call).with(domain_block)
|
||||
expect(flash[:notice]).to eq I18n.t('admin.domain_blocks.destroyed_msg')
|
||||
expect(response).to redirect_to(admin_instances_path(limited: '1'))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::EmailDomainBlocksController, type: :controller do
|
||||
render_views
|
||||
|
||||
before do
|
||||
sign_in Fabricate(:user, admin: true), scope: :user
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
around do |example|
|
||||
default_per_page = EmailDomainBlock.default_per_page
|
||||
EmailDomainBlock.paginates_per 1
|
||||
example.run
|
||||
EmailDomainBlock.paginates_per default_per_page
|
||||
end
|
||||
|
||||
it 'renders email blacks' do
|
||||
2.times { Fabricate(:email_domain_block) }
|
||||
|
||||
get :index, params: { page: 2 }
|
||||
|
||||
assigned = assigns(:email_domain_blocks)
|
||||
expect(assigned.count).to eq 1
|
||||
expect(assigned.klass).to be EmailDomainBlock
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #new' do
|
||||
it 'assigns a new email black' do
|
||||
get :new
|
||||
|
||||
expect(assigns(:email_domain_block)).to be_instance_of(EmailDomainBlock)
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
it 'blocks the domain when succeeded to save' do
|
||||
post :create, params: { email_domain_block: { domain: 'example.com' } }
|
||||
|
||||
expect(flash[:notice]).to eq I18n.t('admin.email_domain_blocks.created_msg')
|
||||
expect(response).to redirect_to(admin_email_domain_blocks_path)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
it 'unblocks the domain' do
|
||||
email_domain_block = Fabricate(:email_domain_block)
|
||||
delete :destroy, params: { id: email_domain_block.id }
|
||||
|
||||
expect(flash[:notice]).to eq I18n.t('admin.email_domain_blocks.destroyed_msg')
|
||||
expect(response).to redirect_to(admin_email_domain_blocks_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
32
spec/controllers/admin/instances_controller_spec.rb
Normal file
32
spec/controllers/admin/instances_controller_spec.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::InstancesController, type: :controller do
|
||||
render_views
|
||||
|
||||
before do
|
||||
sign_in Fabricate(:user, admin: true), scope: :user
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
around do |example|
|
||||
default_per_page = Account.default_per_page
|
||||
Account.paginates_per 1
|
||||
example.run
|
||||
Account.paginates_per default_per_page
|
||||
end
|
||||
|
||||
it 'renders instances' do
|
||||
Fabricate(:account, domain: 'popular')
|
||||
Fabricate(:account, domain: 'popular')
|
||||
Fabricate(:account, domain: 'less.popular')
|
||||
|
||||
get :index, params: { page: 2 }
|
||||
|
||||
instances = assigns(:instances).to_a
|
||||
expect(instances.size).to eq 1
|
||||
expect(instances[0].domain).to eq 'less.popular'
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
59
spec/controllers/admin/invites_controller_spec.rb
Normal file
59
spec/controllers/admin/invites_controller_spec.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::InvitesController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, admin: true) }
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
subject { get :index, params: { available: true } }
|
||||
|
||||
let!(:invite) { Fabricate(:invite) }
|
||||
|
||||
it 'renders index page' do
|
||||
expect(subject).to render_template :index
|
||||
expect(assigns(:invites)).to include invite
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
|
||||
|
||||
it 'succeeds to create a invite' do
|
||||
expect { subject }.to change { Invite.count }.by(1)
|
||||
expect(subject).to redirect_to admin_invites_path
|
||||
expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
let!(:invite) { Fabricate(:invite, expires_at: nil) }
|
||||
|
||||
subject { delete :destroy, params: { id: invite.id } }
|
||||
|
||||
it 'expires invite' do
|
||||
expect(subject).to redirect_to admin_invites_path
|
||||
expect(invite.reload).to be_expired
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #deactivate_all' do
|
||||
it 'expires all invites, then redirects to admin_invites_path' do
|
||||
invites = Fabricate.times(2, :invite, expires_at: nil)
|
||||
|
||||
post :deactivate_all
|
||||
|
||||
invites.each do |invite|
|
||||
expect(invite.reload).to be_expired
|
||||
end
|
||||
|
||||
expect(response).to redirect_to admin_invites_path
|
||||
end
|
||||
end
|
||||
end
|
||||
90
spec/controllers/admin/report_notes_controller_spec.rb
Normal file
90
spec/controllers/admin/report_notes_controller_spec.rb
Normal file
@@ -0,0 +1,90 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::ReportNotesController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, admin: true) }
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
subject { post :create, params: params }
|
||||
|
||||
let(:report) { Fabricate(:report, action_taken: action_taken, action_taken_by_account_id: account_id) }
|
||||
|
||||
context 'when parameter is valid' do
|
||||
context 'when report is unsolved' do
|
||||
let(:action_taken) { false }
|
||||
let(:account_id) { nil }
|
||||
|
||||
context 'when create_and_resolve flag is on' do
|
||||
let(:params) { { report_note: { content: 'test content', report_id: report.id }, create_and_resolve: nil } }
|
||||
|
||||
it 'creates a report note and resolves report' do
|
||||
expect { subject }.to change { ReportNote.count }.by(1)
|
||||
expect(report.reload).to be_action_taken
|
||||
expect(subject).to redirect_to admin_reports_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'when create_and_resolve flag is false' do
|
||||
let(:params) { { report_note: { content: 'test content', report_id: report.id } } }
|
||||
|
||||
it 'creates a report note and does not resolve report' do
|
||||
expect { subject }.to change { ReportNote.count }.by(1)
|
||||
expect(report.reload).not_to be_action_taken
|
||||
expect(subject).to redirect_to admin_report_path(report)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when report is resolved' do
|
||||
let(:action_taken) { true }
|
||||
let(:account_id) { user.account.id }
|
||||
|
||||
context 'when create_and_unresolve flag is on' do
|
||||
let(:params) { { report_note: { content: 'test content', report_id: report.id }, create_and_unresolve: nil } }
|
||||
|
||||
it 'creates a report note and unresolves report' do
|
||||
expect { subject }.to change { ReportNote.count }.by(1)
|
||||
expect(report.reload).not_to be_action_taken
|
||||
expect(subject).to redirect_to admin_report_path(report)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when create_and_unresolve flag is false' do
|
||||
let(:params) { { report_note: { content: 'test content', report_id: report.id } } }
|
||||
|
||||
it 'creates a report note and does not unresolve report' do
|
||||
expect { subject }.to change { ReportNote.count }.by(1)
|
||||
expect(report.reload).to be_action_taken
|
||||
expect(subject).to redirect_to admin_report_path(report)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parameter is invalid' do
|
||||
let(:params) { { report_note: { content: '', report_id: report.id } } }
|
||||
let(:action_taken) { false }
|
||||
let(:account_id) { nil }
|
||||
|
||||
it 'renders admin/reports/show' do
|
||||
expect(subject).to render_template 'admin/reports/show'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
subject { delete :destroy, params: { id: report_note.id } }
|
||||
|
||||
let!(:report_note) { Fabricate(:report_note) }
|
||||
|
||||
it 'deletes note' do
|
||||
expect { subject }.to change { ReportNote.count }.by(-1)
|
||||
expect(subject).to redirect_to admin_report_path(report_note.report)
|
||||
end
|
||||
end
|
||||
end
|
||||
59
spec/controllers/admin/reported_statuses_controller_spec.rb
Normal file
59
spec/controllers/admin/reported_statuses_controller_spec.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::ReportedStatusesController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, admin: true) }
|
||||
let(:report) { Fabricate(:report, status_ids: [status.id]) }
|
||||
let(:status) { Fabricate(:status) }
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
subject do
|
||||
-> { post :create, params: { :report_id => report, action => '', :form_status_batch => { status_ids: status_ids } } }
|
||||
end
|
||||
|
||||
let(:action) { 'nsfw_on' }
|
||||
let(:status_ids) { [status.id] }
|
||||
let(:status) { Fabricate(:status, sensitive: !sensitive) }
|
||||
let(:sensitive) { true }
|
||||
let!(:media_attachment) { Fabricate(:media_attachment, status: status) }
|
||||
|
||||
context 'when action is nsfw_on' do
|
||||
it 'updates sensitive column' do
|
||||
is_expected.to change {
|
||||
status.reload.sensitive
|
||||
}.from(false).to(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when action is nsfw_off' do
|
||||
let(:action) { 'nsfw_off' }
|
||||
let(:sensitive) { false }
|
||||
|
||||
it 'updates sensitive column' do
|
||||
is_expected.to change {
|
||||
status.reload.sensitive
|
||||
}.from(true).to(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when action is delete' do
|
||||
let(:action) { 'delete' }
|
||||
|
||||
it 'removes a status' do
|
||||
allow(RemovalWorker).to receive(:perform_async)
|
||||
subject.call
|
||||
expect(RemovalWorker).to have_received(:perform_async).with(status_ids.first)
|
||||
end
|
||||
end
|
||||
|
||||
it 'redirects to report page' do
|
||||
subject.call
|
||||
expect(response).to redirect_to(admin_report_path(report))
|
||||
end
|
||||
end
|
||||
end
|
||||
82
spec/controllers/admin/reports_controller_spec.rb
Normal file
82
spec/controllers/admin/reports_controller_spec.rb
Normal file
@@ -0,0 +1,82 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::ReportsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, admin: true) }
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success with no filters' do
|
||||
specified = Fabricate(:report, action_taken: false)
|
||||
Fabricate(:report, action_taken: true)
|
||||
|
||||
get :index
|
||||
|
||||
reports = assigns(:reports).to_a
|
||||
expect(reports.size).to eq 1
|
||||
expect(reports[0]).to eq specified
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns http success with resolved filter' do
|
||||
specified = Fabricate(:report, action_taken: true)
|
||||
Fabricate(:report, action_taken: false)
|
||||
|
||||
get :index, params: { resolved: 1 }
|
||||
|
||||
reports = assigns(:reports).to_a
|
||||
expect(reports.size).to eq 1
|
||||
expect(reports[0]).to eq specified
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'renders report' do
|
||||
report = Fabricate(:report)
|
||||
|
||||
get :show, params: { id: report }
|
||||
|
||||
expect(assigns(:report)).to eq report
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #reopen' do
|
||||
it 'reopens the report' do
|
||||
report = Fabricate(:report)
|
||||
|
||||
put :reopen, params: { id: report }
|
||||
expect(response).to redirect_to(admin_report_path(report))
|
||||
report.reload
|
||||
expect(report.action_taken_by_account).to eq nil
|
||||
expect(report.action_taken).to eq false
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #assign_to_self' do
|
||||
it 'reopens the report' do
|
||||
report = Fabricate(:report)
|
||||
|
||||
put :assign_to_self, params: { id: report }
|
||||
expect(response).to redirect_to(admin_report_path(report))
|
||||
report.reload
|
||||
expect(report.assigned_account).to eq user.account
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #unassign' do
|
||||
it 'reopens the report' do
|
||||
report = Fabricate(:report)
|
||||
|
||||
put :unassign, params: { id: report }
|
||||
expect(response).to redirect_to(admin_report_path(report))
|
||||
report.reload
|
||||
expect(report.assigned_account).to eq nil
|
||||
end
|
||||
end
|
||||
end
|
||||
22
spec/controllers/admin/resets_controller_spec.rb
Normal file
22
spec/controllers/admin/resets_controller_spec.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::ResetsController do
|
||||
render_views
|
||||
|
||||
let(:account) { Fabricate(:account, user: Fabricate(:user)) }
|
||||
before do
|
||||
sign_in Fabricate(:user, admin: true), scope: :user
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
it 'redirects to admin accounts page' do
|
||||
expect_any_instance_of(User).to receive(:send_reset_password_instructions) do |value|
|
||||
expect(value.account_id).to eq account.id
|
||||
end
|
||||
|
||||
post :create, params: { account_id: account.id }
|
||||
|
||||
expect(response).to redirect_to(admin_accounts_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
33
spec/controllers/admin/roles_controller_spec.rb
Normal file
33
spec/controllers/admin/roles_controller_spec.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::RolesController do
|
||||
render_views
|
||||
|
||||
let(:admin) { Fabricate(:user, admin: true) }
|
||||
|
||||
before do
|
||||
sign_in admin, scope: :user
|
||||
end
|
||||
|
||||
describe 'POST #promote' do
|
||||
subject { post :promote, params: { account_id: user.account_id } }
|
||||
|
||||
let(:user) { Fabricate(:user, moderator: false, admin: false) }
|
||||
|
||||
it 'promotes user' do
|
||||
expect(subject).to redirect_to admin_account_path(user.account_id)
|
||||
expect(user.reload).to be_moderator
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #demote' do
|
||||
subject { post :demote, params: { account_id: user.account_id } }
|
||||
|
||||
let(:user) { Fabricate(:user, moderator: true, admin: false) }
|
||||
|
||||
it 'demotes user' do
|
||||
expect(subject).to redirect_to admin_account_path(user.account_id)
|
||||
expect(user.reload).not_to be_moderator
|
||||
end
|
||||
end
|
||||
end
|
||||
71
spec/controllers/admin/settings_controller_spec.rb
Normal file
71
spec/controllers/admin/settings_controller_spec.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::SettingsController, type: :controller do
|
||||
render_views
|
||||
|
||||
describe 'When signed in as an admin' do
|
||||
before do
|
||||
sign_in Fabricate(:user, admin: true), scope: :user
|
||||
end
|
||||
|
||||
describe 'GET #edit' do
|
||||
it 'returns http success' do
|
||||
get :edit
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
before do
|
||||
allow_any_instance_of(Form::AdminSettings).to receive(:valid?).and_return(true)
|
||||
end
|
||||
|
||||
describe 'for a record that doesnt exist' do
|
||||
around do |example|
|
||||
before = Setting.site_extended_description
|
||||
Setting.site_extended_description = nil
|
||||
example.run
|
||||
Setting.site_extended_description = before
|
||||
Setting.new_setting_key = nil
|
||||
end
|
||||
|
||||
it 'cannot create a setting value for a non-admin key' do
|
||||
expect(Setting.new_setting_key).to be_blank
|
||||
|
||||
patch :update, params: { form_admin_settings: { new_setting_key: 'New key value' } }
|
||||
|
||||
expect(response).to redirect_to(edit_admin_settings_path)
|
||||
expect(Setting.new_setting_key).to be_nil
|
||||
end
|
||||
|
||||
it 'creates a settings value that didnt exist before for eligible key' do
|
||||
expect(Setting.site_extended_description).to be_blank
|
||||
|
||||
patch :update, params: { form_admin_settings: { site_extended_description: 'New key value' } }
|
||||
|
||||
expect(response).to redirect_to(edit_admin_settings_path)
|
||||
expect(Setting.site_extended_description).to eq 'New key value'
|
||||
end
|
||||
end
|
||||
|
||||
context do
|
||||
around do |example|
|
||||
site_title = Setting.site_title
|
||||
example.run
|
||||
Setting.site_title = site_title
|
||||
end
|
||||
|
||||
it 'updates a settings value' do
|
||||
Setting.site_title = 'Original'
|
||||
patch :update, params: { form_admin_settings: { site_title: 'New title' } }
|
||||
|
||||
expect(response).to redirect_to(edit_admin_settings_path)
|
||||
expect(Setting.site_title).to eq 'New title'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
77
spec/controllers/admin/statuses_controller_spec.rb
Normal file
77
spec/controllers/admin/statuses_controller_spec.rb
Normal file
@@ -0,0 +1,77 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::StatusesController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, admin: true) }
|
||||
let(:account) { Fabricate(:account) }
|
||||
let!(:status) { Fabricate(:status, account: account) }
|
||||
let(:media_attached_status) { Fabricate(:status, account: account, sensitive: !sensitive) }
|
||||
let!(:media_attachment) { Fabricate(:media_attachment, account: account, status: media_attached_status) }
|
||||
let(:sensitive) { true }
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success with no media' do
|
||||
get :index, params: { account_id: account.id }
|
||||
|
||||
statuses = assigns(:statuses).to_a
|
||||
expect(statuses.size).to eq 2
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns http success with media' do
|
||||
get :index, params: { account_id: account.id, media: true }
|
||||
|
||||
statuses = assigns(:statuses).to_a
|
||||
expect(statuses.size).to eq 1
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
subject do
|
||||
-> { post :create, params: { :account_id => account.id, action => '', :form_status_batch => { status_ids: status_ids } } }
|
||||
end
|
||||
|
||||
let(:action) { 'nsfw_on' }
|
||||
let(:status_ids) { [media_attached_status.id] }
|
||||
|
||||
context 'when action is nsfw_on' do
|
||||
it 'updates sensitive column' do
|
||||
is_expected.to change {
|
||||
media_attached_status.reload.sensitive
|
||||
}.from(false).to(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when action is nsfw_off' do
|
||||
let(:action) { 'nsfw_off' }
|
||||
let(:sensitive) { false }
|
||||
|
||||
it 'updates sensitive column' do
|
||||
is_expected.to change {
|
||||
media_attached_status.reload.sensitive
|
||||
}.from(true).to(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when action is delete' do
|
||||
let(:action) { 'delete' }
|
||||
|
||||
it 'removes a status' do
|
||||
allow(RemovalWorker).to receive(:perform_async)
|
||||
subject.call
|
||||
expect(RemovalWorker).to have_received(:perform_async).with(status_ids.first)
|
||||
end
|
||||
end
|
||||
|
||||
it 'redirects to account statuses page' do
|
||||
subject.call
|
||||
expect(response).to redirect_to(admin_account_statuses_path(account.id))
|
||||
end
|
||||
end
|
||||
end
|
||||
32
spec/controllers/admin/subscriptions_controller_spec.rb
Normal file
32
spec/controllers/admin/subscriptions_controller_spec.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
# frozen_string_literal: true
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::SubscriptionsController, type: :controller do
|
||||
render_views
|
||||
|
||||
describe 'GET #index' do
|
||||
around do |example|
|
||||
default_per_page = Subscription.default_per_page
|
||||
Subscription.paginates_per 1
|
||||
example.run
|
||||
Subscription.paginates_per default_per_page
|
||||
end
|
||||
|
||||
before do
|
||||
sign_in Fabricate(:user, admin: true), scope: :user
|
||||
end
|
||||
|
||||
it 'renders subscriptions' do
|
||||
Fabricate(:subscription)
|
||||
specified = Fabricate(:subscription)
|
||||
|
||||
get :index
|
||||
|
||||
subscriptions = assigns(:subscriptions)
|
||||
expect(subscriptions.count).to eq 1
|
||||
expect(subscriptions[0]).to eq specified
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
71
spec/controllers/admin/tags_controller_spec.rb
Normal file
71
spec/controllers/admin/tags_controller_spec.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::TagsController, type: :controller do
|
||||
render_views
|
||||
|
||||
before do
|
||||
sign_in Fabricate(:user, admin: true)
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
before do
|
||||
account_tag_stat = Fabricate(:tag).account_tag_stat
|
||||
account_tag_stat.update(hidden: hidden, accounts_count: 1)
|
||||
get :index, params: { hidden: hidden }
|
||||
end
|
||||
|
||||
context 'with hidden tags' do
|
||||
let(:hidden) { true }
|
||||
|
||||
it 'returns status 200' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without hidden tags' do
|
||||
let(:hidden) { false }
|
||||
|
||||
it 'returns status 200' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #hide' do
|
||||
let(:tag) { Fabricate(:tag) }
|
||||
|
||||
before do
|
||||
tag.account_tag_stat.update(hidden: false)
|
||||
post :hide, params: { id: tag.id }
|
||||
end
|
||||
|
||||
it 'hides tag' do
|
||||
tag.reload
|
||||
expect(tag).to be_hidden
|
||||
end
|
||||
|
||||
it 'redirects to admin_tags_path' do
|
||||
expect(response).to redirect_to(admin_tags_path(controller.instance_variable_get(:@filter_params)))
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #unhide' do
|
||||
let(:tag) { Fabricate(:tag) }
|
||||
|
||||
before do
|
||||
tag.account_tag_stat.update(hidden: true)
|
||||
post :unhide, params: { id: tag.id }
|
||||
end
|
||||
|
||||
it 'unhides tag' do
|
||||
tag.reload
|
||||
expect(tag).not_to be_hidden
|
||||
end
|
||||
|
||||
it 'redirects to admin_tags_path' do
|
||||
expect(response).to redirect_to(admin_tags_path(controller.instance_variable_get(:@filter_params)))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::TwoFactorAuthenticationsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, otp_required_for_login: true) }
|
||||
before do
|
||||
sign_in Fabricate(:user, admin: true), scope: :user
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
it 'redirects to admin accounts page' do
|
||||
delete :destroy, params: { user_id: user.id }
|
||||
|
||||
user.reload
|
||||
expect(user.otp_required_for_login).to eq false
|
||||
expect(response).to redirect_to(admin_accounts_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
54
spec/controllers/api/base_controller_spec.rb
Normal file
54
spec/controllers/api/base_controller_spec.rb
Normal file
@@ -0,0 +1,54 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
class FakeService; end
|
||||
|
||||
describe Api::BaseController do
|
||||
controller do
|
||||
def success
|
||||
head 200
|
||||
end
|
||||
|
||||
def error
|
||||
FakeService.new
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Forgery protection' do
|
||||
before do
|
||||
routes.draw { post 'success' => 'api/base#success' }
|
||||
end
|
||||
|
||||
it 'does not protect from forgery' do
|
||||
ActionController::Base.allow_forgery_protection = true
|
||||
post 'success'
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Error handling' do
|
||||
ERRORS_WITH_CODES = {
|
||||
ActiveRecord::RecordInvalid => 422,
|
||||
GabSocial::ValidationError => 422,
|
||||
ActiveRecord::RecordNotFound => 404,
|
||||
GabSocial::UnexpectedResponseError => 503,
|
||||
HTTP::Error => 503,
|
||||
OpenSSL::SSL::SSLError => 503,
|
||||
GabSocial::NotPermittedError => 403,
|
||||
}
|
||||
|
||||
before do
|
||||
routes.draw { get 'error' => 'api/base#error' }
|
||||
end
|
||||
|
||||
ERRORS_WITH_CODES.each do |error, code|
|
||||
it "Handles error class of #{error}" do
|
||||
expect(FakeService).to receive(:new).and_raise(error)
|
||||
|
||||
get 'error'
|
||||
expect(response).to have_http_status(code)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
19
spec/controllers/api/oembed_controller_spec.rb
Normal file
19
spec/controllers/api/oembed_controller_spec.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::OEmbedController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:alice) { Fabricate(:account, username: 'alice') }
|
||||
let(:status) { Fabricate(:status, text: 'Hello world', account: alice) }
|
||||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
request.host = Rails.configuration.x.local_domain
|
||||
get :show, params: { url: account_stream_entry_url(alice, status.stream_entry) }, format: :json
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
96
spec/controllers/api/proofs_controller_spec.rb
Normal file
96
spec/controllers/api/proofs_controller_spec.rb
Normal file
@@ -0,0 +1,96 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::ProofsController do
|
||||
let(:alice) { Fabricate(:account, username: 'alice') }
|
||||
|
||||
before do
|
||||
stub_request(:get, 'https://keybase.io/_/api/1.0/sig/proof_valid.json?domain=cb6e6126.ngrok.io&kb_username=crypto_alice&sig_hash=111111111111111111111111111111111111111111111111111111111111111111&username=alice').to_return(status: 200, body: '{"proof_valid":true,"proof_live":false}')
|
||||
stub_request(:get, 'https://keybase.io/_/api/1.0/sig/proof_live.json?domain=cb6e6126.ngrok.io&kb_username=crypto_alice&sig_hash=111111111111111111111111111111111111111111111111111111111111111111&username=alice').to_return(status: 200, body: '{"proof_valid":true,"proof_live":true}')
|
||||
stub_request(:get, 'https://keybase.io/_/api/1.0/sig/proof_valid.json?domain=cb6e6126.ngrok.io&kb_username=hidden_alice&sig_hash=222222222222222222222222222222222222222222222222222222222222222222&username=alice').to_return(status: 200, body: '{"proof_valid":true,"proof_live":true}')
|
||||
stub_request(:get, 'https://keybase.io/_/api/1.0/sig/proof_live.json?domain=cb6e6126.ngrok.io&kb_username=hidden_alice&sig_hash=222222222222222222222222222222222222222222222222222222222222222222&username=alice').to_return(status: 200, body: '{"proof_valid":true,"proof_live":true}')
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
describe 'with a non-existent username' do
|
||||
it '404s' do
|
||||
get :index, params: { username: 'nonexistent', provider: 'keybase' }
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a user that has no proofs' do
|
||||
it 'is an empty list of signatures' do
|
||||
get :index, params: { username: alice.username, provider: 'keybase' }
|
||||
|
||||
expect(body_as_json[:signatures]).to eq []
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a user that has a live, valid proof' do
|
||||
let(:token1) { '111111111111111111111111111111111111111111111111111111111111111111' }
|
||||
let(:kb_name1) { 'crypto_alice' }
|
||||
|
||||
before do
|
||||
Fabricate(:account_identity_proof, account: alice, verified: true, live: true, token: token1, provider_username: kb_name1)
|
||||
end
|
||||
|
||||
it 'is a list with that proof in it' do
|
||||
get :index, params: { username: alice.username, provider: 'keybase' }
|
||||
|
||||
expect(body_as_json[:signatures]).to eq [
|
||||
{ kb_username: kb_name1, sig_hash: token1 },
|
||||
]
|
||||
end
|
||||
|
||||
describe 'add one that is neither live nor valid' do
|
||||
let(:token2) { '222222222222222222222222222222222222222222222222222222222222222222' }
|
||||
let(:kb_name2) { 'hidden_alice' }
|
||||
|
||||
before do
|
||||
Fabricate(:account_identity_proof, account: alice, verified: false, live: false, token: token2, provider_username: kb_name2)
|
||||
end
|
||||
|
||||
it 'is a list with both proofs' do
|
||||
get :index, params: { username: alice.username, provider: 'keybase' }
|
||||
|
||||
expect(body_as_json[:signatures]).to eq [
|
||||
{ kb_username: kb_name1, sig_hash: token1 },
|
||||
{ kb_username: kb_name2, sig_hash: token2 },
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'a user that has an avatar' do
|
||||
let(:alice) { Fabricate(:account, username: 'alice', avatar: attachment_fixture('avatar.gif')) }
|
||||
|
||||
context 'and a proof' do
|
||||
let(:token1) { '111111111111111111111111111111111111111111111111111111111111111111' }
|
||||
let(:kb_name1) { 'crypto_alice' }
|
||||
|
||||
before do
|
||||
Fabricate(:account_identity_proof, account: alice, verified: true, live: true, token: token1, provider_username: kb_name1)
|
||||
get :index, params: { username: alice.username, provider: 'keybase' }
|
||||
end
|
||||
|
||||
it 'has two keys: signatures and avatar' do
|
||||
expect(body_as_json.keys).to match_array [:signatures, :avatar]
|
||||
end
|
||||
|
||||
it 'has the correct signatures' do
|
||||
expect(body_as_json[:signatures]).to eq [
|
||||
{ kb_username: kb_name1, sig_hash: token1 },
|
||||
]
|
||||
end
|
||||
|
||||
it 'has the correct avatar url' do
|
||||
first_part = 'https://cb6e6126.ngrok.io/system/accounts/avatars/'
|
||||
last_part = 'original/avatar.gif'
|
||||
|
||||
expect(body_as_json[:avatar]).to match /#{Regexp.quote(first_part)}(?:\d{3,5}\/){3}#{Regexp.quote(last_part)}/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
59
spec/controllers/api/push_controller_spec.rb
Normal file
59
spec/controllers/api/push_controller_spec.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::PushController, type: :controller do
|
||||
describe 'POST #update' do
|
||||
context 'with hub.mode=subscribe' do
|
||||
it 'creates a subscription' do
|
||||
service = double(call: ['', 202])
|
||||
allow(Pubsubhubbub::SubscribeService).to receive(:new).and_return(service)
|
||||
account = Fabricate(:account)
|
||||
account_topic_url = "https://#{Rails.configuration.x.local_domain}/users/#{account.username}.atom"
|
||||
post :update, params: {
|
||||
'hub.mode' => 'subscribe',
|
||||
'hub.topic' => account_topic_url,
|
||||
'hub.callback' => 'https://callback.host/api',
|
||||
'hub.lease_seconds' => '3600',
|
||||
'hub.secret' => 'as1234df',
|
||||
}
|
||||
|
||||
expect(service).to have_received(:call).with(
|
||||
account,
|
||||
'https://callback.host/api',
|
||||
'as1234df',
|
||||
'3600',
|
||||
nil
|
||||
)
|
||||
expect(response).to have_http_status(202)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with hub.mode=unsubscribe' do
|
||||
it 'unsubscribes the account' do
|
||||
service = double(call: ['', 202])
|
||||
allow(Pubsubhubbub::UnsubscribeService).to receive(:new).and_return(service)
|
||||
account = Fabricate(:account)
|
||||
account_topic_url = "https://#{Rails.configuration.x.local_domain}/users/#{account.username}.atom"
|
||||
post :update, params: {
|
||||
'hub.mode' => 'unsubscribe',
|
||||
'hub.topic' => account_topic_url,
|
||||
'hub.callback' => 'https://callback.host/api',
|
||||
}
|
||||
|
||||
expect(service).to have_received(:call).with(
|
||||
account,
|
||||
'https://callback.host/api',
|
||||
)
|
||||
expect(response).to have_http_status(202)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with unknown mode' do
|
||||
it 'returns an unknown mode error' do
|
||||
post :update, params: { 'hub.mode' => 'fake' }
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
expect(response.body).to match(/Unknown mode/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
65
spec/controllers/api/salmon_controller_spec.rb
Normal file
65
spec/controllers/api/salmon_controller_spec.rb
Normal file
@@ -0,0 +1,65 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::SalmonController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:account) { Fabricate(:user, account: Fabricate(:account, username: 'catsrgr8')).account }
|
||||
|
||||
before do
|
||||
stub_request(:get, "https://quitter.no/.well-known/host-meta").to_return(request_fixture('.host-meta.txt'))
|
||||
stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:robcolbert@quitter.no").to_return(request_fixture('webfinger.txt'))
|
||||
stub_request(:get, "https://quitter.no/api/statuses/user_timeline/7477.atom").to_return(request_fixture('feed.txt'))
|
||||
stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt'))
|
||||
end
|
||||
|
||||
describe 'POST #update' do
|
||||
context 'with valid post data' do
|
||||
before do
|
||||
post :update, params: { id: account.id }, body: File.read(Rails.root.join('spec', 'fixtures', 'salmon', 'mention.xml'))
|
||||
end
|
||||
|
||||
it 'contains XML in the request body' do
|
||||
expect(request.body.read).to be_a String
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(202)
|
||||
end
|
||||
|
||||
it 'creates remote account' do
|
||||
expect(Account.find_by(username: 'robcolbert', domain: 'quitter.no')).to_not be_nil
|
||||
end
|
||||
|
||||
it 'creates status' do
|
||||
expect(Status.find_by(uri: 'tag:quitter.no,2016-03-20:noticeId=1276923:objectType=note')).to_not be_nil
|
||||
end
|
||||
|
||||
it 'creates mention for target account' do
|
||||
expect(account.mentions.count).to eq 1
|
||||
end
|
||||
end
|
||||
|
||||
context 'with empty post data' do
|
||||
before do
|
||||
post :update, params: { id: account.id }, body: ''
|
||||
end
|
||||
|
||||
it 'returns http client error' do
|
||||
expect(response).to have_http_status(400)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid post data' do
|
||||
before do
|
||||
service = double(call: false)
|
||||
allow(VerifySalmonService).to receive(:new).and_return(service)
|
||||
|
||||
post :update, params: { id: account.id }, body: File.read(Rails.root.join('spec', 'fixtures', 'salmon', 'mention.xml'))
|
||||
end
|
||||
|
||||
it 'returns http client error' do
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
68
spec/controllers/api/subscriptions_controller_spec.rb
Normal file
68
spec/controllers/api/subscriptions_controller_spec.rb
Normal file
@@ -0,0 +1,68 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::SubscriptionsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:account) { Fabricate(:account, username: 'robcolbert', domain: 'quitter.no', remote_url: 'topic_url', secret: 'abc') }
|
||||
|
||||
describe 'GET #show' do
|
||||
context 'with valid subscription' do
|
||||
before do
|
||||
get :show, params: { :id => account.id, 'hub.topic' => 'topic_url', 'hub.challenge' => '456', 'hub.lease_seconds' => "#{86400 * 30}" }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'echoes back the challenge' do
|
||||
expect(response.body).to match '456'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid subscription' do
|
||||
before do
|
||||
expect_any_instance_of(Account).to receive_message_chain(:subscription, :valid?).and_return(false)
|
||||
get :show, params: { :id => account.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #update' do
|
||||
let(:feed) { File.read(Rails.root.join('spec', 'fixtures', 'push', 'feed.atom')) }
|
||||
|
||||
before do
|
||||
stub_request(:post, "https://quitter.no/main/push/hub").to_return(:status => 200, :body => "", :headers => {})
|
||||
stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt'))
|
||||
stub_request(:get, "https://quitter.no/notice/1269244").to_return(status: 404)
|
||||
stub_request(:get, "https://quitter.no/notice/1265331").to_return(status: 404)
|
||||
stub_request(:get, "https://community.highlandarrow.com/notice/54411").to_return(status: 404)
|
||||
stub_request(:get, "https://community.highlandarrow.com/notice/53857").to_return(status: 404)
|
||||
stub_request(:get, "https://community.highlandarrow.com/notice/51852").to_return(status: 404)
|
||||
stub_request(:get, "https://social.umeahackerspace.se/notice/424348").to_return(status: 404)
|
||||
stub_request(:get, "https://community.highlandarrow.com/notice/50467").to_return(status: 404)
|
||||
stub_request(:get, "https://quitter.no/notice/1243309").to_return(status: 404)
|
||||
stub_request(:get, "https://quitter.no/user/7477").to_return(status: 404)
|
||||
stub_request(:any, "https://community.highlandarrow.com/user/1").to_return(status: 404)
|
||||
stub_request(:any, "https://social.umeahackerspace.se/user/2").to_return(status: 404)
|
||||
stub_request(:any, "https://gs.kawa-kun.com/user/2").to_return(status: 404)
|
||||
stub_request(:any, "https://mastodon.social/users/Gargron").to_return(status: 404)
|
||||
|
||||
request.env['HTTP_X_HUB_SIGNATURE'] = "sha1=#{OpenSSL::HMAC.hexdigest('sha1', 'abc', feed)}"
|
||||
|
||||
post :update, params: { id: account.id }, body: feed
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates statuses for feed' do
|
||||
expect(account.statuses.count).to_not eq 0
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,93 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::CredentialsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:scopes) { 'read:accounts' }
|
||||
|
||||
it 'returns http success' do
|
||||
get :show
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH #update' do
|
||||
let(:scopes) { 'write:accounts' }
|
||||
|
||||
describe 'with valid data' do
|
||||
before do
|
||||
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
|
||||
|
||||
patch :update, params: {
|
||||
display_name: "Alice Isn't Dead",
|
||||
note: "Hi!\n\nToot toot!",
|
||||
avatar: fixture_file_upload('files/avatar.gif', 'image/gif'),
|
||||
header: fixture_file_upload('files/attachment.jpg', 'image/jpeg'),
|
||||
source: {
|
||||
privacy: 'unlisted',
|
||||
sensitive: true,
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'updates account info' do
|
||||
user.account.reload
|
||||
|
||||
expect(user.account.display_name).to eq("Alice Isn't Dead")
|
||||
expect(user.account.note).to eq("Hi!\n\nToot toot!")
|
||||
expect(user.account.avatar).to exist
|
||||
expect(user.account.header).to exist
|
||||
expect(user.setting_default_privacy).to eq('unlisted')
|
||||
expect(user.setting_default_sensitive).to eq(true)
|
||||
end
|
||||
|
||||
it 'queues up an account update distribution' do
|
||||
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(user.account_id)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with invalid data' do
|
||||
before do
|
||||
patch :update, params: { note: 'This is too long. ' * 30 }
|
||||
end
|
||||
|
||||
it 'returns http unprocessable entity' do
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { nil }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http unauthorized' do
|
||||
get :show
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH #update' do
|
||||
it 'returns http unauthorized' do
|
||||
patch :update, params: { note: 'Foo' }
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::FollowerAccountsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
|
||||
|
||||
before do
|
||||
Fabricate(:follow, target_account: user.account)
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: user.account.id, limit: 1 }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::FollowingAccountsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
|
||||
|
||||
before do
|
||||
Fabricate(:follow, account: user.account)
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: user.account.id, limit: 1 }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
23
spec/controllers/api/v1/accounts/lists_controller_spec.rb
Normal file
23
spec/controllers/api/v1/accounts/lists_controller_spec.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::ListsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:lists') }
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:list) { Fabricate(:list, account: user.account) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
user.account.follow!(account)
|
||||
list.accounts << account
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: account.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
46
spec/controllers/api/v1/accounts/pins_controller_spec.rb
Normal file
46
spec/controllers/api/v1/accounts/pins_controller_spec.rb
Normal file
@@ -0,0 +1,46 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Accounts::PinsController, type: :controller do
|
||||
let(:john) { Fabricate(:user, account: Fabricate(:account, username: 'john')) }
|
||||
let(:kevin) { Fabricate(:user, account: Fabricate(:account, username: 'kevin')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: john.id, scopes: 'write:accounts') }
|
||||
|
||||
before do
|
||||
kevin.account.followers << john.account
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
subject { post :create, params: { account_id: kevin.account.id } }
|
||||
|
||||
it 'returns 200' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates account_pin' do
|
||||
expect do
|
||||
subject
|
||||
end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
subject { delete :destroy, params: { account_id: kevin.account.id } }
|
||||
|
||||
before do
|
||||
Fabricate(:account_pin, account: john.account, target_account: kevin.account)
|
||||
end
|
||||
|
||||
it 'returns 200' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'destroys account_pin' do
|
||||
expect do
|
||||
subject
|
||||
end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(-1)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,93 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::RelationshipsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:follows') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:simon) { Fabricate(:user, email: 'simon@example.com', account: Fabricate(:account, username: 'simon')).account }
|
||||
let(:lewis) { Fabricate(:user, email: 'lewis@example.com', account: Fabricate(:account, username: 'lewis')).account }
|
||||
|
||||
before do
|
||||
user.account.follow!(simon)
|
||||
lewis.follow!(user.account)
|
||||
end
|
||||
|
||||
context 'provided only one ID' do
|
||||
before do
|
||||
get :index, params: { id: simon.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns JSON with correct data' do
|
||||
json = body_as_json
|
||||
|
||||
expect(json).to be_a Enumerable
|
||||
expect(json.first[:following]).to be true
|
||||
expect(json.first[:followed_by]).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context 'provided multiple IDs' do
|
||||
before do
|
||||
get :index, params: { id: [simon.id, lewis.id] }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns JSON with correct data' do
|
||||
json = body_as_json
|
||||
|
||||
expect(json).to be_a Enumerable
|
||||
expect(json.first[:id]).to eq simon.id.to_s
|
||||
expect(json.first[:following]).to be true
|
||||
expect(json.first[:showing_reblogs]).to be true
|
||||
expect(json.first[:followed_by]).to be false
|
||||
expect(json.first[:muting]).to be false
|
||||
expect(json.first[:requested]).to be false
|
||||
expect(json.first[:domain_blocking]).to be false
|
||||
|
||||
expect(json.second[:id]).to eq lewis.id.to_s
|
||||
expect(json.second[:following]).to be false
|
||||
expect(json.second[:showing_reblogs]).to be false
|
||||
expect(json.second[:followed_by]).to be true
|
||||
expect(json.second[:muting]).to be false
|
||||
expect(json.second[:requested]).to be false
|
||||
expect(json.second[:domain_blocking]).to be false
|
||||
end
|
||||
|
||||
it 'returns JSON with correct data on cached requests too' do
|
||||
get :index, params: { id: [simon.id] }
|
||||
|
||||
json = body_as_json
|
||||
|
||||
expect(json).to be_a Enumerable
|
||||
expect(json.first[:following]).to be true
|
||||
expect(json.first[:showing_reblogs]).to be true
|
||||
end
|
||||
|
||||
it 'returns JSON with correct data after change too' do
|
||||
user.account.unfollow!(simon)
|
||||
|
||||
get :index, params: { id: [simon.id] }
|
||||
|
||||
json = body_as_json
|
||||
|
||||
expect(json).to be_a Enumerable
|
||||
expect(json.first[:following]).to be false
|
||||
expect(json.first[:showing_reblogs]).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
20
spec/controllers/api/v1/accounts/search_controller_spec.rb
Normal file
20
spec/controllers/api/v1/accounts/search_controller_spec.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Accounts::SearchController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
get :show, params: { q: 'query' }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
54
spec/controllers/api/v1/accounts/statuses_controller_spec.rb
Normal file
54
spec/controllers/api/v1/accounts/statuses_controller_spec.rb
Normal file
@@ -0,0 +1,54 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::StatusesController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
Fabricate(:status, account: user.account)
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: user.account.id, limit: 1 }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size).to eq(2)
|
||||
end
|
||||
|
||||
context 'with only media' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: user.account.id, only_media: true }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with exclude replies' do
|
||||
before do
|
||||
Fabricate(:status, account: user.account, thread: Fabricate(:status))
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: user.account.id, exclude_replies: true }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with only pinned' do
|
||||
before do
|
||||
Fabricate(:status_pin, account: user.account, status: Fabricate(:status, account: user.account))
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: user.account.id, pinned: true }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
260
spec/controllers/api/v1/accounts_controller_spec.rb
Normal file
260
spec/controllers/api/v1/accounts_controller_spec.rb
Normal file
@@ -0,0 +1,260 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::AccountsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:scopes) { '' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||
let(:scopes) { wrong_scope }
|
||||
|
||||
it 'returns http forbidden' do
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:app) { Fabricate(:application) }
|
||||
let(:token) { Doorkeeper::AccessToken.find_or_create_for(app, nil, 'read write', nil, false) }
|
||||
let(:agreement) { nil }
|
||||
|
||||
before do
|
||||
post :create, params: { username: 'test', password: '12345678', email: 'hello@world.tld', agreement: agreement }
|
||||
end
|
||||
|
||||
context 'given truthy agreement' do
|
||||
let(:agreement) { 'true' }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns a new access token as JSON' do
|
||||
expect(body_as_json[:access_token]).to_not be_blank
|
||||
end
|
||||
|
||||
it 'creates a user' do
|
||||
user = User.find_by(email: 'hello@world.tld')
|
||||
expect(user).to_not be_nil
|
||||
expect(user.created_by_application_id).to eq app.id
|
||||
end
|
||||
end
|
||||
|
||||
context 'given no agreement' do
|
||||
it 'returns http unprocessable entity' do
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:scopes) { 'read:accounts' }
|
||||
|
||||
before do
|
||||
get :show, params: { id: user.account.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||
end
|
||||
|
||||
describe 'POST #follow' do
|
||||
let(:scopes) { 'write:follows' }
|
||||
let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', locked: locked)).account }
|
||||
|
||||
before do
|
||||
post :follow, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
context 'with unlocked account' do
|
||||
let(:locked) { false }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns JSON with following=true and requested=false' do
|
||||
json = body_as_json
|
||||
|
||||
expect(json[:following]).to be true
|
||||
expect(json[:requested]).to be false
|
||||
end
|
||||
|
||||
it 'creates a following relation between user and target user' do
|
||||
expect(user.account.following?(other_account)).to be true
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
context 'with locked account' do
|
||||
let(:locked) { true }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns JSON with following=false and requested=true' do
|
||||
json = body_as_json
|
||||
|
||||
expect(json[:following]).to be false
|
||||
expect(json[:requested]).to be true
|
||||
end
|
||||
|
||||
it 'creates a follow request relation between user and target user' do
|
||||
expect(user.account.requested?(other_account)).to be true
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #unfollow' do
|
||||
let(:scopes) { 'write:follows' }
|
||||
let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
|
||||
|
||||
before do
|
||||
user.account.follow!(other_account)
|
||||
post :unfollow, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'removes the following relation between user and target user' do
|
||||
expect(user.account.following?(other_account)).to be false
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #block' do
|
||||
let(:scopes) { 'write:blocks' }
|
||||
let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
|
||||
|
||||
before do
|
||||
user.account.follow!(other_account)
|
||||
post :block, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'removes the following relation between user and target user' do
|
||||
expect(user.account.following?(other_account)).to be false
|
||||
end
|
||||
|
||||
it 'creates a blocking relation' do
|
||||
expect(user.account.blocking?(other_account)).to be true
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #unblock' do
|
||||
let(:scopes) { 'write:blocks' }
|
||||
let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
|
||||
|
||||
before do
|
||||
user.account.block!(other_account)
|
||||
post :unblock, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'removes the blocking relation between user and target user' do
|
||||
expect(user.account.blocking?(other_account)).to be false
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #mute' do
|
||||
let(:scopes) { 'write:mutes' }
|
||||
let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
|
||||
|
||||
before do
|
||||
user.account.follow!(other_account)
|
||||
post :mute, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'does not remove the following relation between user and target user' do
|
||||
expect(user.account.following?(other_account)).to be true
|
||||
end
|
||||
|
||||
it 'creates a muting relation' do
|
||||
expect(user.account.muting?(other_account)).to be true
|
||||
end
|
||||
|
||||
it 'mutes notifications' do
|
||||
expect(user.account.muting_notifications?(other_account)).to be true
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #mute with notifications set to false' do
|
||||
let(:scopes) { 'write:mutes' }
|
||||
let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
|
||||
|
||||
before do
|
||||
user.account.follow!(other_account)
|
||||
post :mute, params: { id: other_account.id, notifications: false }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'does not remove the following relation between user and target user' do
|
||||
expect(user.account.following?(other_account)).to be true
|
||||
end
|
||||
|
||||
it 'creates a muting relation' do
|
||||
expect(user.account.muting?(other_account)).to be true
|
||||
end
|
||||
|
||||
it 'does not mute notifications' do
|
||||
expect(user.account.muting_notifications?(other_account)).to be false
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #unmute' do
|
||||
let(:scopes) { 'write:mutes' }
|
||||
let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
|
||||
|
||||
before do
|
||||
user.account.mute!(other_account)
|
||||
post :unmute, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'removes the muting relation between user and target user' do
|
||||
expect(user.account.muting?(other_account)).to be false
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
end
|
||||
43
spec/controllers/api/v1/apps/credentials_controller_spec.rb
Normal file
43
spec/controllers/api/v1/apps/credentials_controller_spec.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Apps::CredentialsController do
|
||||
render_views
|
||||
|
||||
let(:token) { Fabricate(:accessible_access_token, scopes: 'read', application: Fabricate(:application)) }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
get :show
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'does not contain client credentials' do
|
||||
json = body_as_json
|
||||
|
||||
expect(json).to_not have_key(:client_secret)
|
||||
expect(json).to_not have_key(:client_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { nil }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http unauthorized' do
|
||||
get :show
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
26
spec/controllers/api/v1/apps_controller_spec.rb
Normal file
26
spec/controllers/api/v1/apps_controller_spec.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::AppsController, type: :controller do
|
||||
render_views
|
||||
|
||||
describe 'POST #create' do
|
||||
before do
|
||||
post :create, params: { client_name: 'Test app', redirect_uris: 'urn:ietf:wg:oauth:2.0:oob' }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates an OAuth app' do
|
||||
expect(Doorkeeper::Application.find_by(name: 'Test app')).to_not be nil
|
||||
end
|
||||
|
||||
it 'returns client ID and client secret' do
|
||||
json = body_as_json
|
||||
|
||||
expect(json[:client_id]).to_not be_blank
|
||||
expect(json[:client_secret]).to_not be_blank
|
||||
end
|
||||
end
|
||||
end
|
||||
63
spec/controllers/api/v1/blocks_controller_spec.rb
Normal file
63
spec/controllers/api/v1/blocks_controller_spec.rb
Normal file
@@ -0,0 +1,63 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::BlocksController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:scopes) { 'read:blocks' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
before { allow(controller).to receive(:doorkeeper_token) { token } }
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'limits according to limit parameter' do
|
||||
2.times.map { Fabricate(:block, account: user.account) }
|
||||
get :index, params: { limit: 1 }
|
||||
expect(body_as_json.size).to eq 1
|
||||
end
|
||||
|
||||
it 'queries blocks in range according to max_id' do
|
||||
blocks = 2.times.map { Fabricate(:block, account: user.account) }
|
||||
|
||||
get :index, params: { max_id: blocks[1] }
|
||||
|
||||
expect(body_as_json.size).to eq 1
|
||||
expect(body_as_json[0][:id]).to eq blocks[0].target_account_id.to_s
|
||||
end
|
||||
|
||||
it 'queries blocks in range according to since_id' do
|
||||
blocks = 2.times.map { Fabricate(:block, account: user.account) }
|
||||
|
||||
get :index, params: { since_id: blocks[0] }
|
||||
|
||||
expect(body_as_json.size).to eq 1
|
||||
expect(body_as_json[0][:id]).to eq blocks[1].target_account_id.to_s
|
||||
end
|
||||
|
||||
it 'sets pagination header for next path' do
|
||||
blocks = 2.times.map { Fabricate(:block, account: user.account) }
|
||||
get :index, params: { limit: 1, since_id: blocks[0] }
|
||||
expect(response.headers['Link'].find_link(['rel', 'next']).href).to eq api_v1_blocks_url(limit: 1, max_id: blocks[1])
|
||||
end
|
||||
|
||||
it 'sets pagination header for previous path' do
|
||||
block = Fabricate(:block, account: user.account)
|
||||
get :index
|
||||
expect(response.headers['Link'].find_link(['rel', 'prev']).href).to eq api_v1_blocks_url(since_id: block)
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
context 'with wrong scopes' do
|
||||
let(:scopes) { 'write:blocks' }
|
||||
|
||||
it 'returns http forbidden' do
|
||||
get :index
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
37
spec/controllers/api/v1/conversations_controller_spec.rb
Normal file
37
spec/controllers/api/v1/conversations_controller_spec.rb
Normal file
@@ -0,0 +1,37 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::ConversationsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let!(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:other) { Fabricate(:user, account: Fabricate(:account, username: 'bob')) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:scopes) { 'read:statuses' }
|
||||
|
||||
before do
|
||||
PostStatusService.new.call(other.account, text: 'Hey @alice', visibility: 'direct')
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns pagination headers' do
|
||||
get :index, params: { limit: 1 }
|
||||
expect(response.headers['Link'].links.size).to eq(2)
|
||||
end
|
||||
|
||||
it 'returns conversations' do
|
||||
get :index
|
||||
json = body_as_json
|
||||
expect(json.size).to eq 1
|
||||
end
|
||||
end
|
||||
end
|
||||
18
spec/controllers/api/v1/custom_emojis_controller_spec.rb
Normal file
18
spec/controllers/api/v1/custom_emojis_controller_spec.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::CustomEmojisController, type: :controller do
|
||||
render_views
|
||||
|
||||
describe 'GET #index' do
|
||||
before do
|
||||
Fabricate(:custom_emoji)
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
75
spec/controllers/api/v1/domain_blocks_controller_spec.rb
Normal file
75
spec/controllers/api/v1/domain_blocks_controller_spec.rb
Normal file
@@ -0,0 +1,75 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::DomainBlocksController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
before do
|
||||
user.account.block_domain!('example.com')
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||
let(:scopes) { wrong_scope }
|
||||
|
||||
it 'returns http forbidden' do
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:scopes) { 'read:blocks' }
|
||||
|
||||
before do
|
||||
get :show, params: { limit: 1 }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns blocked domains' do
|
||||
expect(body_as_json.first).to eq 'example.com'
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:scopes) { 'write:blocks' }
|
||||
|
||||
before do
|
||||
post :create, params: { domain: 'example.org' }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates a domain block' do
|
||||
expect(user.account.domain_blocking?('example.org')).to be true
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
let(:scopes) { 'write:blocks' }
|
||||
|
||||
before do
|
||||
delete :destroy, params: { domain: 'example.com' }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'deletes a domain block' do
|
||||
expect(user.account.domain_blocking?('example.com')).to be false
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||
end
|
||||
end
|
||||
17
spec/controllers/api/v1/endorsements_controller_spec.rb
Normal file
17
spec/controllers/api/v1/endorsements_controller_spec.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::EndorsementsController, type: :controller do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns 200' do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
get :index
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
78
spec/controllers/api/v1/favourites_controller_spec.rb
Normal file
78
spec/controllers/api/v1/favourites_controller_spec.rb
Normal file
@@ -0,0 +1,78 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::FavouritesController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') }
|
||||
|
||||
describe 'GET #index' do
|
||||
context 'without token' do
|
||||
it 'returns http unauthorized' do
|
||||
get :index
|
||||
expect(response).to have_http_status :unauthorized
|
||||
end
|
||||
end
|
||||
|
||||
context 'with token' do
|
||||
context 'without read scope' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) do
|
||||
Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: '')
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns http forbidden' do
|
||||
get :index
|
||||
expect(response).to have_http_status :forbidden
|
||||
end
|
||||
end
|
||||
|
||||
context 'without valid resource owner' do
|
||||
before do
|
||||
token = Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read')
|
||||
user.destroy!
|
||||
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
it 'returns http unprocessable entity' do
|
||||
get :index
|
||||
expect(response).to have_http_status :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
context 'with read scope and valid resource owner' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) do
|
||||
Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:favourites')
|
||||
end
|
||||
end
|
||||
|
||||
it 'shows favourites owned by the user' do
|
||||
favourite_by_user = Fabricate(:favourite, account: user.account)
|
||||
favourite_by_others = Fabricate(:favourite)
|
||||
|
||||
get :index
|
||||
|
||||
expect(assigns(:statuses)).to match_array [favourite_by_user.status]
|
||||
end
|
||||
|
||||
it 'adds pagination headers if necessary' do
|
||||
favourite = Fabricate(:favourite, account: user.account)
|
||||
|
||||
get :index, params: { limit: 1 }
|
||||
|
||||
expect(response.headers['Link'].find_link(['rel', 'next']).href).to eq "http://test.host/api/v1/favourites?limit=1&max_id=#{favourite.id}"
|
||||
expect(response.headers['Link'].find_link(['rel', 'prev']).href).to eq "http://test.host/api/v1/favourites?limit=1&min_id=#{favourite.id}"
|
||||
end
|
||||
|
||||
it 'does not add pagination headers if not necessary' do
|
||||
get :index
|
||||
|
||||
expect(response.headers['Link']).to eq nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
87
spec/controllers/api/v1/filters_controller_spec.rb
Normal file
87
spec/controllers/api/v1/filters_controller_spec.rb
Normal file
@@ -0,0 +1,87 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::FiltersController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:scopes) { 'read:filters' }
|
||||
let!(:filter) { Fabricate(:custom_filter, account: user.account) }
|
||||
|
||||
it 'returns http success' do
|
||||
get :index
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:scopes) { 'write:filters' }
|
||||
|
||||
before do
|
||||
post :create, params: { phrase: 'magic', context: %w(home), irreversible: true }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates a filter' do
|
||||
filter = user.account.custom_filters.first
|
||||
expect(filter).to_not be_nil
|
||||
expect(filter.phrase).to eq 'magic'
|
||||
expect(filter.context).to eq %w(home)
|
||||
expect(filter.irreversible?).to be true
|
||||
expect(filter.expires_at).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:scopes) { 'read:filters' }
|
||||
let(:filter) { Fabricate(:custom_filter, account: user.account) }
|
||||
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: filter.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
let(:scopes) { 'write:filters' }
|
||||
let(:filter) { Fabricate(:custom_filter, account: user.account) }
|
||||
|
||||
before do
|
||||
put :update, params: { id: filter.id, phrase: 'updated' }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'updates the filter' do
|
||||
expect(filter.reload.phrase).to eq 'updated'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
let(:scopes) { 'write:filters' }
|
||||
let(:filter) { Fabricate(:custom_filter, account: user.account) }
|
||||
|
||||
before do
|
||||
delete :destroy, params: { id: filter.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'removes the filter' do
|
||||
expect { filter.reload }.to raise_error ActiveRecord::RecordNotFound
|
||||
end
|
||||
end
|
||||
end
|
||||
58
spec/controllers/api/v1/follow_requests_controller_spec.rb
Normal file
58
spec/controllers/api/v1/follow_requests_controller_spec.rb
Normal file
@@ -0,0 +1,58 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::FollowRequestsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice', locked: true)) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:follower) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
FollowService.new.call(follower, user.account.acct)
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:scopes) { 'read:follows' }
|
||||
|
||||
before do
|
||||
get :index, params: { limit: 1 }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #authorize' do
|
||||
let(:scopes) { 'write:follows' }
|
||||
|
||||
before do
|
||||
post :authorize, params: { id: follower.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'allows follower to follow' do
|
||||
expect(follower.following?(user.account)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #reject' do
|
||||
let(:scopes) { 'write:follows' }
|
||||
|
||||
before do
|
||||
post :reject, params: { id: follower.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'removes follow request' do
|
||||
expect(FollowRequest.where(target_account: user.account, account: follower).count).to eq 0
|
||||
end
|
||||
end
|
||||
end
|
||||
51
spec/controllers/api/v1/follows_controller_spec.rb
Normal file
51
spec/controllers/api/v1/follows_controller_spec.rb
Normal file
@@ -0,0 +1,51 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::FollowsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:follows') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
before do
|
||||
stub_request(:get, "https://quitter.no/.well-known/host-meta").to_return(request_fixture('.host-meta.txt'))
|
||||
stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:robcolbert@quitter.no").to_return(request_fixture('webfinger.txt'))
|
||||
stub_request(:head, "https://quitter.no/api/statuses/user_timeline/7477.atom").to_return(:status => 405, :body => "", :headers => {})
|
||||
stub_request(:get, "https://quitter.no/api/statuses/user_timeline/7477.atom").to_return(request_fixture('feed.txt'))
|
||||
stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt'))
|
||||
stub_request(:post, "https://quitter.no/main/push/hub").to_return(:status => 200, :body => "", :headers => {})
|
||||
stub_request(:post, "https://quitter.no/main/salmon/user/7477").to_return(:status => 200, :body => "", :headers => {})
|
||||
|
||||
post :create, params: { uri: 'robcolbert@quitter.no' }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates account for remote user' do
|
||||
expect(Account.find_by(username: 'robcolbert', domain: 'quitter.no')).to_not be_nil
|
||||
end
|
||||
|
||||
it 'creates a follow relation between user and remote user' do
|
||||
expect(user.account.following?(Account.find_by(username: 'robcolbert', domain: 'quitter.no'))).to be true
|
||||
end
|
||||
|
||||
it 'sends a salmon slap to the remote user' do
|
||||
expect(a_request(:post, "https://quitter.no/main/salmon/user/7477")).to have_been_made
|
||||
end
|
||||
|
||||
it 'subscribes to remote hub' do
|
||||
expect(a_request(:post, "https://quitter.no/main/push/hub")).to have_been_made
|
||||
end
|
||||
|
||||
it 'returns http success if already following, too' do
|
||||
post :create, params: { uri: 'robcolbert@quitter.no' }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Instances::ActivityController, type: :controller do
|
||||
describe 'GET #show' do
|
||||
it 'returns 200' do
|
||||
get :show
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
context '!Setting.activity_api_enabled' do
|
||||
it 'returns 404' do
|
||||
Setting.activity_api_enabled = false
|
||||
|
||||
get :show
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
21
spec/controllers/api/v1/instances/peers_controller_spec.rb
Normal file
21
spec/controllers/api/v1/instances/peers_controller_spec.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Instances::PeersController, type: :controller do
|
||||
describe 'GET #index' do
|
||||
it 'returns 200' do
|
||||
get :index
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
context '!Setting.peers_api_enabled' do
|
||||
it 'returns 404' do
|
||||
Setting.peers_api_enabled = false
|
||||
|
||||
get :index
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
22
spec/controllers/api/v1/instances_controller_spec.rb
Normal file
22
spec/controllers/api/v1/instances_controller_spec.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::InstancesController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
get :show
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
59
spec/controllers/api/v1/lists/accounts_controller_spec.rb
Normal file
59
spec/controllers/api/v1/lists/accounts_controller_spec.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Lists::AccountsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:list) { Fabricate(:list, account: user.account) }
|
||||
|
||||
before do
|
||||
follow = Fabricate(:follow, account: user.account)
|
||||
list.accounts << follow.target_account
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:scopes) { 'read:lists' }
|
||||
|
||||
it 'returns http success' do
|
||||
get :show, params: { list_id: list.id }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:scopes) { 'write:lists' }
|
||||
let(:bob) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
user.account.follow!(bob)
|
||||
post :create, params: { list_id: list.id, account_ids: [bob.id] }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'adds account to the list' do
|
||||
expect(list.accounts.include?(bob)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
let(:scopes) { 'write:lists' }
|
||||
|
||||
before do
|
||||
delete :destroy, params: { list_id: list.id, account_ids: [list.accounts.first.id] }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'removes account from the list' do
|
||||
expect(list.accounts.count).to eq 0
|
||||
end
|
||||
end
|
||||
end
|
||||
78
spec/controllers/api/v1/lists_controller_spec.rb
Normal file
78
spec/controllers/api/v1/lists_controller_spec.rb
Normal file
@@ -0,0 +1,78 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::ListsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let!(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let!(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let!(:list) { Fabricate(:list, account: user.account) }
|
||||
|
||||
before { allow(controller).to receive(:doorkeeper_token) { token } }
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:scopes) { 'read:lists' }
|
||||
|
||||
it 'returns http success' do
|
||||
get :index
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:scopes) { 'read:lists' }
|
||||
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: list.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:scopes) { 'write:lists' }
|
||||
|
||||
before do
|
||||
post :create, params: { title: 'Foo bar' }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates list' do
|
||||
expect(List.where(account: user.account).count).to eq 2
|
||||
expect(List.last.title).to eq 'Foo bar'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
let(:scopes) { 'write:lists' }
|
||||
|
||||
before do
|
||||
put :update, params: { id: list.id, title: 'Updated title' }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'updates the list' do
|
||||
expect(list.reload.title).to eq 'Updated title'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
let(:scopes) { 'write:lists' }
|
||||
|
||||
before do
|
||||
delete :destroy, params: { id: list.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'deletes the list' do
|
||||
expect(List.find_by(id: list.id)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
131
spec/controllers/api/v1/media_controller_spec.rb
Normal file
131
spec/controllers/api/v1/media_controller_spec.rb
Normal file
@@ -0,0 +1,131 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::MediaController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:media') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
describe 'with paperclip errors' do
|
||||
context 'when imagemagick cant identify the file type' do
|
||||
before do
|
||||
expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Errors::NotIdentifiedByImageMagickError)
|
||||
post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
|
||||
end
|
||||
|
||||
it 'returns http 422' do
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is a generic error' do
|
||||
before do
|
||||
expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Error)
|
||||
post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
|
||||
end
|
||||
|
||||
it 'returns http 422' do
|
||||
expect(response).to have_http_status(500)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'image/jpeg' do
|
||||
before do
|
||||
post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates a media attachment' do
|
||||
expect(MediaAttachment.first).to_not be_nil
|
||||
end
|
||||
|
||||
it 'uploads a file' do
|
||||
expect(MediaAttachment.first).to have_attached_file(:file)
|
||||
end
|
||||
|
||||
it 'returns media ID in JSON' do
|
||||
expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
|
||||
end
|
||||
end
|
||||
|
||||
context 'image/gif' do
|
||||
before do
|
||||
post :create, params: { file: fixture_file_upload('files/attachment.gif', 'image/gif') }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates a media attachment' do
|
||||
expect(MediaAttachment.first).to_not be_nil
|
||||
end
|
||||
|
||||
it 'uploads a file' do
|
||||
expect(MediaAttachment.first).to have_attached_file(:file)
|
||||
end
|
||||
|
||||
it 'returns media ID in JSON' do
|
||||
expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
|
||||
end
|
||||
end
|
||||
|
||||
context 'video/webm' do
|
||||
before do
|
||||
post :create, params: { file: fixture_file_upload('files/attachment.webm', 'video/webm') }
|
||||
end
|
||||
|
||||
it do
|
||||
# returns http success
|
||||
expect(response).to have_http_status(200)
|
||||
|
||||
# creates a media attachment
|
||||
expect(MediaAttachment.first).to_not be_nil
|
||||
|
||||
# uploads a file
|
||||
expect(MediaAttachment.first).to have_attached_file(:file)
|
||||
|
||||
# returns media ID in JSON
|
||||
expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
context 'when somebody else\'s' do
|
||||
let(:media) { Fabricate(:media_attachment, status: nil) }
|
||||
|
||||
it 'returns http not found' do
|
||||
put :update, params: { id: media.id, description: 'Lorem ipsum!!!' }
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not attached to a status' do
|
||||
let(:media) { Fabricate(:media_attachment, status: nil, account: user.account) }
|
||||
|
||||
it 'updates the description' do
|
||||
put :update, params: { id: media.id, description: 'Lorem ipsum!!!' }
|
||||
expect(media.reload.description).to eq 'Lorem ipsum!!!'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when attached to a status' do
|
||||
let(:media) { Fabricate(:media_attachment, status: Fabricate(:status), account: user.account) }
|
||||
|
||||
it 'returns http not found' do
|
||||
put :update, params: { id: media.id, description: 'Lorem ipsum!!!' }
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
63
spec/controllers/api/v1/mutes_controller_spec.rb
Normal file
63
spec/controllers/api/v1/mutes_controller_spec.rb
Normal file
@@ -0,0 +1,63 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::MutesController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:scopes) { 'read:mutes' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
before { allow(controller).to receive(:doorkeeper_token) { token } }
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'limits according to limit parameter' do
|
||||
2.times.map { Fabricate(:mute, account: user.account) }
|
||||
get :index, params: { limit: 1 }
|
||||
expect(body_as_json.size).to eq 1
|
||||
end
|
||||
|
||||
it 'queries mutes in range according to max_id' do
|
||||
mutes = 2.times.map { Fabricate(:mute, account: user.account) }
|
||||
|
||||
get :index, params: { max_id: mutes[1] }
|
||||
|
||||
expect(body_as_json.size).to eq 1
|
||||
expect(body_as_json[0][:id]).to eq mutes[0].target_account_id.to_s
|
||||
end
|
||||
|
||||
it 'queries mutes in range according to since_id' do
|
||||
mutes = 2.times.map { Fabricate(:mute, account: user.account) }
|
||||
|
||||
get :index, params: { since_id: mutes[0] }
|
||||
|
||||
expect(body_as_json.size).to eq 1
|
||||
expect(body_as_json[0][:id]).to eq mutes[1].target_account_id.to_s
|
||||
end
|
||||
|
||||
it 'sets pagination header for next path' do
|
||||
mutes = 2.times.map { Fabricate(:mute, account: user.account) }
|
||||
get :index, params: { limit: 1, since_id: mutes[0] }
|
||||
expect(response.headers['Link'].find_link(['rel', 'next']).href).to eq api_v1_mutes_url(limit: 1, max_id: mutes[1])
|
||||
end
|
||||
|
||||
it 'sets pagination header for previous path' do
|
||||
mute = Fabricate(:mute, account: user.account)
|
||||
get :index
|
||||
expect(response.headers['Link'].find_link(['rel', 'prev']).href).to eq api_v1_mutes_url(since_id: mute)
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
context 'with wrong scopes' do
|
||||
let(:scopes) { 'write:mutes' }
|
||||
|
||||
it 'returns http forbidden' do
|
||||
get :index
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
179
spec/controllers/api/v1/notifications_controller_spec.rb
Normal file
179
spec/controllers/api/v1/notifications_controller_spec.rb
Normal file
@@ -0,0 +1,179 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::NotificationsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:other) { Fabricate(:user, account: Fabricate(:account, username: 'bob')) }
|
||||
let(:third) { Fabricate(:user, account: Fabricate(:account, username: 'carol')) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:scopes) { 'read:notifications' }
|
||||
|
||||
it 'returns http success' do
|
||||
notification = Fabricate(:notification, account: user.account)
|
||||
get :show, params: { id: notification.id }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #dismiss' do
|
||||
let(:scopes) { 'write:notifications' }
|
||||
|
||||
it 'destroys the notification' do
|
||||
notification = Fabricate(:notification, account: user.account)
|
||||
post :dismiss, params: { id: notification.id }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect { notification.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #clear' do
|
||||
let(:scopes) { 'write:notifications' }
|
||||
|
||||
it 'clears notifications for the account' do
|
||||
notification = Fabricate(:notification, account: user.account)
|
||||
post :clear
|
||||
|
||||
expect(notification.account.reload.notifications).to be_empty
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:scopes) { 'read:notifications' }
|
||||
|
||||
before do
|
||||
first_status = PostStatusService.new.call(user.account, text: 'Test')
|
||||
@reblog_of_first_status = ReblogService.new.call(other.account, first_status)
|
||||
mentioning_status = PostStatusService.new.call(other.account, text: 'Hello @alice')
|
||||
@mention_from_status = mentioning_status.mentions.first
|
||||
@favourite = FavouriteService.new.call(other.account, first_status)
|
||||
@second_favourite = FavouriteService.new.call(third.account, first_status)
|
||||
@follow = FollowService.new.call(other.account, 'alice')
|
||||
end
|
||||
|
||||
describe 'with no options' do
|
||||
before do
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'includes reblog' do
|
||||
expect(assigns(:notifications).map(&:activity)).to include(@reblog_of_first_status)
|
||||
end
|
||||
|
||||
it 'includes mention' do
|
||||
expect(assigns(:notifications).map(&:activity)).to include(@mention_from_status)
|
||||
end
|
||||
|
||||
it 'includes favourite' do
|
||||
expect(assigns(:notifications).map(&:activity)).to include(@favourite)
|
||||
end
|
||||
|
||||
it 'includes follow' do
|
||||
expect(assigns(:notifications).map(&:activity)).to include(@follow)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'from specified user' do
|
||||
before do
|
||||
get :index, params: { account_id: third.account.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'includes favourite' do
|
||||
expect(assigns(:notifications).map(&:activity)).to include(@second_favourite)
|
||||
end
|
||||
|
||||
it 'excludes favourite' do
|
||||
expect(assigns(:notifications).map(&:activity)).to_not include(@favourite)
|
||||
end
|
||||
|
||||
it 'excludes mention' do
|
||||
expect(assigns(:notifications).map(&:activity)).to_not include(@mention_from_status)
|
||||
end
|
||||
|
||||
it 'excludes reblog' do
|
||||
expect(assigns(:notifications).map(&:activity)).to_not include(@reblog_of_first_status)
|
||||
end
|
||||
|
||||
it 'excludes follow' do
|
||||
expect(assigns(:notifications).map(&:activity)).to_not include(@follow)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'from nonexistent user' do
|
||||
before do
|
||||
get :index, params: { account_id: 'foo' }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'excludes favourite' do
|
||||
expect(assigns(:notifications).map(&:activity)).to_not include(@favourite)
|
||||
end
|
||||
|
||||
it 'excludes second favourite' do
|
||||
expect(assigns(:notifications).map(&:activity)).to_not include(@second_favourite)
|
||||
end
|
||||
|
||||
it 'excludes mention' do
|
||||
expect(assigns(:notifications).map(&:activity)).to_not include(@mention_from_status)
|
||||
end
|
||||
|
||||
it 'excludes reblog' do
|
||||
expect(assigns(:notifications).map(&:activity)).to_not include(@reblog_of_first_status)
|
||||
end
|
||||
|
||||
it 'excludes follow' do
|
||||
expect(assigns(:notifications).map(&:activity)).to_not include(@follow)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with excluded mentions' do
|
||||
before do
|
||||
get :index, params: { exclude_types: ['mention'] }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'includes reblog' do
|
||||
expect(assigns(:notifications).map(&:activity)).to include(@reblog_of_first_status)
|
||||
end
|
||||
|
||||
it 'excludes mention' do
|
||||
expect(assigns(:notifications).map(&:activity)).to_not include(@mention_from_status)
|
||||
end
|
||||
|
||||
it 'includes favourite' do
|
||||
expect(assigns(:notifications).map(&:activity)).to include(@favourite)
|
||||
end
|
||||
|
||||
it 'includes third favourite' do
|
||||
expect(assigns(:notifications).map(&:activity)).to include(@second_favourite)
|
||||
end
|
||||
|
||||
it 'includes follow' do
|
||||
expect(assigns(:notifications).map(&:activity)).to include(@follow)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
34
spec/controllers/api/v1/polls/votes_controller_spec.rb
Normal file
34
spec/controllers/api/v1/polls/votes_controller_spec.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Polls::VotesController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:scopes) { 'write:statuses' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
before { allow(controller).to receive(:doorkeeper_token) { token } }
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:poll) { Fabricate(:poll) }
|
||||
|
||||
before do
|
||||
post :create, params: { poll_id: poll.id, choices: %w(1) }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates a vote' do
|
||||
vote = poll.votes.where(account: user.account).first
|
||||
|
||||
expect(vote).to_not be_nil
|
||||
expect(vote.choice).to eq 1
|
||||
end
|
||||
|
||||
it 'updates poll tallies' do
|
||||
expect(poll.reload.cached_tallies).to eq [0, 1]
|
||||
end
|
||||
end
|
||||
end
|
||||
23
spec/controllers/api/v1/polls_controller_spec.rb
Normal file
23
spec/controllers/api/v1/polls_controller_spec.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::PollsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:scopes) { 'read:statuses' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
before { allow(controller).to receive(:doorkeeper_token) { token } }
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:poll) { Fabricate(:poll) }
|
||||
|
||||
before do
|
||||
get :show, params: { id: poll.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,83 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Push::SubscriptionsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'push') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
let(:create_payload) do
|
||||
{
|
||||
subscription: {
|
||||
endpoint: 'https://fcm.googleapis.com/fcm/send/fiuH06a27qE:APA91bHnSiGcLwdaxdyqVXNDR9w1NlztsHb6lyt5WDKOC_Z_Q8BlFxQoR8tWFSXUIDdkyw0EdvxTu63iqamSaqVSevW5LfoFwojws8XYDXv_NRRLH6vo2CdgiN4jgHv5VLt2A8ah6lUX',
|
||||
keys: {
|
||||
p256dh: 'BEm_a0bdPDhf0SOsrnB2-ategf1hHoCnpXgQsFj5JCkcoMrMt2WHoPfEYOYPzOIs9mZE8ZUaD7VA5vouy0kEkr8=',
|
||||
auth: 'eH_C8rq2raXqlcBVDa1gLg==',
|
||||
},
|
||||
}
|
||||
}.with_indifferent_access
|
||||
end
|
||||
|
||||
let(:alerts_payload) do
|
||||
{
|
||||
data: {
|
||||
alerts: {
|
||||
follow: true,
|
||||
favourite: false,
|
||||
reblog: true,
|
||||
mention: false,
|
||||
}
|
||||
}
|
||||
}.with_indifferent_access
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
it 'saves push subscriptions' do
|
||||
post :create, params: create_payload
|
||||
|
||||
push_subscription = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])
|
||||
|
||||
expect(push_subscription.endpoint).to eq(create_payload[:subscription][:endpoint])
|
||||
expect(push_subscription.key_p256dh).to eq(create_payload[:subscription][:keys][:p256dh])
|
||||
expect(push_subscription.key_auth).to eq(create_payload[:subscription][:keys][:auth])
|
||||
expect(push_subscription.user_id).to eq user.id
|
||||
expect(push_subscription.access_token_id).to eq token.id
|
||||
end
|
||||
|
||||
it 'replaces old subscription on repeat calls' do
|
||||
post :create, params: create_payload
|
||||
post :create, params: create_payload
|
||||
|
||||
expect(Web::PushSubscription.where(endpoint: create_payload[:subscription][:endpoint]).count).to eq 1
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
it 'changes alert settings' do
|
||||
post :create, params: create_payload
|
||||
put :update, params: alerts_payload
|
||||
|
||||
push_subscription = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])
|
||||
|
||||
expect(push_subscription.data.dig('alerts', 'follow')).to eq(alerts_payload[:data][:alerts][:follow].to_s)
|
||||
expect(push_subscription.data.dig('alerts', 'favourite')).to eq(alerts_payload[:data][:alerts][:favourite].to_s)
|
||||
expect(push_subscription.data.dig('alerts', 'reblog')).to eq(alerts_payload[:data][:alerts][:reblog].to_s)
|
||||
expect(push_subscription.data.dig('alerts', 'mention')).to eq(alerts_payload[:data][:alerts][:mention].to_s)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
it 'removes the subscription' do
|
||||
post :create, params: create_payload
|
||||
delete :destroy
|
||||
|
||||
expect(Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
34
spec/controllers/api/v1/reports_controller_spec.rb
Normal file
34
spec/controllers/api/v1/reports_controller_spec.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::ReportsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:scopes) { 'write:reports' }
|
||||
let!(:status) { Fabricate(:status) }
|
||||
let!(:admin) { Fabricate(:user, admin: true) }
|
||||
|
||||
before do
|
||||
allow(AdminMailer).to receive(:new_report).and_return(double('email', deliver_later: nil))
|
||||
post :create, params: { status_ids: [status.id], account_id: status.account.id, comment: 'reasons' }
|
||||
end
|
||||
|
||||
it 'creates a report' do
|
||||
expect(status.reload.account.targeted_reports).not_to be_empty
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'sends e-mails to admins' do
|
||||
expect(AdminMailer).to have_received(:new_report).with(admin.account, Report)
|
||||
end
|
||||
end
|
||||
end
|
||||
22
spec/controllers/api/v1/search_controller_spec.rb
Normal file
22
spec/controllers/api/v1/search_controller_spec.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::SearchController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:search') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { q: 'test' }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,65 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Statuses::FavouritedByAccountsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
Fabricate(:favourite, status: status)
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: { status_id: status.id, limit: 1 }
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size).to eq(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { nil }
|
||||
end
|
||||
|
||||
context 'with a private status' do
|
||||
let(:status) { Fabricate(:status, account: user.account, visibility: :private) }
|
||||
|
||||
describe 'GET #index' do
|
||||
before do
|
||||
Fabricate(:favourite, status: status)
|
||||
end
|
||||
|
||||
it 'returns http unautharized' do
|
||||
get :index, params: { status_id: status.id }
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a public status' do
|
||||
let(:status) { Fabricate(:status, account: user.account, visibility: :public) }
|
||||
|
||||
describe 'GET #index' do
|
||||
before do
|
||||
Fabricate(:favourite, status: status)
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: { status_id: status.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,66 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Statuses::FavouritesController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:favourites', application: app) }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
post :create, params: { status_id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'updates the favourites count' do
|
||||
expect(status.favourites.count).to eq 1
|
||||
end
|
||||
|
||||
it 'updates the favourited attribute' do
|
||||
expect(user.account.favourited?(status)).to be true
|
||||
end
|
||||
|
||||
it 'return json with updated attributes' do
|
||||
hash_body = body_as_json
|
||||
|
||||
expect(hash_body[:id]).to eq status.id.to_s
|
||||
expect(hash_body[:favourites_count]).to eq 1
|
||||
expect(hash_body[:favourited]).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #destroy' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
FavouriteService.new.call(user.account, status)
|
||||
post :destroy, params: { status_id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'updates the favourites count' do
|
||||
expect(status.favourites.count).to eq 0
|
||||
end
|
||||
|
||||
it 'updates the favourited attribute' do
|
||||
expect(user.account.favourited?(status)).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
50
spec/controllers/api/v1/statuses/mutes_controller_spec.rb
Normal file
50
spec/controllers/api/v1/statuses/mutes_controller_spec.rb
Normal file
@@ -0,0 +1,50 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Statuses::MutesController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:mutes', application: app) }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
post :create, params: { status_id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates a conversation mute' do
|
||||
expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #destroy' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
user.account.mute_conversation!(status.conversation)
|
||||
post :destroy, params: { status_id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'destroys the conversation mute' do
|
||||
expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
57
spec/controllers/api/v1/statuses/pins_controller_spec.rb
Normal file
57
spec/controllers/api/v1/statuses/pins_controller_spec.rb
Normal file
@@ -0,0 +1,57 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Statuses::PinsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:accounts', application: app) }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
post :create, params: { status_id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'updates the pinned attribute' do
|
||||
expect(user.account.pinned?(status)).to be true
|
||||
end
|
||||
|
||||
it 'return json with updated attributes' do
|
||||
hash_body = body_as_json
|
||||
|
||||
expect(hash_body[:id]).to eq status.id.to_s
|
||||
expect(hash_body[:pinned]).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #destroy' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
Fabricate(:status_pin, status: status, account: user.account)
|
||||
post :destroy, params: { status_id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'updates the pinned attribute' do
|
||||
expect(user.account.pinned?(status)).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,65 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Statuses::RebloggedByAccountsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
Fabricate(:status, reblog_of_id: status.id)
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: { status_id: status.id, limit: 1 }
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size).to eq(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { nil }
|
||||
end
|
||||
|
||||
context 'with a private status' do
|
||||
let(:status) { Fabricate(:status, account: user.account, visibility: :private) }
|
||||
|
||||
describe 'GET #index' do
|
||||
before do
|
||||
Fabricate(:status, reblog_of_id: status.id)
|
||||
end
|
||||
|
||||
it 'returns http unautharized' do
|
||||
get :index, params: { status_id: status.id }
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a public status' do
|
||||
let(:status) { Fabricate(:status, account: user.account, visibility: :public) }
|
||||
|
||||
describe 'GET #index' do
|
||||
before do
|
||||
Fabricate(:status, reblog_of_id: status.id)
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: { status_id: status.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
66
spec/controllers/api/v1/statuses/reblogs_controller_spec.rb
Normal file
66
spec/controllers/api/v1/statuses/reblogs_controller_spec.rb
Normal file
@@ -0,0 +1,66 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Statuses::ReblogsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:statuses', application: app) }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
post :create, params: { status_id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'updates the reblogs count' do
|
||||
expect(status.reblogs.count).to eq 1
|
||||
end
|
||||
|
||||
it 'updates the reblogged attribute' do
|
||||
expect(user.account.reblogged?(status)).to be true
|
||||
end
|
||||
|
||||
it 'return json with updated attributes' do
|
||||
hash_body = body_as_json
|
||||
|
||||
expect(hash_body[:reblog][:id]).to eq status.id.to_s
|
||||
expect(hash_body[:reblog][:reblogs_count]).to eq 1
|
||||
expect(hash_body[:reblog][:reblogged]).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #destroy' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
ReblogService.new.call(user.account, status)
|
||||
post :destroy, params: { status_id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'updates the reblogs count' do
|
||||
expect(status.reblogs.count).to eq 0
|
||||
end
|
||||
|
||||
it 'updates the reblogged attribute' do
|
||||
expect(user.account.reblogged?(status)).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
132
spec/controllers/api/v1/statuses_controller_spec.rb
Normal file
132
spec/controllers/api/v1/statuses_controller_spec.rb
Normal file
@@ -0,0 +1,132 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::StatusesController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: scopes) }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:scopes) { 'read:statuses' }
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: status.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #context' do
|
||||
let(:scopes) { 'read:statuses' }
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
Fabricate(:status, account: user.account, thread: status)
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :context, params: { id: status.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:scopes) { 'write:statuses' }
|
||||
|
||||
before do
|
||||
post :create, params: { status: 'Hello world' }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
let(:scopes) { 'write:statuses' }
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
post :destroy, params: { id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'removes the status' do
|
||||
expect(Status.find_by(id: status.id)).to be nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { nil }
|
||||
end
|
||||
|
||||
context 'with a private status' do
|
||||
let(:status) { Fabricate(:status, account: user.account, visibility: :private) }
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http unautharized' do
|
||||
get :show, params: { id: status.id }
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #context' do
|
||||
before do
|
||||
Fabricate(:status, account: user.account, thread: status)
|
||||
end
|
||||
|
||||
it 'returns http unautharized' do
|
||||
get :context, params: { id: status.id }
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #card' do
|
||||
it 'returns http unautharized' do
|
||||
get :card, params: { id: status.id }
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a public status' do
|
||||
let(:status) { Fabricate(:status, account: user.account, visibility: :public) }
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: status.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #context' do
|
||||
before do
|
||||
Fabricate(:status, account: user.account, thread: status)
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :context, params: { id: status.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #card' do
|
||||
it 'returns http success' do
|
||||
get :card, params: { id: status.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
45
spec/controllers/api/v1/streaming_controller_spec.rb
Normal file
45
spec/controllers/api/v1/streaming_controller_spec.rb
Normal file
@@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::StreamingController do
|
||||
around(:each) do |example|
|
||||
before = Rails.configuration.x.streaming_api_base_url
|
||||
Rails.configuration.x.streaming_api_base_url = Rails.configuration.x.web_domain
|
||||
example.run
|
||||
Rails.configuration.x.streaming_api_base_url = before
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
request.headers.merge! Host: Rails.configuration.x.web_domain
|
||||
end
|
||||
|
||||
context 'with streaming api on same host' do
|
||||
describe 'GET #index' do
|
||||
it 'raises ActiveRecord::RecordNotFound' do
|
||||
get :index
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with streaming api on different host' do
|
||||
before(:each) do
|
||||
Rails.configuration.x.streaming_api_base_url = 'wss://streaming-' + Rails.configuration.x.web_domain
|
||||
@streaming_host = URI.parse(Rails.configuration.x.streaming_api_base_url).host
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'redirects to streaming host' do
|
||||
get :index, params: { access_token: 'deadbeef', stream: 'public' }
|
||||
expect(response).to have_http_status(301)
|
||||
request_uri = URI.parse(request.url)
|
||||
redirect_to_uri = URI.parse(response.location)
|
||||
[:scheme, :path, :query, :fragment].each do |part|
|
||||
expect(redirect_to_uri.send(part)).to eq(request_uri.send(part)), "redirect target #{part}"
|
||||
end
|
||||
expect(redirect_to_uri.host).to eq(@streaming_host), "redirect target host"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
35
spec/controllers/api/v1/suggestions_controller_spec.rb
Normal file
35
spec/controllers/api/v1/suggestions_controller_spec.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::SuggestionsController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read write') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:bob) { Fabricate(:account) }
|
||||
let(:jeff) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
PotentialFriendshipTracker.record(user.account_id, bob.id, :reblog)
|
||||
PotentialFriendshipTracker.record(user.account_id, jeff.id, :favourite)
|
||||
|
||||
get :index
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns accounts' do
|
||||
json = body_as_json
|
||||
|
||||
expect(json.size).to be >= 1
|
||||
expect(json.map { |i| i[:id] }).to include *[bob, jeff].map { |i| i.id.to_s }
|
||||
end
|
||||
end
|
||||
end
|
||||
17
spec/controllers/api/v1/timelines/direct_controller_spec.rb
Normal file
17
spec/controllers/api/v1/timelines/direct_controller_spec.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Timelines::DirectController, type: :controller do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns 200' do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
get :show
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
44
spec/controllers/api/v1/timelines/home_controller_spec.rb
Normal file
44
spec/controllers/api/v1/timelines/home_controller_spec.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Timelines::HomeController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice'), current_sign_in_at: 1.day.ago) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
context 'with a user context' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }
|
||||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
follow = Fabricate(:follow, account: user.account)
|
||||
PostStatusService.new.call(follow.target_account, text: 'New status for user home timeline.')
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :show
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size).to eq(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without a user context' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: 'read') }
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http unprocessable entity' do
|
||||
get :show
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(response.headers['Link']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
56
spec/controllers/api/v1/timelines/list_controller_spec.rb
Normal file
56
spec/controllers/api/v1/timelines/list_controller_spec.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Timelines::ListController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:list) { Fabricate(:list, account: user.account) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
context 'with a user context' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:lists') }
|
||||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
follow = Fabricate(:follow, account: user.account)
|
||||
list.accounts << follow.target_account
|
||||
PostStatusService.new.call(follow.target_account, text: 'New status for user home timeline.')
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: list.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with the wrong user context' do
|
||||
let(:other_user) { Fabricate(:user, account: Fabricate(:account, username: 'bob')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: other_user.id, scopes: 'read') }
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http not found' do
|
||||
get :show, params: { id: list.id }
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without a user context' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: 'read') }
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http unprocessable entity' do
|
||||
get :show, params: { id: list.id }
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(response.headers['Link']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
56
spec/controllers/api/v1/timelines/public_controller_spec.rb
Normal file
56
spec/controllers/api/v1/timelines/public_controller_spec.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Timelines::PublicController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
context 'with a user context' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
|
||||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
PostStatusService.new.call(user.account, text: 'New status from user for federated public timeline.')
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :show
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size).to eq(2)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show with local only' do
|
||||
before do
|
||||
PostStatusService.new.call(user.account, text: 'New status from user for local public timeline.')
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :show, params: { local: true }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size).to eq(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without a user context' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil) }
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
get :show
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
41
spec/controllers/api/v1/timelines/tag_controller_spec.rb
Normal file
41
spec/controllers/api/v1/timelines/tag_controller_spec.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Timelines::TagController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
context 'with a user context' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
|
||||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
PostStatusService.new.call(user.account, text: 'It is a #test')
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: 'test' }
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size).to eq(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without a user context' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil) }
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: 'test' }
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
22
spec/controllers/api/v2/search_controller_spec.rb
Normal file
22
spec/controllers/api/v2/search_controller_spec.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V2::SearchController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:search') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { q: 'test' }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
52
spec/controllers/api/web/embeds_controller_spec.rb
Normal file
52
spec/controllers/api/web/embeds_controller_spec.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::Web::EmbedsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
before { sign_in user }
|
||||
|
||||
describe 'POST #create' do
|
||||
subject(:response) { post :create, params: { url: url } }
|
||||
subject(:body) { JSON.parse(response.body, symbolize_names: true) }
|
||||
|
||||
context 'when successfully finds status' do
|
||||
let(:status) { Fabricate(:status) }
|
||||
let(:url) { "http://#{Rails.configuration.x.web_domain}/@#{status.account.username}/#{status.id}" }
|
||||
|
||||
it 'returns a right response' do
|
||||
expect(response).to have_http_status :ok
|
||||
expect(body[:author_name]).to eq status.account.username
|
||||
end
|
||||
end
|
||||
|
||||
context 'when fails to find status' do
|
||||
let(:url) { 'https://host.test/oembed.html' }
|
||||
let(:service_instance) { double('fetch_oembed_service') }
|
||||
|
||||
before do
|
||||
allow(FetchOEmbedService).to receive(:new) { service_instance }
|
||||
allow(service_instance).to receive(:call) { call_result }
|
||||
end
|
||||
|
||||
context 'when successfully fetching oembed' do
|
||||
let(:call_result) { { result: :ok } }
|
||||
|
||||
it 'returns a right response' do
|
||||
expect(response).to have_http_status :ok
|
||||
expect(body[:result]).to eq 'ok'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when fails to fetch oembed' do
|
||||
let(:call_result) { nil }
|
||||
|
||||
it 'returns a right response' do
|
||||
expect(response).to have_http_status :not_found
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,90 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::Web::PushSubscriptionsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
let(:create_payload) do
|
||||
{
|
||||
subscription: {
|
||||
endpoint: 'https://fcm.googleapis.com/fcm/send/fiuH06a27qE:APA91bHnSiGcLwdaxdyqVXNDR9w1NlztsHb6lyt5WDKOC_Z_Q8BlFxQoR8tWFSXUIDdkyw0EdvxTu63iqamSaqVSevW5LfoFwojws8XYDXv_NRRLH6vo2CdgiN4jgHv5VLt2A8ah6lUX',
|
||||
keys: {
|
||||
p256dh: 'BEm_a0bdPDhf0SOsrnB2-ategf1hHoCnpXgQsFj5JCkcoMrMt2WHoPfEYOYPzOIs9mZE8ZUaD7VA5vouy0kEkr8=',
|
||||
auth: 'eH_C8rq2raXqlcBVDa1gLg==',
|
||||
},
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
let(:alerts_payload) do
|
||||
{
|
||||
data: {
|
||||
alerts: {
|
||||
follow: true,
|
||||
favourite: false,
|
||||
reblog: true,
|
||||
mention: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
it 'saves push subscriptions' do
|
||||
sign_in(user)
|
||||
|
||||
stub_request(:post, create_payload[:subscription][:endpoint]).to_return(status: 200)
|
||||
|
||||
post :create, format: :json, params: create_payload
|
||||
|
||||
user.reload
|
||||
|
||||
push_subscription = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])
|
||||
|
||||
expect(push_subscription['endpoint']).to eq(create_payload[:subscription][:endpoint])
|
||||
expect(push_subscription['key_p256dh']).to eq(create_payload[:subscription][:keys][:p256dh])
|
||||
expect(push_subscription['key_auth']).to eq(create_payload[:subscription][:keys][:auth])
|
||||
end
|
||||
|
||||
context 'with initial data' do
|
||||
it 'saves alert settings' do
|
||||
sign_in(user)
|
||||
|
||||
stub_request(:post, create_payload[:subscription][:endpoint]).to_return(status: 200)
|
||||
|
||||
post :create, format: :json, params: create_payload.merge(alerts_payload)
|
||||
|
||||
push_subscription = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])
|
||||
|
||||
expect(push_subscription.data['alerts']['follow']).to eq(alerts_payload[:data][:alerts][:follow].to_s)
|
||||
expect(push_subscription.data['alerts']['favourite']).to eq(alerts_payload[:data][:alerts][:favourite].to_s)
|
||||
expect(push_subscription.data['alerts']['reblog']).to eq(alerts_payload[:data][:alerts][:reblog].to_s)
|
||||
expect(push_subscription.data['alerts']['mention']).to eq(alerts_payload[:data][:alerts][:mention].to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
it 'changes alert settings' do
|
||||
sign_in(user)
|
||||
|
||||
stub_request(:post, create_payload[:subscription][:endpoint]).to_return(status: 200)
|
||||
|
||||
post :create, format: :json, params: create_payload
|
||||
|
||||
alerts_payload[:id] = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint]).id
|
||||
|
||||
put :update, format: :json, params: alerts_payload
|
||||
|
||||
push_subscription = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])
|
||||
|
||||
expect(push_subscription.data['alerts']['follow']).to eq(alerts_payload[:data][:alerts][:follow].to_s)
|
||||
expect(push_subscription.data['alerts']['favourite']).to eq(alerts_payload[:data][:alerts][:favourite].to_s)
|
||||
expect(push_subscription.data['alerts']['reblog']).to eq(alerts_payload[:data][:alerts][:reblog].to_s)
|
||||
expect(push_subscription.data['alerts']['mention']).to eq(alerts_payload[:data][:alerts][:mention].to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
24
spec/controllers/api/web/settings_controller_spec.rb
Normal file
24
spec/controllers/api/web/settings_controller_spec.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::Web::SettingsController do
|
||||
render_views
|
||||
|
||||
let!(:user) { Fabricate(:user) }
|
||||
|
||||
describe 'PATCH #update' do
|
||||
it 'redirects to about page' do
|
||||
sign_in(user)
|
||||
patch :update, format: :json, params: { data: { 'onboarded' => true } }
|
||||
|
||||
user.reload
|
||||
expect(response).to have_http_status(200)
|
||||
expect(user_web_setting.data['onboarded']).to eq('true')
|
||||
end
|
||||
|
||||
def user_web_setting
|
||||
Web::Setting.where(user: user).first
|
||||
end
|
||||
end
|
||||
end
|
||||
368
spec/controllers/application_controller_spec.rb
Normal file
368
spec/controllers/application_controller_spec.rb
Normal file
@@ -0,0 +1,368 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ApplicationController, type: :controller do
|
||||
controller do
|
||||
def success
|
||||
head 200
|
||||
end
|
||||
|
||||
def routing_error
|
||||
raise ActionController::RoutingError, ''
|
||||
end
|
||||
|
||||
def record_not_found
|
||||
raise ActiveRecord::RecordNotFound, ''
|
||||
end
|
||||
|
||||
def invalid_authenticity_token
|
||||
raise ActionController::InvalidAuthenticityToken, ''
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'respond_with_error' do |code|
|
||||
it "returns http #{code} for any" do
|
||||
subject
|
||||
expect(response).to have_http_status(code)
|
||||
end
|
||||
|
||||
it "returns http #{code} for http" do
|
||||
subject
|
||||
expect(response).to have_http_status(code)
|
||||
end
|
||||
|
||||
it "renders template for http" do
|
||||
is_expected.to render_template("errors/#{code}", layout: 'error')
|
||||
end
|
||||
end
|
||||
|
||||
context 'forgery' do
|
||||
subject do
|
||||
ActionController::Base.allow_forgery_protection = true
|
||||
routes.draw { post 'success' => 'anonymous#success' }
|
||||
post 'success'
|
||||
end
|
||||
|
||||
include_examples 'respond_with_error', 422
|
||||
end
|
||||
|
||||
it "does not force ssl if Rails.env.production? is not 'true'" do
|
||||
routes.draw { get 'success' => 'anonymous#success' }
|
||||
allow(Rails.env).to receive(:production?).and_return(false)
|
||||
get 'success'
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it "forces ssl if Rails.env.production? is 'true'" do
|
||||
routes.draw { get 'success' => 'anonymous#success' }
|
||||
allow(Rails.env).to receive(:production?).and_return(true)
|
||||
get 'success'
|
||||
expect(response).to redirect_to('https://test.host/success')
|
||||
end
|
||||
|
||||
describe 'helper_method :current_account' do
|
||||
it 'returns nil if not signed in' do
|
||||
expect(controller.view_context.current_account).to be_nil
|
||||
end
|
||||
|
||||
it 'returns account if signed in' do
|
||||
account = Fabricate(:account)
|
||||
sign_in(Fabricate(:user, account: account))
|
||||
expect(controller.view_context.current_account).to eq account
|
||||
end
|
||||
end
|
||||
|
||||
describe 'helper_method :single_user_mode?' do
|
||||
it 'returns false if it is in single_user_mode but there is no account' do
|
||||
allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
|
||||
expect(controller.view_context.single_user_mode?).to eq false
|
||||
end
|
||||
|
||||
it 'returns false if there is an account but it is not in single_user_mode' do
|
||||
allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false)
|
||||
Fabricate(:account)
|
||||
expect(controller.view_context.single_user_mode?).to eq false
|
||||
end
|
||||
|
||||
it 'returns true if it is in single_user_mode and there is an account' do
|
||||
allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
|
||||
Fabricate(:account)
|
||||
expect(controller.view_context.single_user_mode?).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'helper_method :current_theme' do
|
||||
it 'returns "default" when theme wasn\'t changed in admin settings' do
|
||||
allow(Setting).to receive(:default_settings).and_return({ 'theme' => 'default' })
|
||||
|
||||
expect(controller.view_context.current_theme).to eq 'default'
|
||||
end
|
||||
|
||||
it 'returns instances\'s theme when user is not signed in' do
|
||||
allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
|
||||
|
||||
expect(controller.view_context.current_theme).to eq 'contrast'
|
||||
end
|
||||
|
||||
it 'returns instances\'s default theme when user didn\'t set theme' do
|
||||
current_user = Fabricate(:user)
|
||||
sign_in current_user
|
||||
|
||||
allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
|
||||
|
||||
expect(controller.view_context.current_theme).to eq 'contrast'
|
||||
end
|
||||
|
||||
it 'returns user\'s theme when it is set' do
|
||||
current_user = Fabricate(:user)
|
||||
current_user.settings['theme'] = 'gabsocial-light'
|
||||
sign_in current_user
|
||||
|
||||
allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
|
||||
|
||||
expect(controller.view_context.current_theme).to eq 'gabsocial-light'
|
||||
end
|
||||
end
|
||||
|
||||
context 'ActionController::RoutingError' do
|
||||
subject do
|
||||
routes.draw { get 'routing_error' => 'anonymous#routing_error' }
|
||||
get 'routing_error'
|
||||
end
|
||||
|
||||
include_examples 'respond_with_error', 404
|
||||
end
|
||||
|
||||
context 'ActiveRecord::RecordNotFound' do
|
||||
subject do
|
||||
routes.draw { get 'record_not_found' => 'anonymous#record_not_found' }
|
||||
get 'record_not_found'
|
||||
end
|
||||
|
||||
include_examples 'respond_with_error', 404
|
||||
end
|
||||
|
||||
context 'ActionController::InvalidAuthenticityToken' do
|
||||
subject do
|
||||
routes.draw { get 'invalid_authenticity_token' => 'anonymous#invalid_authenticity_token' }
|
||||
get 'invalid_authenticity_token'
|
||||
end
|
||||
|
||||
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' }
|
||||
end
|
||||
|
||||
it 'does nothing if not signed in' do
|
||||
get 'success'
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'does nothing if user who signed in is not suspended' do
|
||||
sign_in(Fabricate(:user, account: Fabricate(:account, suspended: false)))
|
||||
get 'success'
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns http 403 if user who signed in is suspended' do
|
||||
sign_in(Fabricate(:user, account: Fabricate(:account, suspended: true)))
|
||||
get 'success'
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'raise_not_found' do
|
||||
it 'raises error' do
|
||||
controller.params[:unmatched_route] = 'unmatched'
|
||||
expect { controller.raise_not_found }.to raise_error(ActionController::RoutingError, 'No route matches unmatched')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'require_admin!' do
|
||||
controller do
|
||||
before_action :require_admin!
|
||||
|
||||
def sucesss
|
||||
head 200
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
routes.draw { get 'sucesss' => 'anonymous#sucesss' }
|
||||
end
|
||||
|
||||
it 'returns a 403 if current user is not admin' do
|
||||
sign_in(Fabricate(:user, admin: false))
|
||||
get 'sucesss'
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
|
||||
it 'returns a 403 if current user is only a moderator' do
|
||||
sign_in(Fabricate(:user, moderator: true))
|
||||
get 'sucesss'
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
|
||||
it 'does nothing if current user is admin' do
|
||||
sign_in(Fabricate(:user, admin: true))
|
||||
get 'sucesss'
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'require_staff!' do
|
||||
controller do
|
||||
before_action :require_staff!
|
||||
|
||||
def sucesss
|
||||
head 200
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
routes.draw { get 'sucesss' => 'anonymous#sucesss' }
|
||||
end
|
||||
|
||||
it 'returns a 403 if current user is not admin or moderator' do
|
||||
sign_in(Fabricate(:user, admin: false, moderator: false))
|
||||
get 'sucesss'
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
|
||||
it 'does nothing if current user is moderator' do
|
||||
sign_in(Fabricate(:user, moderator: true))
|
||||
get 'sucesss'
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'does nothing if current user is admin' do
|
||||
sign_in(Fabricate(:user, admin: true))
|
||||
get 'sucesss'
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'forbidden' do
|
||||
controller do
|
||||
def route_forbidden
|
||||
forbidden
|
||||
end
|
||||
end
|
||||
|
||||
subject do
|
||||
routes.draw { get 'route_forbidden' => 'anonymous#route_forbidden' }
|
||||
get 'route_forbidden'
|
||||
end
|
||||
|
||||
include_examples 'respond_with_error', 403
|
||||
end
|
||||
|
||||
describe 'not_found' do
|
||||
controller do
|
||||
def route_not_found
|
||||
not_found
|
||||
end
|
||||
end
|
||||
|
||||
subject do
|
||||
routes.draw { get 'route_not_found' => 'anonymous#route_not_found' }
|
||||
get 'route_not_found'
|
||||
end
|
||||
|
||||
include_examples 'respond_with_error', 404
|
||||
end
|
||||
|
||||
describe 'gone' do
|
||||
controller do
|
||||
def route_gone
|
||||
gone
|
||||
end
|
||||
end
|
||||
|
||||
subject do
|
||||
routes.draw { get 'route_gone' => 'anonymous#route_gone' }
|
||||
get 'route_gone'
|
||||
end
|
||||
|
||||
include_examples 'respond_with_error', 410
|
||||
end
|
||||
|
||||
describe 'unprocessable_entity' do
|
||||
controller do
|
||||
def route_unprocessable_entity
|
||||
unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
subject do
|
||||
routes.draw { get 'route_unprocessable_entity' => 'anonymous#route_unprocessable_entity' }
|
||||
get 'route_unprocessable_entity'
|
||||
end
|
||||
|
||||
include_examples 'respond_with_error', 422
|
||||
end
|
||||
|
||||
describe 'cache_collection' do
|
||||
class C < ApplicationController
|
||||
public :cache_collection
|
||||
end
|
||||
|
||||
shared_examples 'receives :with_includes' do |fabricator, klass|
|
||||
it 'uses raw if it is not an ActiveRecord::Relation' do
|
||||
record = Fabricate(fabricator)
|
||||
expect(C.new.cache_collection([record], klass)).to eq [record]
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'cacheable' do |fabricator, klass|
|
||||
include_examples 'receives :with_includes', fabricator, klass
|
||||
|
||||
it 'calls cache_ids of raw if it is an ActiveRecord::Relation' do
|
||||
record = Fabricate(fabricator)
|
||||
relation = klass.none
|
||||
allow(relation).to receive(:cache_ids).and_return([record])
|
||||
expect(C.new.cache_collection(relation, klass)).to eq [record]
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns raw unless class responds to :with_includes' do
|
||||
raw = Object.new
|
||||
expect(C.new.cache_collection(raw, Object)).to eq raw
|
||||
end
|
||||
|
||||
context 'Notification' do
|
||||
include_examples 'cacheable', :notification, Notification
|
||||
end
|
||||
|
||||
context 'Status' do
|
||||
include_examples 'cacheable', :status, Status
|
||||
end
|
||||
|
||||
context 'StreamEntry' do
|
||||
include_examples 'receives :with_includes', :stream_entry, StreamEntry
|
||||
end
|
||||
end
|
||||
end
|
||||
94
spec/controllers/auth/confirmations_controller_spec.rb
Normal file
94
spec/controllers/auth/confirmations_controller_spec.rb
Normal file
@@ -0,0 +1,94 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Auth::ConfirmationsController, type: :controller do
|
||||
render_views
|
||||
|
||||
describe 'GET #new' do
|
||||
it 'returns http success' do
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
get :new
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
context 'when user is unconfirmed' do
|
||||
let!(:user) { Fabricate(:user, confirmation_token: 'foobar', confirmed_at: nil) }
|
||||
|
||||
before do
|
||||
allow(BootstrapTimelineWorker).to receive(:perform_async)
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
get :show, params: { confirmation_token: 'foobar' }
|
||||
end
|
||||
|
||||
it 'redirects to login' do
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
end
|
||||
|
||||
it 'queues up bootstrapping of home timeline' do
|
||||
expect(BootstrapTimelineWorker).to have_received(:perform_async).with(user.account_id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is updating email' do
|
||||
let!(:user) { Fabricate(:user, confirmation_token: 'foobar', unconfirmed_email: 'new-email@example.com') }
|
||||
|
||||
before do
|
||||
allow(BootstrapTimelineWorker).to receive(:perform_async)
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
get :show, params: { confirmation_token: 'foobar' }
|
||||
end
|
||||
|
||||
it 'redirects to login' do
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
end
|
||||
|
||||
it 'does not queue up bootstrapping of home timeline' do
|
||||
expect(BootstrapTimelineWorker).to_not have_received(:perform_async)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #finish_signup' do
|
||||
subject { get :finish_signup }
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
end
|
||||
|
||||
it 'renders finish_signup' do
|
||||
is_expected.to render_template :finish_signup
|
||||
expect(assigns(:user)).to have_attributes id: user.id
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH #finish_signup' do
|
||||
subject { patch :finish_signup, params: { user: { email: email } } }
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
end
|
||||
|
||||
context 'when email is valid' do
|
||||
let(:email) { 'new_' + user.email }
|
||||
|
||||
it 'redirects to root_path' do
|
||||
is_expected.to redirect_to root_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'when email is invalid' do
|
||||
let(:email) { '' }
|
||||
|
||||
it 'renders finish_signup' do
|
||||
is_expected.to render_template :finish_signup
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
38
spec/controllers/auth/passwords_controller_spec.rb
Normal file
38
spec/controllers/auth/passwords_controller_spec.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Auth::PasswordsController, type: :controller do
|
||||
include Devise::Test::ControllerHelpers
|
||||
|
||||
describe 'GET #new' do
|
||||
it 'returns http success' do
|
||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
get :new
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #edit' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
@token = user.send_reset_password_instructions
|
||||
end
|
||||
|
||||
context 'with valid reset_password_token' do
|
||||
it 'returns http success' do
|
||||
get :edit, params: { reset_password_token: @token }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid reset_password_token' do
|
||||
it 'redirects to #new' do
|
||||
get :edit, params: { reset_password_token: 'some_invalid_value' }
|
||||
expect(response).to redirect_to subject.new_password_path(subject.send(:resource_name))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
218
spec/controllers/auth/registrations_controller_spec.rb
Normal file
218
spec/controllers/auth/registrations_controller_spec.rb
Normal file
@@ -0,0 +1,218 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Auth::RegistrationsController, type: :controller do
|
||||
render_views
|
||||
|
||||
shared_examples 'checks for enabled registrations' do |path|
|
||||
around do |example|
|
||||
registrations_mode = Setting.registrations_mode
|
||||
example.run
|
||||
Setting.registrations_mode = registrations_mode
|
||||
end
|
||||
|
||||
it 'redirects if it is in single user mode while it is open for registration' do
|
||||
Fabricate(:account)
|
||||
Setting.registrations_mode = 'open'
|
||||
expect(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
|
||||
|
||||
get path
|
||||
|
||||
expect(response).to redirect_to '/'
|
||||
end
|
||||
|
||||
it 'redirects if it is not open for registration while it is not in single user mode' do
|
||||
Setting.registrations_mode = 'none'
|
||||
expect(Rails.configuration.x).to receive(:single_user_mode).and_return(false)
|
||||
|
||||
get path
|
||||
|
||||
expect(response).to redirect_to '/'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #edit' do
|
||||
it 'returns http success' do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
sign_in(Fabricate(:user))
|
||||
get :edit
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #update' do
|
||||
it 'returns http success' do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
sign_in(Fabricate(:user), scope: :user)
|
||||
post :update
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #new' do
|
||||
before do
|
||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||
end
|
||||
|
||||
context do
|
||||
around do |example|
|
||||
registrations_mode = Setting.registrations_mode
|
||||
example.run
|
||||
Setting.registrations_mode = registrations_mode
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
Setting.registrations_mode = 'open'
|
||||
get :new
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
include_examples 'checks for enabled registrations', :new
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:accept_language) { Rails.application.config.i18n.available_locales.sample.to_s }
|
||||
|
||||
around do |example|
|
||||
current_locale = I18n.locale
|
||||
example.run
|
||||
I18n.locale = current_locale
|
||||
end
|
||||
|
||||
before { request.env["devise.mapping"] = Devise.mappings[:user] }
|
||||
|
||||
context do
|
||||
around do |example|
|
||||
registrations_mode = Setting.registrations_mode
|
||||
example.run
|
||||
Setting.registrations_mode = registrations_mode
|
||||
end
|
||||
|
||||
subject do
|
||||
Setting.registrations_mode = 'open'
|
||||
request.headers["Accept-Language"] = accept_language
|
||||
post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678' } }
|
||||
end
|
||||
|
||||
it 'redirects to login page' do
|
||||
subject
|
||||
expect(response).to redirect_to new_user_session_path
|
||||
end
|
||||
|
||||
it 'creates user' do
|
||||
subject
|
||||
user = User.find_by(email: 'test@example.com')
|
||||
expect(user).to_not be_nil
|
||||
expect(user.locale).to eq(accept_language)
|
||||
end
|
||||
end
|
||||
|
||||
context 'approval-based registrations without invite' do
|
||||
around do |example|
|
||||
registrations_mode = Setting.registrations_mode
|
||||
example.run
|
||||
Setting.registrations_mode = registrations_mode
|
||||
end
|
||||
|
||||
subject do
|
||||
Setting.registrations_mode = 'approved'
|
||||
request.headers["Accept-Language"] = accept_language
|
||||
post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678' } }
|
||||
end
|
||||
|
||||
it 'redirects to login page' do
|
||||
subject
|
||||
expect(response).to redirect_to new_user_session_path
|
||||
end
|
||||
|
||||
it 'creates user' do
|
||||
subject
|
||||
user = User.find_by(email: 'test@example.com')
|
||||
expect(user).to_not be_nil
|
||||
expect(user.locale).to eq(accept_language)
|
||||
expect(user.approved).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'approval-based registrations with expired invite' do
|
||||
around do |example|
|
||||
registrations_mode = Setting.registrations_mode
|
||||
example.run
|
||||
Setting.registrations_mode = registrations_mode
|
||||
end
|
||||
|
||||
subject do
|
||||
Setting.registrations_mode = 'approved'
|
||||
request.headers["Accept-Language"] = accept_language
|
||||
invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.ago)
|
||||
post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code } }
|
||||
end
|
||||
|
||||
it 'redirects to login page' do
|
||||
subject
|
||||
expect(response).to redirect_to new_user_session_path
|
||||
end
|
||||
|
||||
it 'creates user' do
|
||||
subject
|
||||
user = User.find_by(email: 'test@example.com')
|
||||
expect(user).to_not be_nil
|
||||
expect(user.locale).to eq(accept_language)
|
||||
expect(user.approved).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'approval-based registrations with valid invite' do
|
||||
around do |example|
|
||||
registrations_mode = Setting.registrations_mode
|
||||
example.run
|
||||
Setting.registrations_mode = registrations_mode
|
||||
end
|
||||
|
||||
subject do
|
||||
Setting.registrations_mode = 'approved'
|
||||
request.headers["Accept-Language"] = accept_language
|
||||
invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.from_now)
|
||||
post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code } }
|
||||
end
|
||||
|
||||
it 'redirects to login page' do
|
||||
subject
|
||||
expect(response).to redirect_to new_user_session_path
|
||||
end
|
||||
|
||||
it 'creates user' do
|
||||
subject
|
||||
user = User.find_by(email: 'test@example.com')
|
||||
expect(user).to_not be_nil
|
||||
expect(user.locale).to eq(accept_language)
|
||||
expect(user.approved).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
it 'does nothing if user already exists' do
|
||||
Fabricate(:user, account: Fabricate(:account, username: 'test'))
|
||||
subject
|
||||
end
|
||||
|
||||
include_examples 'checks for enabled registrations', :create
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
sign_in(user, scope: :user)
|
||||
delete :destroy
|
||||
end
|
||||
|
||||
it 'returns http not found' do
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
|
||||
it 'does not delete user' do
|
||||
expect(User.find(user.id)).to_not be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
282
spec/controllers/auth/sessions_controller_spec.rb
Normal file
282
spec/controllers/auth/sessions_controller_spec.rb
Normal file
@@ -0,0 +1,282 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Auth::SessionsController, type: :controller do
|
||||
render_views
|
||||
|
||||
describe 'GET #new' do
|
||||
before do
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :new
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
end
|
||||
|
||||
context 'with a regular user' do
|
||||
it 'redirects to home after sign out' do
|
||||
sign_in(user, scope: :user)
|
||||
delete :destroy
|
||||
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
end
|
||||
|
||||
it 'does not delete redirect location with continue=true' do
|
||||
sign_in(user, scope: :user)
|
||||
controller.store_location_for(:user, '/authorize')
|
||||
delete :destroy, params: { continue: 'true' }
|
||||
expect(controller.stored_location_for(:user)).to eq '/authorize'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a suspended user' do
|
||||
it 'redirects to home after sign out' do
|
||||
Fabricate(:account, user: user, suspended: true)
|
||||
sign_in(user, scope: :user)
|
||||
delete :destroy
|
||||
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
before do
|
||||
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||
end
|
||||
|
||||
context 'using PAM authentication', if: ENV['PAM_ENABLED'] == 'true' do
|
||||
context 'using a valid password' do
|
||||
before do
|
||||
post :create, params: { user: { email: "pam_user1", password: '123456' } }
|
||||
end
|
||||
|
||||
it 'redirects to home' do
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
|
||||
it 'logs the user in' do
|
||||
expect(controller.current_user).to be_instance_of(User)
|
||||
end
|
||||
end
|
||||
|
||||
context 'using an invalid password' do
|
||||
before do
|
||||
post :create, params: { user: { email: "pam_user1", password: 'WRONGPW' } }
|
||||
end
|
||||
|
||||
it 'shows a login error' do
|
||||
expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email')
|
||||
end
|
||||
|
||||
it "doesn't log the user in" do
|
||||
expect(controller.current_user).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a valid email and existing user' do
|
||||
let(:user) do
|
||||
account = Fabricate.build(:account, username: 'pam_user1')
|
||||
account.save!(validate: false)
|
||||
user = Fabricate(:user, email: 'pam@example.com', password: nil, account: account)
|
||||
user
|
||||
end
|
||||
|
||||
before do
|
||||
post :create, params: { user: { email: user.email, password: '123456' } }
|
||||
end
|
||||
|
||||
it 'redirects to home' do
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
|
||||
it 'logs the user in' do
|
||||
expect(controller.current_user).to eq user
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'using password authentication' do
|
||||
let(:user) { Fabricate(:user, email: 'foo@bar.com', password: 'abcdefgh') }
|
||||
|
||||
context 'using a valid password' do
|
||||
before do
|
||||
post :create, params: { user: { email: user.email, password: user.password } }
|
||||
end
|
||||
|
||||
it 'redirects to home' do
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
|
||||
it 'logs the user in' do
|
||||
expect(controller.current_user).to eq user
|
||||
end
|
||||
end
|
||||
|
||||
context 'using email with uppercase letters' do
|
||||
before do
|
||||
post :create, params: { user: { email: user.email.upcase, password: user.password } }
|
||||
end
|
||||
|
||||
it 'redirects to home' do
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
|
||||
it 'logs the user in' do
|
||||
expect(controller.current_user).to eq user
|
||||
end
|
||||
end
|
||||
|
||||
context 'using an invalid password' do
|
||||
before do
|
||||
post :create, params: { user: { email: user.email, password: 'wrongpw' } }
|
||||
end
|
||||
|
||||
it 'shows a login error' do
|
||||
expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email')
|
||||
end
|
||||
|
||||
it "doesn't log the user in" do
|
||||
expect(controller.current_user).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'using an unconfirmed password' do
|
||||
before do
|
||||
request.headers['Accept-Language'] = accept_language
|
||||
post :create, params: { user: { email: unconfirmed_user.email, password: unconfirmed_user.password } }
|
||||
end
|
||||
|
||||
let(:unconfirmed_user) { user.tap { |u| u.update!(confirmed_at: nil) } }
|
||||
let(:accept_language) { 'fr' }
|
||||
|
||||
it 'shows a translated login error' do
|
||||
expect(flash[:alert]).to eq(I18n.t('devise.failure.unconfirmed', locale: accept_language))
|
||||
end
|
||||
end
|
||||
|
||||
context "logging in from the user's page" do
|
||||
before do
|
||||
allow(controller).to receive(:single_user_mode?).and_return(single_user_mode)
|
||||
allow(controller).to receive(:stored_location_for).with(:user).and_return("/@#{user.account.username}")
|
||||
post :create, params: { user: { email: user.email, password: user.password } }
|
||||
end
|
||||
|
||||
context "in single user mode" do
|
||||
let(:single_user_mode) { true }
|
||||
|
||||
it 'redirects to home' do
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
end
|
||||
|
||||
context "in non-single user mode" do
|
||||
let(:single_user_mode) { false }
|
||||
|
||||
it "redirects back to the user's page" do
|
||||
expect(response).to redirect_to(short_account_path(username: user.account))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'using two-factor authentication' do
|
||||
let(:user) do
|
||||
Fabricate(:user, email: 'x@y.com', password: 'abcdefgh',
|
||||
otp_required_for_login: true, otp_secret: User.generate_otp_secret(32))
|
||||
end
|
||||
let(:recovery_codes) do
|
||||
codes = user.generate_otp_backup_codes!
|
||||
user.save
|
||||
return codes
|
||||
end
|
||||
|
||||
context 'using email and password' do
|
||||
before do
|
||||
post :create, params: { user: { email: user.email, password: user.password } }
|
||||
end
|
||||
|
||||
it 'renders two factor authentication page' do
|
||||
expect(controller).to render_template("two_factor")
|
||||
end
|
||||
end
|
||||
|
||||
context 'using upcase email and password' do
|
||||
before do
|
||||
post :create, params: { user: { email: user.email.upcase, password: user.password } }
|
||||
end
|
||||
|
||||
it 'renders two factor authentication page' do
|
||||
expect(controller).to render_template("two_factor")
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a valid OTP' do
|
||||
before do
|
||||
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { otp_user_id: user.id }
|
||||
end
|
||||
|
||||
it 'redirects to home' do
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
|
||||
it 'logs the user in' do
|
||||
expect(controller.current_user).to eq user
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the server has an decryption error' do
|
||||
before do
|
||||
allow_any_instance_of(User).to receive(:validate_and_consume_otp!).and_raise(OpenSSL::Cipher::CipherError)
|
||||
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { otp_user_id: user.id }
|
||||
end
|
||||
|
||||
it 'shows a login error' do
|
||||
expect(flash[:alert]).to match I18n.t('users.invalid_otp_token')
|
||||
end
|
||||
|
||||
it "doesn't log the user in" do
|
||||
expect(controller.current_user).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a valid recovery code' do
|
||||
before do
|
||||
post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { otp_user_id: user.id }
|
||||
end
|
||||
|
||||
it 'redirects to home' do
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
|
||||
it 'logs the user in' do
|
||||
expect(controller.current_user).to eq user
|
||||
end
|
||||
end
|
||||
|
||||
context 'using an invalid OTP' do
|
||||
before do
|
||||
post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { otp_user_id: user.id }
|
||||
end
|
||||
|
||||
it 'shows a login error' do
|
||||
expect(flash[:alert]).to match I18n.t('users.invalid_otp_token')
|
||||
end
|
||||
|
||||
it "doesn't log the user in" do
|
||||
expect(controller.current_user).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
113
spec/controllers/authorize_interactions_controller_spec.rb
Normal file
113
spec/controllers/authorize_interactions_controller_spec.rb
Normal file
@@ -0,0 +1,113 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe AuthorizeInteractionsController do
|
||||
render_views
|
||||
|
||||
describe 'GET #show' do
|
||||
describe 'when signed out' do
|
||||
it 'redirects to sign in page' do
|
||||
get :show
|
||||
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when signed in' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:account) { Fabricate(:account, user: user) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'renders error without acct param' do
|
||||
get :show
|
||||
|
||||
expect(response).to render_template(:error)
|
||||
end
|
||||
|
||||
it 'renders error when account cant be found' do
|
||||
service = double
|
||||
allow(ResolveAccountService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call).with('missing@hostname').and_return(nil)
|
||||
|
||||
get :show, params: { acct: 'acct:missing@hostname' }
|
||||
|
||||
expect(response).to render_template(:error)
|
||||
expect(service).to have_received(:call).with('missing@hostname')
|
||||
end
|
||||
|
||||
it 'sets resource from url' do
|
||||
account = Account.new
|
||||
service = double
|
||||
allow(ResolveURLService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call).with('http://example.com').and_return(account)
|
||||
|
||||
get :show, params: { acct: 'http://example.com' }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(assigns(:resource)).to eq account
|
||||
end
|
||||
|
||||
it 'sets resource from acct uri' do
|
||||
account = Account.new
|
||||
service = double
|
||||
allow(ResolveAccountService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call).with('found@hostname').and_return(account)
|
||||
|
||||
get :show, params: { acct: 'acct:found@hostname' }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(assigns(:resource)).to eq account
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
describe 'when signed out' do
|
||||
it 'redirects to sign in page' do
|
||||
post :create
|
||||
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when signed in' do
|
||||
let!(:user) { Fabricate(:user) }
|
||||
let!(:account) { user.account }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'shows error when account not found' do
|
||||
service = double
|
||||
|
||||
allow(ResolveAccountService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call).with('user@hostname').and_return(nil)
|
||||
|
||||
post :create, params: { acct: 'acct:user@hostname' }
|
||||
|
||||
expect(response).to render_template(:error)
|
||||
end
|
||||
|
||||
it 'follows account when found' do
|
||||
target_account = Fabricate(:account)
|
||||
service = double
|
||||
|
||||
allow(ResolveAccountService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call).with('user@hostname').and_return(target_account)
|
||||
allow(service).to receive(:call).with(target_account, skip_webfinger: true).and_return(target_account)
|
||||
|
||||
|
||||
post :create, params: { acct: 'acct:user@hostname' }
|
||||
|
||||
expect(service).to have_received(:call).with(target_account, skip_webfinger: true)
|
||||
expect(account.following?(target_account)).to be true
|
||||
expect(response).to render_template(:success)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
53
spec/controllers/concerns/account_controller_concern_spec.rb
Normal file
53
spec/controllers/concerns/account_controller_concern_spec.rb
Normal file
@@ -0,0 +1,53 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ApplicationController, type: :controller do
|
||||
controller do
|
||||
include AccountControllerConcern
|
||||
|
||||
def success
|
||||
head 200
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
routes.draw { get 'success' => 'anonymous#success' }
|
||||
end
|
||||
|
||||
context 'when account is suspended' do
|
||||
it 'returns http gone' do
|
||||
account = Fabricate(:account, suspended: true, user: Fabricate(:user))
|
||||
get 'success', params: { account_username: account.username }
|
||||
expect(response).to have_http_status(410)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when account is deleted by owner' do
|
||||
it 'returns http gone' do
|
||||
account = Fabricate(:account, suspended: true, user: nil)
|
||||
get 'success', params: { account_username: account.username }
|
||||
expect(response).to have_http_status(410)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when account is not suspended' do
|
||||
it 'assigns @account' do
|
||||
account = Fabricate(:account, user: Fabricate(:user))
|
||||
get 'success', params: { account_username: account.username }
|
||||
expect(assigns(:account)).to eq account
|
||||
end
|
||||
|
||||
it 'sets link headers' do
|
||||
account = Fabricate(:account, username: 'username', user: Fabricate(:user))
|
||||
get 'success', params: { account_username: 'username' }
|
||||
expect(response.headers['Link'].to_s).to eq '<http://test.host/.well-known/webfinger?resource=acct%3Ausername%40cb6e6126.ngrok.io>; rel="lrdd"; type="application/xrd+xml", <http://test.host/users/username.atom>; rel="alternate"; type="application/atom+xml", <https://cb6e6126.ngrok.io/users/username>; rel="alternate"; type="application/activity+json"'
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
account = Fabricate(:account, user: Fabricate(:user))
|
||||
get 'success', params: { account_username: account.username }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
26
spec/controllers/concerns/accountable_concern_spec.rb
Normal file
26
spec/controllers/concerns/accountable_concern_spec.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe AccountableConcern do
|
||||
class Hoge
|
||||
include AccountableConcern
|
||||
attr_reader :current_account
|
||||
|
||||
def initialize(current_account)
|
||||
@current_account = current_account
|
||||
end
|
||||
end
|
||||
|
||||
let(:user) { Fabricate(:user, account: Fabricate(:account)) }
|
||||
let(:target) { Fabricate(:user, account: Fabricate(:account)) }
|
||||
let(:hoge) { Hoge.new(user.account) }
|
||||
|
||||
describe '#log_action' do
|
||||
it 'creates Admin::ActionLog' do
|
||||
expect do
|
||||
hoge.log_action(:create, target.account)
|
||||
end.to change { Admin::ActionLog.count }.by(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
34
spec/controllers/concerns/export_controller_concern_spec.rb
Normal file
34
spec/controllers/concerns/export_controller_concern_spec.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ApplicationController, type: :controller do
|
||||
controller do
|
||||
include ExportControllerConcern
|
||||
def index
|
||||
send_export_file
|
||||
end
|
||||
|
||||
def export_data
|
||||
@export.account.username
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns a csv of the exported data when signed in' do
|
||||
user = Fabricate(:user)
|
||||
sign_in user
|
||||
get :index, format: :csv
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type).to eq 'text/csv'
|
||||
expect(response.headers['Content-Disposition']).to eq 'attachment; filename="anonymous.csv"'
|
||||
expect(response.body).to eq user.account.username
|
||||
end
|
||||
|
||||
it 'returns unauthorized when not signed in' do
|
||||
get :index, format: :csv
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
end
|
||||
68
spec/controllers/concerns/localized_spec.rb
Normal file
68
spec/controllers/concerns/localized_spec.rb
Normal file
@@ -0,0 +1,68 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ApplicationController, type: :controller do
|
||||
controller do
|
||||
include Localized
|
||||
|
||||
def success
|
||||
head 200
|
||||
end
|
||||
end
|
||||
|
||||
around do |example|
|
||||
current_locale = I18n.locale
|
||||
example.run
|
||||
I18n.locale = current_locale
|
||||
end
|
||||
|
||||
before do
|
||||
routes.draw { get 'success' => 'anonymous#success' }
|
||||
end
|
||||
|
||||
shared_examples 'default locale' do
|
||||
it 'sets available and preferred language' do
|
||||
request.headers['Accept-Language'] = 'ca-ES, fa'
|
||||
get 'success'
|
||||
expect(I18n.locale).to eq :fa
|
||||
end
|
||||
|
||||
it 'sets available and compatible language if none of available languages are preferred' do
|
||||
request.headers['Accept-Language'] = 'fa-IR'
|
||||
get 'success'
|
||||
expect(I18n.locale).to eq :fa
|
||||
end
|
||||
|
||||
it 'sets default locale if none of available languages are compatible' do
|
||||
request.headers['Accept-Language'] = ''
|
||||
get 'success'
|
||||
expect(I18n.locale).to eq :en
|
||||
end
|
||||
end
|
||||
|
||||
context 'user with valid locale has signed in' do
|
||||
it "sets user's locale" do
|
||||
user = Fabricate(:user, locale: :ca)
|
||||
|
||||
sign_in(user)
|
||||
get 'success'
|
||||
|
||||
expect(I18n.locale).to eq :ca
|
||||
end
|
||||
end
|
||||
|
||||
context 'user with invalid locale has signed in' do
|
||||
before do
|
||||
user = Fabricate.build(:user, locale: :invalid)
|
||||
user.save!(validate: false)
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
include_examples 'default locale'
|
||||
end
|
||||
|
||||
context 'user has not signed in' do
|
||||
include_examples 'default locale'
|
||||
end
|
||||
end
|
||||
30
spec/controllers/concerns/obfuscate_filename_spec.rb
Normal file
30
spec/controllers/concerns/obfuscate_filename_spec.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ApplicationController, type: :controller do
|
||||
controller do
|
||||
include ObfuscateFilename
|
||||
|
||||
obfuscate_filename :file
|
||||
|
||||
def file
|
||||
render plain: params[:file]&.original_filename
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
routes.draw { get 'file' => 'anonymous#file' }
|
||||
end
|
||||
|
||||
it 'obfusticates filename if the given parameter is specified' do
|
||||
file = fixture_file_upload('files/imports.txt', 'text/plain')
|
||||
post 'file', params: { file: file }
|
||||
expect(response.body).to end_with '.txt'
|
||||
expect(response.body).not_to include 'imports'
|
||||
end
|
||||
|
||||
it 'does nothing if the given parameter is not specified' do
|
||||
post 'file'
|
||||
end
|
||||
end
|
||||
56
spec/controllers/concerns/rate_limit_headers_spec.rb
Normal file
56
spec/controllers/concerns/rate_limit_headers_spec.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ApplicationController do
|
||||
controller do
|
||||
include RateLimitHeaders
|
||||
|
||||
def show
|
||||
head 200
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
routes.draw { get 'show' => 'anonymous#show' }
|
||||
end
|
||||
|
||||
describe 'rate limiting' do
|
||||
context 'throttling is off' do
|
||||
before do
|
||||
request.env['rack.attack.throttle_data'] = nil
|
||||
end
|
||||
|
||||
it 'does not apply rate limiting' do
|
||||
get 'show'
|
||||
|
||||
expect(response.headers['X-RateLimit-Limit']).to be_nil
|
||||
expect(response.headers['X-RateLimit-Remaining']).to be_nil
|
||||
expect(response.headers['X-RateLimit-Reset']).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'throttling is on' do
|
||||
let(:start_time) { DateTime.new(2017, 1, 1, 12, 0, 0).utc }
|
||||
|
||||
before do
|
||||
request.env['rack.attack.throttle_data'] = { 'throttle_authenticated_api' => { limit: 100, count: 20, period: 10 } }
|
||||
travel_to start_time do
|
||||
get 'show'
|
||||
end
|
||||
end
|
||||
|
||||
it 'applies rate limiting limit header' do
|
||||
expect(response.headers['X-RateLimit-Limit']).to eq '100'
|
||||
end
|
||||
|
||||
it 'applies rate limiting remaining header' do
|
||||
expect(response.headers['X-RateLimit-Remaining']).to eq '80'
|
||||
end
|
||||
|
||||
it 'applies rate limiting reset header' do
|
||||
expect(response.headers['X-RateLimit-Reset']).to eq (start_time + 10.seconds).iso8601(6)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
138
spec/controllers/concerns/signature_verification_spec.rb
Normal file
138
spec/controllers/concerns/signature_verification_spec.rb
Normal file
@@ -0,0 +1,138 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ApplicationController, type: :controller do
|
||||
controller do
|
||||
include SignatureVerification
|
||||
|
||||
def success
|
||||
head 200
|
||||
end
|
||||
|
||||
def alternative_success
|
||||
head 200
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
routes.draw { match via: [:get, :post], 'success' => 'anonymous#success' }
|
||||
end
|
||||
|
||||
context 'without signature header' do
|
||||
before do
|
||||
get :success
|
||||
end
|
||||
|
||||
describe '#signed_request?' do
|
||||
it 'returns false' do
|
||||
expect(controller.signed_request?).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#signed_request_account' do
|
||||
it 'returns nil' do
|
||||
expect(controller.signed_request_account).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with signature header' do
|
||||
let!(:author) { Fabricate(:account) }
|
||||
|
||||
context 'without body' do
|
||||
before do
|
||||
get :success
|
||||
|
||||
fake_request = Request.new(:get, request.url)
|
||||
fake_request.on_behalf_of(author)
|
||||
|
||||
request.headers.merge!(fake_request.headers)
|
||||
end
|
||||
|
||||
describe '#signed_request?' do
|
||||
it 'returns true' do
|
||||
expect(controller.signed_request?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#signed_request_account' do
|
||||
it 'returns an account' do
|
||||
expect(controller.signed_request_account).to eq author
|
||||
end
|
||||
|
||||
it 'returns nil when path does not match' do
|
||||
request.path = '/alternative-path'
|
||||
expect(controller.signed_request_account).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil when method does not match' do
|
||||
post :success
|
||||
expect(controller.signed_request_account).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with request older than a day' do
|
||||
before do
|
||||
get :success
|
||||
|
||||
fake_request = Request.new(:get, request.url)
|
||||
fake_request.add_headers({ 'Date' => 2.days.ago.utc.httpdate })
|
||||
fake_request.on_behalf_of(author)
|
||||
|
||||
request.headers.merge!(fake_request.headers)
|
||||
end
|
||||
|
||||
describe '#signed_request?' do
|
||||
it 'returns true' do
|
||||
expect(controller.signed_request?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#signed_request_account' do
|
||||
it 'returns nil' do
|
||||
expect(controller.signed_request_account).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with body' do
|
||||
before do
|
||||
post :success, body: 'Hello world'
|
||||
|
||||
fake_request = Request.new(:post, request.url, body: 'Hello world')
|
||||
fake_request.on_behalf_of(author)
|
||||
|
||||
request.headers.merge!(fake_request.headers)
|
||||
end
|
||||
|
||||
describe '#signed_request?' do
|
||||
it 'returns true' do
|
||||
expect(controller.signed_request?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#signed_request_account' do
|
||||
it 'returns an account' do
|
||||
expect(controller.signed_request_account).to eq author
|
||||
end
|
||||
|
||||
it 'returns nil when path does not match' do
|
||||
request.path = '/alternative-path'
|
||||
expect(controller.signed_request_account).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil when method does not match' do
|
||||
get :success
|
||||
expect(controller.signed_request_account).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil when body has been tampered' do
|
||||
post :success, body: 'doo doo doo'
|
||||
expect(controller.signed_request_account).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
91
spec/controllers/concerns/user_tracking_concern_spec.rb
Normal file
91
spec/controllers/concerns/user_tracking_concern_spec.rb
Normal file
@@ -0,0 +1,91 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ApplicationController, type: :controller do
|
||||
controller do
|
||||
include UserTrackingConcern
|
||||
|
||||
def show
|
||||
render plain: 'show'
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
routes.draw { get 'show' => 'anonymous#show' }
|
||||
end
|
||||
|
||||
describe 'when signed in' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
it 'does not track when there is a recent sign in' do
|
||||
user.update(current_sign_in_at: 60.minutes.ago)
|
||||
prior = user.current_sign_in_at
|
||||
sign_in user, scope: :user
|
||||
get :show
|
||||
|
||||
expect(user.reload.current_sign_in_at).to be_within(1.0).of(prior)
|
||||
end
|
||||
|
||||
it 'tracks when sign in is nil' do
|
||||
user.update(current_sign_in_at: nil)
|
||||
sign_in user, scope: :user
|
||||
get :show
|
||||
|
||||
expect_updated_sign_in_at(user)
|
||||
end
|
||||
|
||||
it 'tracks when sign in is older than one day' do
|
||||
user.update(current_sign_in_at: 2.days.ago)
|
||||
sign_in user, scope: :user
|
||||
get :show
|
||||
|
||||
expect_updated_sign_in_at(user)
|
||||
end
|
||||
|
||||
describe 'feed regeneration' do
|
||||
before do
|
||||
alice = Fabricate(:account)
|
||||
bob = Fabricate(:account)
|
||||
|
||||
user.account.follow!(alice)
|
||||
user.account.follow!(bob)
|
||||
|
||||
Fabricate(:status, account: alice, text: 'hello world')
|
||||
Fabricate(:status, account: bob, text: 'yes hello')
|
||||
Fabricate(:status, account: user.account, text: 'test')
|
||||
|
||||
user.update(last_sign_in_at: 'Tue, 04 Jul 2017 14:45:56 UTC +00:00', current_sign_in_at: 'Wed, 05 Jul 2017 22:10:52 UTC +00:00')
|
||||
|
||||
sign_in user, scope: :user
|
||||
end
|
||||
|
||||
it 'sets a regeneration marker while regenerating' do
|
||||
allow(RegenerationWorker).to receive(:perform_async)
|
||||
get :show
|
||||
|
||||
expect_updated_sign_in_at(user)
|
||||
expect(Redis.current.get("account:#{user.account_id}:regeneration")).to eq 'true'
|
||||
expect(RegenerationWorker).to have_received(:perform_async)
|
||||
end
|
||||
|
||||
it 'sets the regeneration marker to expire' do
|
||||
allow(RegenerationWorker).to receive(:perform_async)
|
||||
get :show
|
||||
expect(Redis.current.ttl("account:#{user.account_id}:regeneration")).to be >= 0
|
||||
end
|
||||
|
||||
it 'regenerates feed when sign in is older than two weeks' do
|
||||
get :show
|
||||
|
||||
expect_updated_sign_in_at(user)
|
||||
expect(Redis.current.zcard(FeedManager.instance.key(:home, user.account_id))).to eq 3
|
||||
expect(Redis.current.get("account:#{user.account_id}:regeneration")).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
def expect_updated_sign_in_at(user)
|
||||
expect(user.reload.current_sign_in_at).to be_within(1.0).of(Time.now.utc)
|
||||
end
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user