forked from fedi/mastodon
Add types
param to GET /api/v1/notifications
in REST API (#17767)
* Add `types` param to `GET /api/v1/notifications` in REST API * Improve tests
This commit is contained in:
parent
eebafe24a8
commit
e6ffbfb5e7
|
@ -35,13 +35,18 @@ class Api::V1::NotificationsController < Api::BaseController
|
||||||
limit_param(DEFAULT_NOTIFICATIONS_LIMIT),
|
limit_param(DEFAULT_NOTIFICATIONS_LIMIT),
|
||||||
params_slice(:max_id, :since_id, :min_id)
|
params_slice(:max_id, :since_id, :min_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
Notification.preload_cache_collection_target_statuses(notifications) do |target_statuses|
|
Notification.preload_cache_collection_target_statuses(notifications) do |target_statuses|
|
||||||
cache_collection(target_statuses, Status)
|
cache_collection(target_statuses, Status)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def browserable_account_notifications
|
def browserable_account_notifications
|
||||||
current_account.notifications.without_suspended.browserable(exclude_types, from_account)
|
current_account.notifications.without_suspended.browserable(
|
||||||
|
types: Array(browserable_params[:types]),
|
||||||
|
exclude_types: Array(browserable_params[:exclude_types]),
|
||||||
|
from_account_id: browserable_params[:account_id]
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def target_statuses_from_notifications
|
def target_statuses_from_notifications
|
||||||
|
@ -72,17 +77,11 @@ class Api::V1::NotificationsController < Api::BaseController
|
||||||
@notifications.first.id
|
@notifications.first.id
|
||||||
end
|
end
|
||||||
|
|
||||||
def exclude_types
|
def browserable_params
|
||||||
val = params.permit(exclude_types: [])[:exclude_types] || []
|
params.permit(:account_id, types: [], exclude_types: [])
|
||||||
val = [val] unless val.is_a?(Enumerable)
|
|
||||||
val
|
|
||||||
end
|
|
||||||
|
|
||||||
def from_account
|
|
||||||
params[:account_id]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def pagination_params(core_params)
|
def pagination_params(core_params)
|
||||||
params.slice(:limit, :exclude_types).permit(:limit, exclude_types: []).merge(core_params)
|
params.slice(:limit, :account_id, :types, :exclude_types).permit(:limit, :account_id, types: [], exclude_types: []).merge(core_params)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -63,13 +63,6 @@ class Notification < ApplicationRecord
|
||||||
|
|
||||||
scope :without_suspended, -> { joins(:from_account).merge(Account.without_suspended) }
|
scope :without_suspended, -> { joins(:from_account).merge(Account.without_suspended) }
|
||||||
|
|
||||||
scope :browserable, ->(exclude_types = [], account_id = nil) {
|
|
||||||
scope = all
|
|
||||||
scope = where(from_account_id: account_id) if account_id.present?
|
|
||||||
scope = scope.where(type: TYPES - exclude_types.map(&:to_sym)) unless exclude_types.empty?
|
|
||||||
scope
|
|
||||||
}
|
|
||||||
|
|
||||||
def type
|
def type
|
||||||
@type ||= (super || LEGACY_TYPE_CLASS_MAP[activity_type]).to_sym
|
@type ||= (super || LEGACY_TYPE_CLASS_MAP[activity_type]).to_sym
|
||||||
end
|
end
|
||||||
|
@ -90,6 +83,23 @@ class Notification < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
def browserable(types: [], exclude_types: [], from_account_id: nil)
|
||||||
|
requested_types = begin
|
||||||
|
if types.empty?
|
||||||
|
TYPES
|
||||||
|
else
|
||||||
|
types.map(&:to_sym) & TYPES
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
requested_types -= exclude_types.map(&:to_sym)
|
||||||
|
|
||||||
|
all.tap do |scope|
|
||||||
|
scope.merge!(where(from_account_id: from_account_id)) if from_account_id.present?
|
||||||
|
scope.merge!(where(type: requested_types)) unless requested_types.size == TYPES.size
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def preload_cache_collection_target_statuses(notifications, &_block)
|
def preload_cache_collection_target_statuses(notifications, &_block)
|
||||||
notifications.group_by(&:type).each do |type, grouped_notifications|
|
notifications.group_by(&:type).each do |type, grouped_notifications|
|
||||||
associations = TARGET_STATUS_INCLUDES_BY_TYPE[type]
|
associations = TARGET_STATUS_INCLUDES_BY_TYPE[type]
|
||||||
|
|
|
@ -70,23 +70,23 @@ RSpec.describe Api::V1::NotificationsController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes reblog' do
|
it 'includes reblog' do
|
||||||
expect(assigns(:notifications).map(&:activity)).to include(@reblog_of_first_status)
|
expect(body_as_json.map { |x| x[:type] }).to include 'reblog'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes mention' do
|
it 'includes mention' do
|
||||||
expect(assigns(:notifications).map(&:activity)).to include(@mention_from_status)
|
expect(body_as_json.map { |x| x[:type] }).to include 'mention'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes favourite' do
|
it 'includes favourite' do
|
||||||
expect(assigns(:notifications).map(&:activity)).to include(@favourite)
|
expect(body_as_json.map { |x| x[:type] }).to include 'favourite'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes follow' do
|
it 'includes follow' do
|
||||||
expect(assigns(:notifications).map(&:activity)).to include(@follow)
|
expect(body_as_json.map { |x| x[:type] }).to include 'follow'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'from specified user' do
|
describe 'with account_id param' do
|
||||||
before do
|
before do
|
||||||
get :index, params: { account_id: third.account.id }
|
get :index, params: { account_id: third.account.id }
|
||||||
end
|
end
|
||||||
|
@ -95,28 +95,12 @@ RSpec.describe Api::V1::NotificationsController, type: :controller do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes favourite' do
|
it 'returns only notifications from specified user' do
|
||||||
expect(assigns(:notifications).map(&:activity)).to include(@second_favourite)
|
expect(body_as_json.map { |x| x[:account][:id] }.uniq).to eq [third.account.id.to_s]
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'from nonexistent user' do
|
describe 'with invalid account_id param' do
|
||||||
before do
|
before do
|
||||||
get :index, params: { account_id: 'foo' }
|
get :index, params: { account_id: 'foo' }
|
||||||
end
|
end
|
||||||
|
@ -125,54 +109,37 @@ RSpec.describe Api::V1::NotificationsController, type: :controller do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'excludes favourite' do
|
it 'returns nothing' do
|
||||||
expect(assigns(:notifications).map(&:activity)).to_not include(@favourite)
|
expect(body_as_json.size).to eq 0
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'with excluded mentions' do
|
describe 'with excluded_types param' do
|
||||||
before do
|
before do
|
||||||
get :index, params: { exclude_types: ['mention'] }
|
get :index, params: { exclude_types: %w(mention) }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes reblog' do
|
it 'returns everything but excluded type' do
|
||||||
expect(assigns(:notifications).map(&:activity)).to include(@reblog_of_first_status)
|
expect(body_as_json.size).to_not eq 0
|
||||||
|
expect(body_as_json.map { |x| x[:type] }.uniq).to_not include 'mention'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'excludes mention' do
|
describe 'with types param' do
|
||||||
expect(assigns(:notifications).map(&:activity)).to_not include(@mention_from_status)
|
before do
|
||||||
|
get :index, params: { types: %w(mention) }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes favourite' do
|
it 'returns http success' do
|
||||||
expect(assigns(:notifications).map(&:activity)).to include(@favourite)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes third favourite' do
|
it 'returns only requested type' do
|
||||||
expect(assigns(:notifications).map(&:activity)).to include(@second_favourite)
|
expect(body_as_json.map { |x| x[:type] }.uniq).to eq ['mention']
|
||||||
end
|
|
||||||
|
|
||||||
it 'includes follow' do
|
|
||||||
expect(assigns(:notifications).map(&:activity)).to include(@follow)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue