commit
c10a667ac2
41 changed files with 1222 additions and 937 deletions
@ -0,0 +1,41 @@ |
||||
- if account.suspended? |
||||
%hr.spacer/ |
||||
- if account.suspension_origin_remote? |
||||
%p.muted-hint= deletion_request.present? ? t('admin.accounts.remote_suspension_reversible_hint_html', date: content_tag(:strong, l(deletion_request.due_at.to_date))) : t('admin.accounts.remote_suspension_irreversible') |
||||
- else |
||||
%p.muted-hint= deletion_request.present? ? t('admin.accounts.suspension_reversible_hint_html', date: content_tag(:strong, l(deletion_request.due_at.to_date))) : t('admin.accounts.suspension_irreversible') |
||||
= link_to t('admin.accounts.undo_suspension'), unsuspend_admin_account_path(account.id), method: :post, class: 'button' if can?(:unsuspend, account) |
||||
= link_to t('admin.accounts.redownload'), redownload_admin_account_path(account.id), method: :post, class: 'button' if can?(:redownload, account) && account.suspension_origin_remote? |
||||
- if deletion_request.present? |
||||
= link_to t('admin.accounts.delete'), admin_account_path(account.id), method: :delete, class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure') } if can?(:destroy, account) |
||||
- else |
||||
.action-buttons |
||||
%div |
||||
- if account.local? && account.user_approved? |
||||
= link_to t('admin.accounts.warn'), new_admin_account_action_path(account.id, type: 'none'), class: 'button' if can?(:warn, account) |
||||
- if account.user_disabled? |
||||
= link_to t('admin.accounts.enable'), enable_admin_account_path(account.id), method: :post, class: 'button' if can?(:enable, account.user) |
||||
- else |
||||
= link_to t('admin.accounts.disable'), new_admin_account_action_path(account.id, type: 'disable'), class: 'button' if can?(:disable, account.user) |
||||
- if account.sensitized? |
||||
= link_to t('admin.accounts.undo_sensitized'), unsensitive_admin_account_path(account.id), method: :post, class: 'button' if can?(:unsensitive, account) |
||||
- elsif !account.local? || account.user_approved? |
||||
= link_to t('admin.accounts.sensitive'), new_admin_account_action_path(account.id, type: 'sensitive'), class: 'button' if can?(:sensitive, account) |
||||
- if account.silenced? |
||||
= link_to t('admin.accounts.undo_silenced'), unsilence_admin_account_path(account.id), method: :post, class: 'button' if can?(:unsilence, account) |
||||
- elsif !account.local? || account.user_approved? |
||||
= link_to t('admin.accounts.silence'), new_admin_account_action_path(account.id, type: 'silence'), class: 'button' if can?(:silence, account) |
||||
- if account.local? |
||||
- if account.user_pending? |
||||
= link_to t('admin.accounts.approve'), approve_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' if can?(:approve, account.user) |
||||
= link_to t('admin.accounts.reject'), reject_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:reject, account.user) |
||||
- unless account.user_confirmed? |
||||
= link_to t('admin.accounts.confirm'), admin_account_confirmation_path(account.id), method: :post, class: 'button' if can?(:confirm, account.user) |
||||
- if !account.local? || account.user_approved? |
||||
= link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(account.id, type: 'suspend'), class: 'button' if can?(:suspend, account) |
||||
%div |
||||
- if account.local? |
||||
- if !account.memorial? && account.user_approved? |
||||
= link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:memorialize, account) |
||||
- else |
||||
= link_to t('admin.accounts.redownload'), redownload_admin_account_path(account.id), method: :post, class: 'button' if can?(:redownload, account) |
@ -0,0 +1,43 @@ |
||||
.dashboard__counters.admin-account-counters |
||||
%div |
||||
= link_to admin_account_statuses_path(account.id) do |
||||
.dashboard__counters__num= number_with_delimiter account.statuses_count |
||||
.dashboard__counters__label= t 'admin.accounts.statuses' |
||||
%div |
||||
= link_to admin_account_statuses_path(account.id, { media: true }) do |
||||
.dashboard__counters__num= number_to_human_size account.media_attachments.sum('file_file_size') |
||||
.dashboard__counters__label= t 'admin.accounts.media_attachments' |
||||
%div |
||||
= link_to admin_account_relationships_path(account.id, location: account.local? ? nil : 'local', relationship: 'followed_by') do |
||||
.dashboard__counters__num= number_with_delimiter account.local_followers_count |
||||
.dashboard__counters__label= t 'admin.accounts.followers' |
||||
%div |
||||
= link_to admin_reports_path(account_id: account.id) do |
||||
.dashboard__counters__num= number_with_delimiter account.reports.count |
||||
.dashboard__counters__label= t 'admin.accounts.show.created_reports' |
||||
%div |
||||
= link_to admin_reports_path(target_account_id: account.id) do |
||||
.dashboard__counters__num= number_with_delimiter account.targeted_reports.count |
||||
.dashboard__counters__label= t 'admin.accounts.show.targeted_reports' |
||||
%div |
||||
= link_to admin_action_logs_path(target_account_id: account.id) do |
||||
.dashboard__counters__text |
||||
- if account.local? && account.user.nil? |
||||
= t('admin.accounts.deleted') |
||||
- elsif account.memorial? |
||||
= t('admin.accounts.memorialized') |
||||
- elsif account.suspended? |
||||
= t('admin.accounts.suspended') |
||||
- elsif account.silenced? |
||||
= t('admin.accounts.silenced') |
||||
- elsif account.local? && account.user&.disabled? |
||||
= t('admin.accounts.disabled') |
||||
- elsif account.local? && !account.user&.confirmed? |
||||
= t('admin.accounts.confirming') |
||||
- elsif account.local? && !account.user_approved? |
||||
= t('admin.accounts.pending') |
||||
- elsif account.sensitized? |
||||
= t('admin.accounts.sensitive') |
||||
- else |
||||
= t('admin.accounts.no_limits_imposed') |
||||
.dashboard__counters__label= t 'admin.accounts.login_status' |
@ -0,0 +1,82 @@ |
||||
- if account.avatar? |
||||
%tr |
||||
%th= t('admin.accounts.avatar') |
||||
%td= table_link_to 'trash', t('admin.accounts.remove_avatar'), remove_avatar_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:remove_avatar, account) |
||||
%td |
||||
- if account.header? |
||||
%tr |
||||
%th= t('admin.accounts.header') |
||||
%td= table_link_to 'trash', t('admin.accounts.remove_header'), remove_header_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:remove_header, account) |
||||
%td |
||||
%tr |
||||
%th= t('admin.accounts.role') |
||||
%td |
||||
- if account.user_role&.everyone? |
||||
= t('admin.accounts.no_role_assigned') |
||||
- else |
||||
= account.user_role&.name |
||||
%td |
||||
= table_link_to 'vcard', t('admin.accounts.change_role.label'), admin_user_role_path(account.user) if can?(:change_role, account.user) |
||||
%tr |
||||
%th{ rowspan: can?(:create, :email_domain_block) ? 3 : 2 }= t('admin.accounts.email') |
||||
%td{ rowspan: can?(:create, :email_domain_block) ? 3 : 2 }= account.user_email |
||||
%td= table_link_to 'edit', t('admin.accounts.change_email.label'), admin_account_change_email_path(account.id) if can?(:change_email, account.user) |
||||
%tr |
||||
%td= table_link_to 'search', t('admin.accounts.search_same_email_domain'), admin_accounts_path(email: "%@#{account.user_email.split('@').last}") |
||||
- if can?(:create, :email_domain_block) |
||||
%tr |
||||
%td= table_link_to 'ban', t('admin.accounts.add_email_domain_block'), new_admin_email_domain_block_path(_domain: account.user_email.split('@').last) |
||||
- if account.user_unconfirmed_email.present? |
||||
%tr |
||||
%th= t('admin.accounts.unconfirmed_email') |
||||
%td= account.user_unconfirmed_email |
||||
%td |
||||
%tr |
||||
%th= t('admin.accounts.email_status') |
||||
%td |
||||
- if account.user&.confirmed? |
||||
= t('admin.accounts.confirmed') |
||||
- else |
||||
= t('admin.accounts.confirming') |
||||
%td= table_link_to 'refresh', t('admin.accounts.resend_confirmation.send'), resend_admin_account_confirmation_path(account.id), method: :post if can?(:confirm, account.user) |
||||
%tr |
||||
%th{ rowspan: can?(:reset_password, account.user) ? 2 : 1 }= t('admin.accounts.security') |
||||
%td{ rowspan: can?(:reset_password, account.user) ? 2 : 1 } |
||||
- if account.user&.two_factor_enabled? |
||||
= t 'admin.accounts.security_measures.password_and_2fa' |
||||
- else |
||||
= t 'admin.accounts.security_measures.only_password' |
||||
%td |
||||
- if account.user&.two_factor_enabled? |
||||
= table_link_to 'unlock', t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(account.user.id), method: :delete if can?(:disable_2fa, account.user) |
||||
- if can?(:reset_password, account.user) |
||||
%tr |
||||
%td |
||||
= table_link_to 'key', t('admin.accounts.reset_password'), admin_account_reset_path(account.id), method: :create, data: { confirm: t('admin.accounts.are_you_sure') } |
||||
%tr |
||||
%th= t('simple_form.labels.defaults.locale') |
||||
%td= standard_locale_name(account.user_locale) |
||||
%td |
||||
%tr |
||||
%th= t('admin.accounts.joined') |
||||
%td |
||||
%time.formatted{ datetime: account.created_at.iso8601, title: l(account.created_at) }= l account.created_at |
||||
%td |
||||
- recent_ips = account.user.ips.order(used_at: :desc).to_a |
||||
- recent_ips.each_with_index do |recent_ip, i| |
||||
%tr |
||||
- if i.zero? |
||||
%th{ rowspan: recent_ips.size }= t('admin.accounts.most_recent_ip') |
||||
%td= recent_ip.ip |
||||
%td= table_link_to 'search', t('admin.accounts.search_same_ip'), admin_accounts_path(ip: recent_ip.ip) |
||||
%tr |
||||
%th= t('admin.accounts.most_recent_activity') |
||||
%td |
||||
- if account.user_current_sign_in_at |
||||
%time.formatted{ datetime: account.user_current_sign_in_at.iso8601, title: l(account.user_current_sign_in_at) }= l account.user_current_sign_in_at |
||||
%td |
||||
- if account.user&.invited? |
||||
%tr |
||||
%th= t('admin.accounts.invited_by') |
||||
%td= admin_account_link_to account.user.invite.user.account |
||||
%td |
@ -0,0 +1,15 @@ |
||||
%tr |
||||
%th= t('admin.accounts.inbox_url') |
||||
%td |
||||
= account.inbox_url |
||||
= fa_icon DeliveryFailureTracker.available?(account.inbox_url) ? 'check' : 'times' |
||||
%td |
||||
= table_link_to 'search', domain_block.present? ? t('admin.domain_blocks.view') : t('admin.accounts.view_domain'), admin_instance_path(account.domain) |
||||
%tr |
||||
%th= t('admin.accounts.shared_inbox_url') |
||||
%td |
||||
= account.shared_inbox_url |
||||
= fa_icon DeliveryFailureTracker.available?(account.shared_inbox_url) ? 'check' : 'times' |
||||
%td |
||||
- if domain_block.nil? |
||||
= table_link_to 'ban', t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: account.domain) |
@ -0,0 +1,24 @@ |
||||
- if report.account.instance_actor? |
||||
%p= t('admin.reports.comment_description_html', name: content_tag(:strong, site_hostname, class: 'username')) |
||||
- elsif report.account.local? |
||||
%p= t('admin.reports.comment_description_html', name: content_tag(:strong, report.account.username, class: 'username')) |
||||
- else |
||||
%p= t('admin.reports.comment_description_html', name: t('admin.reports.remote_user_placeholder', instance: report.account.domain)) |
||||
.report-notes |
||||
.report-notes__item |
||||
- if report.account.local? && !report.account.instance_actor? |
||||
= image_tag report.account.avatar.url, class: 'report-notes__item__avatar' |
||||
- else |
||||
= image_tag(full_asset_url('avatars/original/missing.png', skip_pipeline: true), class: 'report-notes__item__avatar') |
||||
.report-notes__item__header |
||||
%span.username |
||||
- if report.account.instance_actor? |
||||
= site_hostname |
||||
- elsif report.account.local? |
||||
= link_to report.account.username, admin_account_path(report.account_id) |
||||
- else |
||||
= link_to report.account.domain, admin_instance_path(report.account.domain) |
||||
%time.relative-formatted{ datetime: report.created_at.iso8601 } |
||||
= l report.created_at.to_date |
||||
.report-notes__item__content |
||||
= simple_format(h(report.comment)) |
@ -0,0 +1,46 @@ |
||||
.report-header__card |
||||
.account-card |
||||
.account-card__header |
||||
= image_tag report.target_account.header.url, alt: '' |
||||
.account-card__title |
||||
.account-card__title__avatar |
||||
= image_tag report.target_account.avatar.url, alt: '' |
||||
.display-name |
||||
%bdi |
||||
%strong.emojify.p-name= display_name(report.target_account, custom_emojify: true) |
||||
%span |
||||
= acct(report.target_account) |
||||
= fa_icon('lock') if report.target_account.locked? |
||||
- if report.target_account.note.present? |
||||
.account-card__bio.emojify |
||||
= prerender_custom_emojis(account_bio_format(report.target_account), report.target_account.emojis) |
||||
.account-card__actions |
||||
.account-card__counters |
||||
.account-card__counters__item |
||||
= friendly_number_to_human report.target_account.statuses_count |
||||
%small= t('accounts.posts', count: report.target_account.statuses_count).downcase |
||||
.account-card__counters__item |
||||
= friendly_number_to_human report.target_account.followers_count |
||||
%small= t('accounts.followers', count: report.target_account.followers_count).downcase |
||||
.account-card__counters__item |
||||
= friendly_number_to_human report.target_account.following_count |
||||
%small= t('accounts.following', count: report.target_account.following_count).downcase |
||||
.account-card__actions__button |
||||
= link_to t('admin.reports.view_profile'), admin_account_path(report.target_account_id), class: 'button' |
||||
.report-header__details.report-header__details--horizontal |
||||
.report-header__details__item |
||||
.report-header__details__item__header |
||||
%strong= t('admin.accounts.joined') |
||||
.report-header__details__item__content |
||||
%time.time-ago{ datetime: report.target_account.created_at.iso8601, title: l(report.target_account.created_at) }= l report.target_account.created_at |
||||
.report-header__details__item |
||||
.report-header__details__item__header |
||||
%strong= t('accounts.last_active') |
||||
.report-header__details__item__content |
||||
- if report.target_account.last_status_at.present? |
||||
%time.time-ago{ datetime: report.target_account.last_status_at.to_date.iso8601, title: l(report.target_account.last_status_at.to_date) }= l report.target_account.last_status_at |
||||
.report-header__details__item |
||||
.report-header__details__item__header |
||||
%strong= t('admin.accounts.strikes') |
||||
.report-header__details__item__content |
||||
= report.target_account.previous_strikes_count |
@ -0,0 +1,53 @@ |
||||
.report-header__details |
||||
.report-header__details__item |
||||
.report-header__details__item__header |
||||
%strong= t('admin.reports.created_at') |
||||
.report-header__details__item__content |
||||
%time.formatted{ datetime: report.created_at.iso8601 } |
||||
.report-header__details__item |
||||
.report-header__details__item__header |
||||
%strong= t('admin.reports.reported_by') |
||||
.report-header__details__item__content |
||||
- if report.account.instance_actor? |
||||
= site_hostname |
||||
- elsif report.account.local? |
||||
= admin_account_link_to report.account |
||||
- else |
||||
= report.account.domain |
||||
.report-header__details__item |
||||
.report-header__details__item__header |
||||
%strong= t('admin.reports.status') |
||||
.report-header__details__item__content |
||||
- if report.action_taken? |
||||
= t('admin.reports.resolved') |
||||
- else |
||||
= t('admin.reports.unresolved') |
||||
- unless report.target_account.local? |
||||
.report-header__details__item |
||||
.report-header__details__item__header |
||||
%strong= t('admin.reports.forwarded') |
||||
.report-header__details__item__content |
||||
- if report.forwarded? |
||||
= t('simple_form.yes') |
||||
- else |
||||
= t('simple_form.no') |
||||
- if report.action_taken_by_account.present? |
||||
.report-header__details__item |
||||
.report-header__details__item__header |
||||
%strong= t('admin.reports.action_taken_by') |
||||
.report-header__details__item__content |
||||
= admin_account_link_to report.action_taken_by_account |
||||
- else |
||||
.report-header__details__item |
||||
.report-header__details__item__header |
||||
%strong= t('admin.reports.assigned') |
||||
.report-header__details__item__content |
||||
- if report.assigned_account.nil? |
||||
= t 'admin.reports.no_one_assigned' |
||||
- else |
||||
= admin_account_link_to report.assigned_account |
||||
— |
||||
- if report.assigned_account != current_user.account |
||||
= table_link_to 'user', t('admin.reports.assign_to_self'), assign_to_self_admin_report_path(report), method: :post |
||||
- elsif !report.assigned_account.nil? |
||||
= table_link_to 'trash', t('admin.reports.unassign'), unassign_admin_report_path(report), method: :post |
@ -1,137 +0,0 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
require 'rails_helper' |
||||
|
||||
RSpec.describe Api::V1::NotificationsController do |
||||
render_views |
||||
|
||||
let(:user) { Fabricate(:user, account_attributes: { username: 'alice' }) } |
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } |
||||
let(:other) { Fabricate(:user) } |
||||
let(:third) { Fabricate(:user) } |
||||
|
||||
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, user.account) |
||||
end |
||||
|
||||
describe 'with no options' do |
||||
before do |
||||
get :index |
||||
end |
||||
|
||||
it 'returns expected notification types', :aggregate_failures do |
||||
expect(response).to have_http_status(200) |
||||
|
||||
expect(body_json_types).to include 'reblog' |
||||
expect(body_json_types).to include 'mention' |
||||
expect(body_json_types).to include 'favourite' |
||||
expect(body_json_types).to include 'follow' |
||||
end |
||||
end |
||||
|
||||
describe 'with account_id param' do |
||||
before do |
||||
get :index, params: { account_id: third.account.id } |
||||
end |
||||
|
||||
it 'returns only notifications from specified user', :aggregate_failures do |
||||
expect(response).to have_http_status(200) |
||||
|
||||
expect(body_json_account_ids.uniq).to eq [third.account.id.to_s] |
||||
end |
||||
|
||||
def body_json_account_ids |
||||
body_as_json.map { |x| x[:account][:id] } |
||||
end |
||||
end |
||||
|
||||
describe 'with invalid account_id param' do |
||||
before do |
||||
get :index, params: { account_id: 'foo' } |
||||
end |
||||
|
||||
it 'returns nothing', :aggregate_failures do |
||||
expect(response).to have_http_status(200) |
||||
|
||||
expect(body_as_json.size).to eq 0 |
||||
end |
||||
end |
||||
|
||||
describe 'with exclude_types param' do |
||||
before do |
||||
get :index, params: { exclude_types: %w(mention) } |
||||
end |
||||
|
||||
it 'returns everything but excluded type', :aggregate_failures do |
||||
expect(response).to have_http_status(200) |
||||
|
||||
expect(body_as_json.size).to_not eq 0 |
||||
expect(body_json_types.uniq).to_not include 'mention' |
||||
end |
||||
end |
||||
|
||||
describe 'with types param' do |
||||
before do |
||||
get :index, params: { types: %w(mention) } |
||||
end |
||||
|
||||
it 'returns only requested type', :aggregate_failures do |
||||
expect(response).to have_http_status(200) |
||||
|
||||
expect(body_json_types.uniq).to eq ['mention'] |
||||
end |
||||
end |
||||
|
||||
def body_json_types |
||||
body_as_json.pluck(:type) |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,183 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
require 'rails_helper' |
||||
|
||||
RSpec.describe 'Notifications' do |
||||
let(:user) { Fabricate(:user, account_attributes: { username: 'alice' }) } |
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } |
||||
let(:scopes) { 'read:notifications write:notifications' } |
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } |
||||
|
||||
describe 'GET /api/v1/notifications' do |
||||
subject do |
||||
get '/api/v1/notifications', headers: headers, params: params |
||||
end |
||||
|
||||
let(:bob) { Fabricate(:user) } |
||||
let(:tom) { Fabricate(:user) } |
||||
let(:params) { {} } |
||||
|
||||
before do |
||||
first_status = PostStatusService.new.call(user.account, text: 'Test') |
||||
ReblogService.new.call(bob.account, first_status) |
||||
mentioning_status = PostStatusService.new.call(bob.account, text: 'Hello @alice') |
||||
mentioning_status.mentions.first |
||||
FavouriteService.new.call(bob.account, first_status) |
||||
FavouriteService.new.call(tom.account, first_status) |
||||
FollowService.new.call(bob.account, user.account) |
||||
end |
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write write:notifications' |
||||
|
||||
context 'with no options' do |
||||
it 'returns expected notification types', :aggregate_failures do |
||||
subject |
||||
|
||||
expect(response).to have_http_status(200) |
||||
expect(body_json_types).to include 'reblog' |
||||
expect(body_json_types).to include 'mention' |
||||
expect(body_json_types).to include 'favourite' |
||||
expect(body_json_types).to include 'follow' |
||||
end |
||||
end |
||||
|
||||
context 'with account_id param' do |
||||
let(:params) { { account_id: tom.account.id } } |
||||
|
||||
it 'returns only notifications from specified user', :aggregate_failures do |
||||
subject |
||||
|
||||
expect(response).to have_http_status(200) |
||||
expect(body_json_account_ids.uniq).to eq [tom.account.id.to_s] |
||||
end |
||||
|
||||
def body_json_account_ids |
||||
body_as_json.map { |x| x[:account][:id] } |
||||
end |
||||
end |
||||
|
||||
context 'with invalid account_id param' do |
||||
let(:params) { { account_id: 'foo' } } |
||||
|
||||
it 'returns nothing', :aggregate_failures do |
||||
subject |
||||
|
||||
expect(response).to have_http_status(200) |
||||
expect(body_as_json.size).to eq 0 |
||||
end |
||||
end |
||||
|
||||
context 'with exclude_types param' do |
||||
let(:params) { { exclude_types: %w(mention) } } |
||||
|
||||
it 'returns everything but excluded type', :aggregate_failures do |
||||
subject |
||||
|
||||
expect(response).to have_http_status(200) |
||||
expect(body_as_json.size).to_not eq 0 |
||||
expect(body_json_types.uniq).to_not include 'mention' |
||||
end |
||||
end |
||||
|
||||
context 'with types param' do |
||||
let(:params) { { types: %w(mention) } } |
||||
|
||||
it 'returns only requested type', :aggregate_failures do |
||||
subject |
||||
|
||||
expect(response).to have_http_status(200) |
||||
expect(body_json_types.uniq).to eq ['mention'] |
||||
end |
||||
end |
||||
|
||||
context 'with limit param' do |
||||
let(:params) { { limit: 3 } } |
||||
|
||||
it 'returns the requested number of notifications paginated', :aggregate_failures do |
||||
subject |
||||
|
||||
notifications = user.account.notifications |
||||
|
||||
expect(body_as_json.size).to eq(params[:limit]) |
||||
expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq(api_v1_notifications_url(limit: params[:limit], min_id: notifications.last.id.to_s)) |
||||
expect(response.headers['Link'].find_link(%w(rel next)).href).to eq(api_v1_notifications_url(limit: params[:limit], max_id: notifications[2].id.to_s)) |
||||
end |
||||
end |
||||
|
||||
def body_json_types |
||||
body_as_json.pluck(:type) |
||||
end |
||||
end |
||||
|
||||
describe 'GET /api/v1/notifications/:id' do |
||||
subject do |
||||
get "/api/v1/notifications/#{notification.id}", headers: headers |
||||
end |
||||
|
||||
let(:notification) { Fabricate(:notification, account: user.account) } |
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write write:notifications' |
||||
|
||||
it 'returns http success' do |
||||
subject |
||||
|
||||
expect(response).to have_http_status(200) |
||||
end |
||||
|
||||
context 'when notification belongs to someone else' do |
||||
let(:notification) { Fabricate(:notification) } |
||||
|
||||
it 'returns http not found' do |
||||
subject |
||||
|
||||
expect(response).to have_http_status(404) |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe 'POST /api/v1/notifications/:id/dismiss' do |
||||
subject do |
||||
post "/api/v1/notifications/#{notification.id}/dismiss", headers: headers |
||||
end |
||||
|
||||
let!(:notification) { Fabricate(:notification, account: user.account) } |
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read read:notifications' |
||||
|
||||
it 'destroys the notification' do |
||||
subject |
||||
|
||||
expect(response).to have_http_status(200) |
||||
expect { notification.reload }.to raise_error(ActiveRecord::RecordNotFound) |
||||
end |
||||
|
||||
context 'when notification belongs to someone else' do |
||||
let(:notification) { Fabricate(:notification) } |
||||
|
||||
it 'returns http not found' do |
||||
subject |
||||
|
||||
expect(response).to have_http_status(404) |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe 'POST /api/v1/notifications/clear' do |
||||
subject do |
||||
post '/api/v1/notifications/clear', headers: headers |
||||
end |
||||
|
||||
before do |
||||
Fabricate.times(3, :notification, account: user.account) |
||||
end |
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read read:notifications' |
||||
|
||||
it 'clears notifications for the account' do |
||||
subject |
||||
|
||||
expect(user.account.reload.notifications).to be_empty |
||||
expect(response).to have_http_status(200) |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,22 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
shared_examples 'cacheable response' do |expects_vary: false| |
||||
it 'does not set cookies' do |
||||
expect(response.cookies).to be_empty |
||||
expect(response.headers['Set-Cookies']).to be_nil |
||||
end |
||||
|
||||
it 'does not set sessions' do |
||||
expect(session).to be_empty |
||||
end |
||||
|
||||
if expects_vary |
||||
it 'returns Vary header' do |
||||
expect(response.headers['Vary']).to include(expects_vary) |
||||
end |
||||
end |
||||
|
||||
it 'returns public Cache-Control header' do |
||||
expect(response.headers['Cache-Control']).to include('public') |
||||
end |
||||
end |
Loading…
Reference in new issue