Merge commit '2c0441acd7f943a9873b650cf75d33c73d545acf' into glitch-soc/merge-upstream

pull/2674/head
Claire 2024-03-13 19:16:47 +01:00
commit 06881a8669
96 changed files with 232 additions and 277 deletions

View File

@ -73,6 +73,14 @@ class Api::BaseController < ApplicationController
protected protected
def pagination_max_id
pagination_collection.last.id
end
def pagination_since_id
pagination_collection.first.id
end
def set_pagination_headers(next_path = nil, prev_path = nil) def set_pagination_headers(next_path = nil, prev_path = nil)
links = [] links = []
links << [next_path, [%w(rel next)]] if next_path links << [next_path, [%w(rel next)]] if next_path

View File

@ -51,11 +51,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
@statuses.size == limit_param(DEFAULT_STATUSES_LIMIT) @statuses.size == limit_param(DEFAULT_STATUSES_LIMIT)
end end
def pagination_max_id def pagination_collection
@statuses.last.id @statuses
end
def pagination_since_id
@statuses.first.id
end end
end end

View File

@ -137,12 +137,8 @@ class Api::V1::Admin::AccountsController < Api::BaseController
api_v1_admin_accounts_url(pagination_params(min_id: pagination_since_id)) unless @accounts.empty? api_v1_admin_accounts_url(pagination_params(min_id: pagination_since_id)) unless @accounts.empty?
end end
def pagination_max_id def pagination_collection
@accounts.last.id @accounts
end
def pagination_since_id
@accounts.first.id
end end
def records_continue? def records_continue?

View File

@ -77,12 +77,8 @@ class Api::V1::Admin::CanonicalEmailBlocksController < Api::BaseController
api_v1_admin_canonical_email_blocks_url(pagination_params(min_id: pagination_since_id)) unless @canonical_email_blocks.empty? api_v1_admin_canonical_email_blocks_url(pagination_params(min_id: pagination_since_id)) unless @canonical_email_blocks.empty?
end end
def pagination_max_id def pagination_collection
@canonical_email_blocks.last.id @canonical_email_blocks
end
def pagination_since_id
@canonical_email_blocks.first.id
end end
def records_continue? def records_continue?

View File

@ -73,12 +73,8 @@ class Api::V1::Admin::DomainAllowsController < Api::BaseController
api_v1_admin_domain_allows_url(pagination_params(min_id: pagination_since_id)) unless @domain_allows.empty? api_v1_admin_domain_allows_url(pagination_params(min_id: pagination_since_id)) unless @domain_allows.empty?
end end
def pagination_max_id def pagination_collection
@domain_allows.last.id @domain_allows
end
def pagination_since_id
@domain_allows.first.id
end end
def records_continue? def records_continue?

View File

@ -84,12 +84,8 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
api_v1_admin_domain_blocks_url(pagination_params(min_id: pagination_since_id)) unless @domain_blocks.empty? api_v1_admin_domain_blocks_url(pagination_params(min_id: pagination_since_id)) unless @domain_blocks.empty?
end end
def pagination_max_id def pagination_collection
@domain_blocks.last.id @domain_blocks
end
def pagination_since_id
@domain_blocks.first.id
end end
def records_continue? def records_continue?

View File

@ -70,12 +70,8 @@ class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController
api_v1_admin_email_domain_blocks_url(pagination_params(min_id: pagination_since_id)) unless @email_domain_blocks.empty? api_v1_admin_email_domain_blocks_url(pagination_params(min_id: pagination_since_id)) unless @email_domain_blocks.empty?
end end
def pagination_max_id def pagination_collection
@email_domain_blocks.last.id @email_domain_blocks
end
def pagination_since_id
@email_domain_blocks.first.id
end end
def records_continue? def records_continue?

View File

@ -75,12 +75,8 @@ class Api::V1::Admin::IpBlocksController < Api::BaseController
api_v1_admin_ip_blocks_url(pagination_params(min_id: pagination_since_id)) unless @ip_blocks.empty? api_v1_admin_ip_blocks_url(pagination_params(min_id: pagination_since_id)) unless @ip_blocks.empty?
end end
def pagination_max_id def pagination_collection
@ip_blocks.last.id @ip_blocks
end
def pagination_since_id
@ip_blocks.first.id
end end
def records_continue? def records_continue?

View File

@ -101,12 +101,8 @@ class Api::V1::Admin::ReportsController < Api::BaseController
api_v1_admin_reports_url(pagination_params(min_id: pagination_since_id)) unless @reports.empty? api_v1_admin_reports_url(pagination_params(min_id: pagination_since_id)) unless @reports.empty?
end end
def pagination_max_id def pagination_collection
@reports.last.id @reports
end
def pagination_since_id
@reports.first.id
end end
def records_continue? def records_continue?

View File

@ -56,12 +56,8 @@ class Api::V1::Admin::TagsController < Api::BaseController
api_v1_admin_tags_url(pagination_params(min_id: pagination_since_id)) unless @tags.empty? api_v1_admin_tags_url(pagination_params(min_id: pagination_since_id)) unless @tags.empty?
end end
def pagination_max_id def pagination_collection
@tags.last.id @tags
end
def pagination_since_id
@tags.first.id
end end
def records_continue? def records_continue?

View File

@ -54,12 +54,8 @@ class Api::V1::Admin::Trends::Links::PreviewCardProvidersController < Api::BaseC
api_v1_admin_trends_links_preview_card_providers_url(pagination_params(min_id: pagination_since_id)) unless @providers.empty? api_v1_admin_trends_links_preview_card_providers_url(pagination_params(min_id: pagination_since_id)) unless @providers.empty?
end end
def pagination_max_id def pagination_collection
@providers.last.id @providers
end
def pagination_since_id
@providers.first.id
end end
def records_continue? def records_continue?

View File

@ -40,12 +40,8 @@ class Api::V1::BlocksController < Api::BaseController
api_v1_blocks_url pagination_params(since_id: pagination_since_id) unless paginated_blocks.empty? api_v1_blocks_url pagination_params(since_id: pagination_since_id) unless paginated_blocks.empty?
end end
def pagination_max_id def pagination_collection
paginated_blocks.last.id paginated_blocks
end
def pagination_since_id
paginated_blocks.first.id
end end
def records_continue? def records_continue?

View File

@ -43,12 +43,8 @@ class Api::V1::BookmarksController < Api::BaseController
api_v1_bookmarks_url pagination_params(min_id: pagination_since_id) unless results.empty? api_v1_bookmarks_url pagination_params(min_id: pagination_since_id) unless results.empty?
end end
def pagination_max_id def pagination_collection
results.last.id results
end
def pagination_since_id
results.first.id
end end
def records_continue? def records_continue?

View File

@ -41,12 +41,8 @@ class Api::V1::Crypto::EncryptedMessagesController < Api::BaseController
api_v1_crypto_encrypted_messages_url pagination_params(min_id: pagination_since_id) unless @encrypted_messages.empty? api_v1_crypto_encrypted_messages_url pagination_params(min_id: pagination_since_id) unless @encrypted_messages.empty?
end end
def pagination_max_id def pagination_collection
@encrypted_messages.last.id @encrypted_messages
end
def pagination_since_id
@encrypted_messages.first.id
end end
def records_continue? def records_continue?

View File

@ -50,12 +50,8 @@ class Api::V1::DomainBlocksController < Api::BaseController
api_v1_domain_blocks_url pagination_params(since_id: pagination_since_id) unless @blocks.empty? api_v1_domain_blocks_url pagination_params(since_id: pagination_since_id) unless @blocks.empty?
end end
def pagination_max_id def pagination_collection
@blocks.last.id @blocks
end
def pagination_since_id
@blocks.first.id
end end
def records_continue? def records_continue?

View File

@ -44,12 +44,8 @@ class Api::V1::EndorsementsController < Api::BaseController
api_v1_endorsements_url pagination_params(since_id: pagination_since_id) unless @accounts.empty? api_v1_endorsements_url pagination_params(since_id: pagination_since_id) unless @accounts.empty?
end end
def pagination_max_id def pagination_collection
@accounts.last.id @accounts
end
def pagination_since_id
@accounts.first.id
end end
def records_continue? def records_continue?

View File

@ -43,12 +43,8 @@ class Api::V1::FavouritesController < Api::BaseController
api_v1_favourites_url pagination_params(min_id: pagination_since_id) unless results.empty? api_v1_favourites_url pagination_params(min_id: pagination_since_id) unless results.empty?
end end
def pagination_max_id def pagination_collection
results.last.id results
end
def pagination_since_id
results.first.id
end end
def records_continue? def records_continue?

View File

@ -34,12 +34,8 @@ class Api::V1::FollowedTagsController < Api::BaseController
api_v1_followed_tags_url pagination_params(since_id: pagination_since_id) unless @results.empty? api_v1_followed_tags_url pagination_params(since_id: pagination_since_id) unless @results.empty?
end end
def pagination_max_id def pagination_collection
@results.last.id @results
end
def pagination_since_id
@results.first.id
end end
def records_continue? def records_continue?

View File

@ -71,12 +71,8 @@ class Api::V1::Lists::AccountsController < Api::BaseController
api_v1_list_accounts_url pagination_params(since_id: pagination_since_id) unless @accounts.empty? api_v1_list_accounts_url pagination_params(since_id: pagination_since_id) unless @accounts.empty?
end end
def pagination_max_id def pagination_collection
@accounts.last.id @accounts
end
def pagination_since_id
@accounts.first.id
end end
def records_continue? def records_continue?

View File

@ -40,12 +40,8 @@ class Api::V1::MutesController < Api::BaseController
api_v1_mutes_url pagination_params(since_id: pagination_since_id) unless paginated_mutes.empty? api_v1_mutes_url pagination_params(since_id: pagination_since_id) unless paginated_mutes.empty?
end end
def pagination_max_id def pagination_collection
paginated_mutes.last.id paginated_mutes
end
def pagination_since_id
paginated_mutes.first.id
end end
def records_continue? def records_continue?

View File

@ -79,12 +79,8 @@ class Api::V1::NotificationsController < Api::BaseController
api_v1_notifications_url pagination_params(min_id: pagination_since_id) unless @notifications.empty? api_v1_notifications_url pagination_params(min_id: pagination_since_id) unless @notifications.empty?
end end
def pagination_max_id def pagination_collection
@notifications.last.id @notifications
end
def pagination_since_id
@notifications.first.id
end end
def browserable_params def browserable_params

View File

@ -63,11 +63,7 @@ class Api::V1::ScheduledStatusesController < Api::BaseController
@statuses.size == limit_param(DEFAULT_STATUSES_LIMIT) @statuses.size == limit_param(DEFAULT_STATUSES_LIMIT)
end end
def pagination_max_id def pagination_collection
@statuses.last.id @statuses
end
def pagination_since_id
@statuses.first.id
end end
end end

View File

@ -9,12 +9,8 @@ class Api::V1::Timelines::BaseController < Api::BaseController
set_pagination_headers(next_path, prev_path) set_pagination_headers(next_path, prev_path)
end end
def pagination_max_id def pagination_collection
@statuses.last.id @statuses
end
def pagination_since_id
@statuses.first.id
end end
def next_path_params def next_path_params

View File

@ -1,5 +1,3 @@
import Rails from '@rails/ujs';
export const logOut = () => { export const logOut = () => {
const form = document.createElement('form'); const form = document.createElement('form');
@ -9,13 +7,18 @@ export const logOut = () => {
methodInput.setAttribute('type', 'hidden'); methodInput.setAttribute('type', 'hidden');
form.appendChild(methodInput); form.appendChild(methodInput);
const csrfToken = Rails.csrfToken(); const csrfToken = document.querySelector<HTMLMetaElement>(
const csrfParam = Rails.csrfParam(); 'meta[name=csrf-token]',
);
const csrfParam = document.querySelector<HTMLMetaElement>(
'meta[name=csrf-param]',
);
if (csrfParam && csrfToken) { if (csrfParam && csrfToken) {
const csrfInput = document.createElement('input'); const csrfInput = document.createElement('input');
csrfInput.setAttribute('name', csrfParam); csrfInput.setAttribute('name', csrfParam.content);
csrfInput.setAttribute('value', csrfToken); csrfInput.setAttribute('value', csrfToken.content);
csrfInput.setAttribute('type', 'hidden'); csrfInput.setAttribute('type', 'hidden');
form.appendChild(csrfInput); form.appendChild(csrfInput);
} }

View File

@ -37,11 +37,11 @@ class Admin::Metrics::Dimension::InstanceLanguagesDimension < Admin::Metrics::Di
end end
def earliest_status_id def earliest_status_id
Mastodon::Snowflake.id_at(@start_at, with_random: false) Mastodon::Snowflake.id_at(@start_at.beginning_of_day, with_random: false)
end end
def latest_status_id def latest_status_id
Mastodon::Snowflake.id_at(@end_at, with_random: false) Mastodon::Snowflake.id_at(@end_at.end_of_day, with_random: false)
end end
def params def params

View File

@ -30,10 +30,10 @@ class Admin::Metrics::Dimension::ServersDimension < Admin::Metrics::Dimension::B
end end
def earliest_status_id def earliest_status_id
Mastodon::Snowflake.id_at(@start_at) Mastodon::Snowflake.id_at(@start_at.beginning_of_day, with_random: false)
end end
def latest_status_id def latest_status_id
Mastodon::Snowflake.id_at(@end_at) Mastodon::Snowflake.id_at(@end_at.end_of_day, with_random: false)
end end
end end

View File

@ -40,11 +40,11 @@ class Admin::Metrics::Dimension::TagLanguagesDimension < Admin::Metrics::Dimensi
end end
def earliest_status_id def earliest_status_id
Mastodon::Snowflake.id_at(@start_at, with_random: false) Mastodon::Snowflake.id_at(@start_at.beginning_of_day, with_random: false)
end end
def latest_status_id def latest_status_id
Mastodon::Snowflake.id_at(@end_at, with_random: false) Mastodon::Snowflake.id_at(@end_at.end_of_day, with_random: false)
end end
def params def params

View File

@ -40,11 +40,11 @@ class Admin::Metrics::Dimension::TagServersDimension < Admin::Metrics::Dimension
end end
def earliest_status_id def earliest_status_id
Mastodon::Snowflake.id_at(@start_at, with_random: false) Mastodon::Snowflake.id_at(@start_at.beginning_of_day, with_random: false)
end end
def latest_status_id def latest_status_id
Mastodon::Snowflake.id_at(@end_at, with_random: false) Mastodon::Snowflake.id_at(@end_at.end_of_day, with_random: false)
end end
def params def params

View File

@ -51,11 +51,11 @@ class Admin::Metrics::Measure::InstanceStatusesMeasure < Admin::Metrics::Measure
end end
def earliest_status_id def earliest_status_id
Mastodon::Snowflake.id_at(@start_at, with_random: false) Mastodon::Snowflake.id_at(@start_at.beginning_of_day, with_random: false)
end end
def latest_status_id def latest_status_id
Mastodon::Snowflake.id_at(@end_at, with_random: false) Mastodon::Snowflake.id_at(@end_at.end_of_day, with_random: false)
end end
def time_period def time_period

View File

@ -50,6 +50,7 @@ class TextFormatter
class << self class << self
include ERB::Util include ERB::Util
include ActionView::Helpers::TagHelper
def shortened_link(url, rel_me: false) def shortened_link(url, rel_me: false)
url = Addressable::URI.parse(url).to_s url = Addressable::URI.parse(url).to_s
@ -60,9 +61,11 @@ class TextFormatter
suffix = url[prefix.length + 30..] suffix = url[prefix.length + 30..]
cutoff = url[prefix.length..].length > 30 cutoff = url[prefix.length..].length > 30
<<~HTML.squish.html_safe # rubocop:disable Rails/OutputSafety tag.a href: url, target: '_blank', rel: rel.join(' '), translate: 'no' do
<a href="#{h(url)}" target="_blank" rel="#{rel.join(' ')}" translate="no"><span class="invisible">#{h(prefix)}</span><span class="#{cutoff ? 'ellipsis' : ''}">#{h(display_url)}</span><span class="invisible">#{h(suffix)}</span></a> tag.span(prefix, class: 'invisible') +
HTML tag.span(display_url, class: (cutoff ? 'ellipsis' : '')) +
tag.span(suffix, class: 'invisible')
end
rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
h(url) h(url)
end end

View File

@ -41,7 +41,7 @@ class CustomFilter < ApplicationRecord
validates :title, :context, presence: true validates :title, :context, presence: true
validate :context_must_be_valid validate :context_must_be_valid
before_validation :clean_up_contexts normalizes :context, with: ->(context) { context.map(&:strip).filter_map(&:presence) }
before_save :prepare_cache_invalidation! before_save :prepare_cache_invalidation!
before_destroy :prepare_cache_invalidation! before_destroy :prepare_cache_invalidation!
@ -114,10 +114,6 @@ class CustomFilter < ApplicationRecord
private private
def clean_up_contexts
self.context = Array(context).map(&:strip).filter_map(&:presence)
end
def context_must_be_valid def context_must_be_valid
errors.add(:context, I18n.t('filters.errors.invalid_context')) if invalid_context_value? errors.add(:context, I18n.t('filters.errors.invalid_context')) if invalid_context_value?
end end

View File

@ -50,7 +50,7 @@ RSpec.describe ActivityPub::Activity::Add do
end end
it 'fetches the status and pins it' do it 'fetches the status and pins it' do
allow(service_stub).to receive(:call) do |uri, id: true, on_behalf_of: nil, request_id: nil| # rubocop:disable Lint/UnusedBlockArgument allow(service_stub).to receive(:call) do |uri, id: true, on_behalf_of: nil, **|
expect(uri).to eq 'https://example.com/unknown' expect(uri).to eq 'https://example.com/unknown'
expect(id).to be true expect(id).to be true
expect(on_behalf_of&.following?(sender)).to be true expect(on_behalf_of&.following?(sender)).to be true
@ -64,7 +64,7 @@ RSpec.describe ActivityPub::Activity::Add do
context 'when there is no local follower' do context 'when there is no local follower' do
it 'tries to fetch the status' do it 'tries to fetch the status' do
allow(service_stub).to receive(:call) do |uri, id: true, on_behalf_of: nil, request_id: nil| # rubocop:disable Lint/UnusedBlockArgument allow(service_stub).to receive(:call) do |uri, id: true, on_behalf_of: nil, **|
expect(uri).to eq 'https://example.com/unknown' expect(uri).to eq 'https://example.com/unknown'
expect(id).to be true expect(id).to be true
expect(on_behalf_of).to be_nil expect(on_behalf_of).to be_nil

View File

@ -32,4 +32,12 @@ RSpec.describe CustomFilter do
expect(record).to model_have_error_on_field(:context) expect(record).to model_have_error_on_field(:context)
end end
end end
describe 'Normalizations' do
it 'cleans up context values' do
record = described_class.new(context: ['home', 'notifications', 'public ', ''])
expect(record.context).to eq(%w(home notifications public))
end
end
end end

View File

@ -21,6 +21,7 @@ require 'paperclip/matchers'
require 'capybara/rspec' require 'capybara/rspec'
require 'chewy/rspec' require 'chewy/rspec'
require 'email_spec/rspec' require 'email_spec/rspec'
require 'test_prof/recipes/rspec/before_all'
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f } Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }

View File

@ -2,25 +2,20 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe Api::V2::Filters::KeywordsController do RSpec.describe 'API V2 Filters Keywords' do
render_views
let(:user) { Fabricate(:user) } let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:filter) { Fabricate(:custom_filter, account: user.account) } let(:filter) { Fabricate(:custom_filter, account: user.account) }
let(:other_user) { Fabricate(:user) } let(:other_user) { Fabricate(:user) }
let(:other_filter) { Fabricate(:custom_filter, account: other_user.account) } let(:other_filter) { Fabricate(:custom_filter, account: other_user.account) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
before do describe 'GET /api/v2/filters/:filter_id/keywords' do
allow(controller).to receive(:doorkeeper_token) { token }
end
describe 'GET #index' do
let(:scopes) { 'read:filters' } let(:scopes) { 'read:filters' }
let!(:keyword) { Fabricate(:custom_filter_keyword, custom_filter: filter) } let!(:keyword) { Fabricate(:custom_filter_keyword, custom_filter: filter) }
it 'returns http success' do it 'returns http success' do
get :index, params: { filter_id: filter.id } get "/api/v2/filters/#{filter.id}/keywords", headers: headers
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(body_as_json) expect(body_as_json)
.to contain_exactly( .to contain_exactly(
@ -30,18 +25,18 @@ RSpec.describe Api::V2::Filters::KeywordsController do
context "when trying to access another's user filters" do context "when trying to access another's user filters" do
it 'returns http not found' do it 'returns http not found' do
get :index, params: { filter_id: other_filter.id } get "/api/v2/filters/#{other_filter.id}/keywords", headers: headers
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
end end
end end
describe 'POST #create' do describe 'POST /api/v2/filters/:filter_id/keywords' do
let(:scopes) { 'write:filters' } let(:scopes) { 'write:filters' }
let(:filter_id) { filter.id } let(:filter_id) { filter.id }
before do before do
post :create, params: { filter_id: filter_id, keyword: 'magic', whole_word: false } post "/api/v2/filters/#{filter_id}/keywords", headers: headers, params: { keyword: 'magic', whole_word: false }
end end
it 'creates a filter', :aggregate_failures do it 'creates a filter', :aggregate_failures do
@ -65,12 +60,12 @@ RSpec.describe Api::V2::Filters::KeywordsController do
end end
end end
describe 'GET #show' do describe 'GET /api/v2/filters/keywords/:id' do
let(:scopes) { 'read:filters' } let(:scopes) { 'read:filters' }
let(:keyword) { Fabricate(:custom_filter_keyword, keyword: 'foo', whole_word: false, custom_filter: filter) } let(:keyword) { Fabricate(:custom_filter_keyword, keyword: 'foo', whole_word: false, custom_filter: filter) }
before do before do
get :show, params: { id: keyword.id } get "/api/v2/filters/keywords/#{keyword.id}", headers: headers
end end
it 'responds with the keyword', :aggregate_failures do it 'responds with the keyword', :aggregate_failures do
@ -90,12 +85,12 @@ RSpec.describe Api::V2::Filters::KeywordsController do
end end
end end
describe 'PUT #update' do describe 'PUT /api/v2/filters/keywords/:id' do
let(:scopes) { 'write:filters' } let(:scopes) { 'write:filters' }
let(:keyword) { Fabricate(:custom_filter_keyword, custom_filter: filter) } let(:keyword) { Fabricate(:custom_filter_keyword, custom_filter: filter) }
before do before do
get :update, params: { id: keyword.id, keyword: 'updated' } put "/api/v2/filters/keywords/#{keyword.id}", headers: headers, params: { keyword: 'updated' }
end end
it 'updates the keyword', :aggregate_failures do it 'updates the keyword', :aggregate_failures do
@ -113,12 +108,12 @@ RSpec.describe Api::V2::Filters::KeywordsController do
end end
end end
describe 'DELETE #destroy' do describe 'DELETE /api/v2/filters/keywords/:id' do
let(:scopes) { 'write:filters' } let(:scopes) { 'write:filters' }
let(:keyword) { Fabricate(:custom_filter_keyword, custom_filter: filter) } let(:keyword) { Fabricate(:custom_filter_keyword, custom_filter: filter) }
before do before do
delete :destroy, params: { id: keyword.id } delete "/api/v2/filters/keywords/#{keyword.id}", headers: headers
end end
it 'destroys the keyword', :aggregate_failures do it 'destroys the keyword', :aggregate_failures do

View File

@ -2,25 +2,20 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe Api::V2::Filters::StatusesController do RSpec.describe 'API V2 Filters Statuses' do
render_views
let(:user) { Fabricate(:user) } let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:filter) { Fabricate(:custom_filter, account: user.account) } let(:filter) { Fabricate(:custom_filter, account: user.account) }
let(:other_user) { Fabricate(:user) } let(:other_user) { Fabricate(:user) }
let(:other_filter) { Fabricate(:custom_filter, account: other_user.account) } let(:other_filter) { Fabricate(:custom_filter, account: other_user.account) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
before do describe 'GET /api/v2/filters/:filter_id/statuses' do
allow(controller).to receive(:doorkeeper_token) { token }
end
describe 'GET #index' do
let(:scopes) { 'read:filters' } let(:scopes) { 'read:filters' }
let!(:status_filter) { Fabricate(:custom_filter_status, custom_filter: filter) } let!(:status_filter) { Fabricate(:custom_filter_status, custom_filter: filter) }
it 'returns http success' do it 'returns http success' do
get :index, params: { filter_id: filter.id } get "/api/v2/filters/#{filter.id}/statuses", headers: headers
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(body_as_json) expect(body_as_json)
.to contain_exactly( .to contain_exactly(
@ -30,7 +25,7 @@ RSpec.describe Api::V2::Filters::StatusesController do
context "when trying to access another's user filters" do context "when trying to access another's user filters" do
it 'returns http not found' do it 'returns http not found' do
get :index, params: { filter_id: other_filter.id } get "/api/v2/filters/#{other_filter.id}/statuses", headers: headers
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
end end
@ -42,7 +37,7 @@ RSpec.describe Api::V2::Filters::StatusesController do
let!(:status) { Fabricate(:status) } let!(:status) { Fabricate(:status) }
before do before do
post :create, params: { filter_id: filter_id, status_id: status.id } post "/api/v2/filters/#{filter_id}/statuses", headers: headers, params: { status_id: status.id }
end end
it 'creates a filter', :aggregate_failures do it 'creates a filter', :aggregate_failures do
@ -65,12 +60,12 @@ RSpec.describe Api::V2::Filters::StatusesController do
end end
end end
describe 'GET #show' do describe 'GET /api/v2/filters/statuses/:id' do
let(:scopes) { 'read:filters' } let(:scopes) { 'read:filters' }
let!(:status_filter) { Fabricate(:custom_filter_status, custom_filter: filter) } let!(:status_filter) { Fabricate(:custom_filter_status, custom_filter: filter) }
before do before do
get :show, params: { id: status_filter.id } get "/api/v2/filters/statuses/#{status_filter.id}", headers: headers
end end
it 'responds with the filter', :aggregate_failures do it 'responds with the filter', :aggregate_failures do
@ -89,12 +84,12 @@ RSpec.describe Api::V2::Filters::StatusesController do
end end
end end
describe 'DELETE #destroy' do describe 'DELETE /api/v2/filters/statuses/:id' do
let(:scopes) { 'write:filters' } let(:scopes) { 'write:filters' }
let(:status_filter) { Fabricate(:custom_filter_status, custom_filter: filter) } let(:status_filter) { Fabricate(:custom_filter_status, custom_filter: filter) }
before do before do
delete :destroy, params: { id: status_filter.id } delete "/api/v2/filters/statuses/#{status_filter.id}", headers: headers
end end
it 'destroys the filter', :aggregate_failures do it 'destroys the filter', :aggregate_failures do

View File

@ -39,7 +39,7 @@ module TestEndpoints
/api/v1/accounts/lookup?acct=alice /api/v1/accounts/lookup?acct=alice
/api/v1/statuses/110224538612341312 /api/v1/statuses/110224538612341312
/api/v1/statuses/110224538612341312/context /api/v1/statuses/110224538612341312/context
/api/v1/polls/12345 /api/v1/polls/123456789
/api/v1/trends/statuses /api/v1/trends/statuses
/api/v1/directory /api/v1/directory
).freeze ).freeze
@ -166,14 +166,18 @@ describe 'Caching behavior' do
ActionController::Base.allow_forgery_protection = old ActionController::Base.allow_forgery_protection = old
end end
let(:alice) { Fabricate(:account, username: 'alice') } let(:alice) { Account.find_by(username: 'alice') }
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Moderator')) } let(:user) { User.find_by(email: 'user@host.example') }
let(:token) { Doorkeeper::AccessToken.find_by(resource_owner_id: user.id) }
before do before_all do
status = Fabricate(:status, account: alice, id: '110224538612341312') alice = Fabricate(:account, username: 'alice')
Fabricate(:status, account: alice, id: '110224538643211312', visibility: :private) user = Fabricate(:user, email: 'user@host.example', role: UserRole.find_by(name: 'Moderator'))
status = Fabricate(:status, account: alice, id: 110_224_538_612_341_312)
Fabricate(:status, account: alice, id: 110_224_538_643_211_312, visibility: :private)
Fabricate(:invite, code: 'abcdef') Fabricate(:invite, code: 'abcdef')
Fabricate(:poll, status: status, account: alice, id: '12345') Fabricate(:poll, status: status, account: alice, id: 123_456_789)
Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read')
user.account.follow!(alice) user.account.follow!(alice)
end end
@ -321,8 +325,6 @@ describe 'Caching behavior' do
end end
context 'with an auth token' do context 'with an auth token' do
let!(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') }
TestEndpoints::ALWAYS_CACHED.each do |endpoint| TestEndpoints::ALWAYS_CACHED.each do |endpoint|
describe endpoint do describe endpoint do
before do before do
@ -585,8 +587,6 @@ describe 'Caching behavior' do
end end
context 'with an auth token' do context 'with an auth token' do
let!(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') }
TestEndpoints::ALWAYS_CACHED.each do |endpoint| TestEndpoints::ALWAYS_CACHED.each do |endpoint|
describe endpoint do describe endpoint do
before do before do

View File

@ -3,25 +3,38 @@
require 'rails_helper' require 'rails_helper'
describe 'Content-Security-Policy' do describe 'Content-Security-Policy' do
it 'sets the expected CSP headers' do before { allow(SecureRandom).to receive(:base64).with(16).and_return('ZbA+JmE7+bK8F5qvADZHuQ==') }
allow(SecureRandom).to receive(:base64).with(16).and_return('ZbA+JmE7+bK8F5qvADZHuQ==')
it 'sets the expected CSP headers' do
get '/' get '/'
expect(response.headers['Content-Security-Policy'].split(';').map(&:strip)).to contain_exactly(
"base-uri 'none'", expect(response_csp_headers)
"default-src 'none'", .to match_array(expected_csp_headers)
"frame-ancestors 'none'", end
"font-src 'self' https://cb6e6126.ngrok.io",
"img-src 'self' data: blob: https://cb6e6126.ngrok.io", def response_csp_headers
"style-src 'self' https://cb6e6126.ngrok.io 'nonce-ZbA+JmE7+bK8F5qvADZHuQ=='", response
"media-src 'self' data: https://cb6e6126.ngrok.io", .headers['Content-Security-Policy']
"frame-src 'self' https:", .split(';')
"manifest-src 'self' https://cb6e6126.ngrok.io", .map(&:strip)
"form-action 'self'", end
"child-src 'self' blob: https://cb6e6126.ngrok.io",
"worker-src 'self' blob: https://cb6e6126.ngrok.io", def expected_csp_headers
"connect-src 'self' data: blob: https://cb6e6126.ngrok.io ws://cb6e6126.ngrok.io:4000", <<~CSP.split("\n").map(&:strip)
"script-src 'self' https://cb6e6126.ngrok.io 'wasm-unsafe-eval'" base-uri 'none'
) child-src 'self' blob: https://cb6e6126.ngrok.io
connect-src 'self' data: blob: https://cb6e6126.ngrok.io ws://cb6e6126.ngrok.io:4000
default-src 'none'
font-src 'self' https://cb6e6126.ngrok.io
form-action 'self'
frame-ancestors 'none'
frame-src 'self' https:
img-src 'self' data: blob: https://cb6e6126.ngrok.io
manifest-src 'self' https://cb6e6126.ngrok.io
media-src 'self' data: https://cb6e6126.ngrok.io
script-src 'self' https://cb6e6126.ngrok.io 'wasm-unsafe-eval'
style-src 'self' https://cb6e6126.ngrok.io 'nonce-ZbA+JmE7+bK8F5qvADZHuQ=='
worker-src 'self' blob: https://cb6e6126.ngrok.io
CSP
end end
end end

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
describe AccountSearchService, type: :service do describe AccountSearchService do
describe '#call' do describe '#call' do
context 'with a query to ignore' do context 'with a query to ignore' do
it 'returns empty array for missing query' do it 'returns empty array for missing query' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
describe AccountStatusesCleanupService, type: :service do describe AccountStatusesCleanupService do
let(:account) { Fabricate(:account, username: 'alice', domain: nil) } let(:account) { Fabricate(:account, username: 'alice', domain: nil) }
let(:account_policy) { Fabricate(:account_statuses_cleanup_policy, account: account) } let(:account_policy) { Fabricate(:account_statuses_cleanup_policy, account: account) }
let!(:unrelated_status) { Fabricate(:status, created_at: 3.years.ago) } let!(:unrelated_status) { Fabricate(:status, created_at: 3.years.ago) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do RSpec.describe ActivityPub::FetchFeaturedCollectionService do
subject { described_class.new } subject { described_class.new }
let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/account', featured_collection_url: 'https://example.com/account/pinned') } let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/account', featured_collection_url: 'https://example.com/account/pinned') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service do RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService do
subject { described_class.new } subject { described_class.new }
let(:collection_url) { 'https://example.com/account/tags' } let(:collection_url) { 'https://example.com/account/tags' }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do RSpec.describe ActivityPub::FetchRemoteAccountService do
subject { described_class.new } subject { described_class.new }
let!(:actor) do let!(:actor) do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do RSpec.describe ActivityPub::FetchRemoteActorService do
subject { described_class.new } subject { described_class.new }
let!(:actor) do let!(:actor) do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do RSpec.describe ActivityPub::FetchRemoteKeyService do
subject { described_class.new } subject { described_class.new }
let(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } let(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do RSpec.describe ActivityPub::FetchRemoteStatusService do
include ActionView::Helpers::TextHelper include ActionView::Helpers::TextHelper
subject { described_class.new } subject { described_class.new }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::FetchRepliesService, type: :service do RSpec.describe ActivityPub::FetchRepliesService do
subject { described_class.new } subject { described_class.new }
let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account') } let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::ProcessAccountService, type: :service do RSpec.describe ActivityPub::ProcessAccountService do
subject { described_class.new } subject { described_class.new }
context 'with property values, an avatar, and a profile header' do context 'with property values, an avatar, and a profile header' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::ProcessCollectionService, type: :service do RSpec.describe ActivityPub::ProcessCollectionService do
subject { described_class.new } subject { described_class.new }
let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account') } let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account') }

View File

@ -6,7 +6,7 @@ def poll_option_json(name, votes)
{ type: 'Note', name: name, replies: { type: 'Collection', totalItems: votes } } { type: 'Note', name: name, replies: { type: 'Collection', totalItems: votes } }
end end
RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do RSpec.describe ActivityPub::ProcessStatusUpdateService do
subject { described_class.new } subject { described_class.new }
let!(:status) { Fabricate(:status, text: 'Hello world', account: Fabricate(:account, domain: 'example.com')) } let!(:status) { Fabricate(:status, text: 'Hello world', account: Fabricate(:account, domain: 'example.com')) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do RSpec.describe ActivityPub::SynchronizeFollowersService do
subject { described_class.new } subject { described_class.new }
let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account', inbox_url: 'http://example.com/inbox') } let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account', inbox_url: 'http://example.com/inbox') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe AfterBlockDomainFromAccountService, type: :service do RSpec.describe AfterBlockDomainFromAccountService do
subject { described_class.new } subject { described_class.new }
let!(:wolf) { Fabricate(:account, username: 'wolf', domain: 'evil.org', inbox_url: 'https://evil.org/inbox', protocol: :activitypub) } let!(:wolf) { Fabricate(:account, username: 'wolf', domain: 'evil.org', inbox_url: 'https://evil.org/inbox', protocol: :activitypub) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe AfterBlockService, type: :service do RSpec.describe AfterBlockService do
subject { described_class.new.call(account, target_account) } subject { described_class.new.call(account, target_account) }
let(:account) { Fabricate(:account) } let(:account) { Fabricate(:account) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe AppSignUpService, type: :service do RSpec.describe AppSignUpService do
subject { described_class.new } subject { described_class.new }
let(:app) { Fabricate(:application, scopes: 'read write') } let(:app) { Fabricate(:application, scopes: 'read write') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe AuthorizeFollowService, type: :service do RSpec.describe AuthorizeFollowService do
subject { described_class.new } subject { described_class.new }
let(:sender) { Fabricate(:account, username: 'alice') } let(:sender) { Fabricate(:account, username: 'alice') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe BackupService, type: :service do RSpec.describe BackupService do
subject(:service_call) { described_class.new.call(backup) } subject(:service_call) { described_class.new.call(backup) }
let!(:user) { Fabricate(:user) } let!(:user) { Fabricate(:user) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe BatchedRemoveStatusService, :sidekiq_inline, type: :service do RSpec.describe BatchedRemoveStatusService, :sidekiq_inline do
subject { described_class.new } subject { described_class.new }
let!(:alice) { Fabricate(:account) } let!(:alice) { Fabricate(:account) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe BlockDomainService, type: :service do RSpec.describe BlockDomainService do
subject { described_class.new } subject { described_class.new }
let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') } let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe BlockService, type: :service do RSpec.describe BlockService do
subject { described_class.new } subject { described_class.new }
let(:sender) { Fabricate(:account, username: 'alice') } let(:sender) { Fabricate(:account, username: 'alice') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe BootstrapTimelineService, type: :service do RSpec.describe BootstrapTimelineService do
subject { described_class.new } subject { described_class.new }
context 'when the new user has registered from an invite' do context 'when the new user has registered from an invite' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ClearDomainMediaService, type: :service do RSpec.describe ClearDomainMediaService do
subject { described_class.new } subject { described_class.new }
let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') } let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe DeleteAccountService, type: :service do RSpec.describe DeleteAccountService do
shared_examples 'common behavior' do shared_examples 'common behavior' do
subject { described_class.new.call(account) } subject { described_class.new.call(account) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe FanOutOnWriteService, type: :service do RSpec.describe FanOutOnWriteService do
subject { described_class.new } subject { described_class.new }
let(:last_active_at) { Time.now.utc } let(:last_active_at) { Time.now.utc }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe FavouriteService, type: :service do RSpec.describe FavouriteService do
subject { described_class.new } subject { described_class.new }
let(:sender) { Fabricate(:account, username: 'alice') } let(:sender) { Fabricate(:account, username: 'alice') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe FetchLinkCardService, type: :service do RSpec.describe FetchLinkCardService do
subject { described_class.new } subject { described_class.new }
let(:html) { '<!doctype html><title>Hello world</title>' } let(:html) { '<!doctype html><title>Hello world</title>' }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
describe FetchOEmbedService, type: :service do describe FetchOEmbedService do
subject { described_class.new } subject { described_class.new }
before do before do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe FetchRemoteStatusService, type: :service do RSpec.describe FetchRemoteStatusService do
let(:account) { Fabricate(:account, domain: 'example.org', uri: 'https://example.org/foo') } let(:account) { Fabricate(:account, domain: 'example.org', uri: 'https://example.org/foo') }
let(:prefetched_body) { nil } let(:prefetched_body) { nil }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe FetchResourceService, type: :service do RSpec.describe FetchResourceService do
describe '#call' do describe '#call' do
subject { described_class.new.call(url) } subject { described_class.new.call(url) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe FollowService, type: :service do RSpec.describe FollowService do
subject { described_class.new } subject { described_class.new }
let(:sender) { Fabricate(:account, username: 'alice') } let(:sender) { Fabricate(:account, username: 'alice') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ImportService, :sidekiq_inline, type: :service do RSpec.describe ImportService, :sidekiq_inline do
include RoutingHelper include RoutingHelper
let!(:account) { Fabricate(:account, locked: false) } let!(:account) { Fabricate(:account, locked: false) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe MuteService, type: :service do RSpec.describe MuteService do
subject { described_class.new.call(account, target_account) } subject { described_class.new.call(account, target_account) }
let(:account) { Fabricate(:account) } let(:account) { Fabricate(:account) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe NotifyService, type: :service do RSpec.describe NotifyService do
subject { described_class.new.call(recipient, type, activity) } subject { described_class.new.call(recipient, type, activity) }
let(:user) { Fabricate(:user) } let(:user) { Fabricate(:user) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe PostStatusService, type: :service do RSpec.describe PostStatusService do
subject { described_class.new } subject { described_class.new }
it 'creates a new status' do it 'creates a new status' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe PrecomputeFeedService, type: :service do RSpec.describe PrecomputeFeedService do
subject { described_class.new } subject { described_class.new }
describe 'call' do describe 'call' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ProcessMentionsService, type: :service do RSpec.describe ProcessMentionsService do
subject { described_class.new } subject { described_class.new }
let(:account) { Fabricate(:account, username: 'alice') } let(:account) { Fabricate(:account, username: 'alice') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe PurgeDomainService, type: :service do RSpec.describe PurgeDomainService do
subject { described_class.new } subject { described_class.new }
let(:domain) { 'obsolete.org' } let(:domain) { 'obsolete.org' }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ReblogService, type: :service do RSpec.describe ReblogService do
let(:alice) { Fabricate(:account, username: 'alice') } let(:alice) { Fabricate(:account, username: 'alice') }
context 'when creates a reblog with appropriate visibility' do context 'when creates a reblog with appropriate visibility' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe RejectFollowService, type: :service do RSpec.describe RejectFollowService do
subject { described_class.new } subject { described_class.new }
let(:sender) { Fabricate(:account, username: 'alice') } let(:sender) { Fabricate(:account, username: 'alice') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe RemoveFromFollowersService, type: :service do RSpec.describe RemoveFromFollowersService do
subject { described_class.new } subject { described_class.new }
let(:bob) { Fabricate(:account, username: 'bob') } let(:bob) { Fabricate(:account, username: 'bob') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe RemoveStatusService, :sidekiq_inline, type: :service do RSpec.describe RemoveStatusService, :sidekiq_inline do
subject { described_class.new } subject { described_class.new }
let!(:alice) { Fabricate(:account) } let!(:alice) { Fabricate(:account) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ReportService, type: :service do RSpec.describe ReportService do
subject { described_class.new } subject { described_class.new }
let(:source_account) { Fabricate(:account) } let(:source_account) { Fabricate(:account) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ResolveAccountService, type: :service do RSpec.describe ResolveAccountService do
subject { described_class.new } subject { described_class.new }
before do before do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
describe ResolveURLService, type: :service do describe ResolveURLService do
subject { described_class.new } subject { described_class.new }
describe '#call' do describe '#call' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
describe SearchService, type: :service do describe SearchService do
subject { described_class.new } subject { described_class.new }
describe '#call' do describe '#call' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe SoftwareUpdateCheckService, type: :service do RSpec.describe SoftwareUpdateCheckService do
subject { described_class.new } subject { described_class.new }
shared_examples 'when the feature is enabled' do shared_examples 'when the feature is enabled' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe SuspendAccountService, :sidekiq_inline, type: :service do RSpec.describe SuspendAccountService, :sidekiq_inline do
shared_examples 'common behavior' do shared_examples 'common behavior' do
subject { described_class.new.call(account) } subject { described_class.new.call(account) }

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe TagSearchService do
describe '#call' do
let!(:one) { Fabricate(:tag, name: 'one') }
before { Fabricate(:tag, name: 'two') }
it 'runs a search for tags' do
results = subject.call('#one', limit: 5)
expect(results)
.to have_attributes(
size: 1,
first: eq(one)
)
end
end
end

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe TranslateStatusService, type: :service do RSpec.describe TranslateStatusService do
subject(:service) { described_class.new } subject(:service) { described_class.new }
let(:status) { Fabricate(:status, text: text, spoiler_text: spoiler_text, language: 'en', preloadable_poll: poll, media_attachments: media_attachments) } let(:status) { Fabricate(:status, text: text, spoiler_text: spoiler_text, language: 'en', preloadable_poll: poll, media_attachments: media_attachments) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe UnallowDomainService, type: :service do RSpec.describe UnallowDomainService do
subject { described_class.new } subject { described_class.new }
let(:bad_domain) { 'evil.org' } let(:bad_domain) { 'evil.org' }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
describe UnblockDomainService, type: :service do describe UnblockDomainService do
subject { described_class.new } subject { described_class.new }
describe 'call' do describe 'call' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe UnblockService, type: :service do RSpec.describe UnblockService do
subject { described_class.new } subject { described_class.new }
let(:sender) { Fabricate(:account, username: 'alice') } let(:sender) { Fabricate(:account, username: 'alice') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe UnfollowService, type: :service do RSpec.describe UnfollowService do
subject { described_class.new } subject { described_class.new }
let(:sender) { Fabricate(:account, username: 'alice') } let(:sender) { Fabricate(:account, username: 'alice') }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe UnsuspendAccountService, type: :service do RSpec.describe UnsuspendAccountService do
shared_context 'with common context' do shared_context 'with common context' do
subject { described_class.new.call(account) } subject { described_class.new.call(account) }

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe UpdateAccountService, type: :service do RSpec.describe UpdateAccountService do
subject { described_class.new } subject { described_class.new }
describe 'switching form locked to unlocked accounts', :sidekiq_inline do describe 'switching form locked to unlocked accounts', :sidekiq_inline do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe UpdateStatusService, type: :service do RSpec.describe UpdateStatusService do
subject { described_class.new } subject { described_class.new }
context 'when nothing changes' do context 'when nothing changes' do

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe VerifyLinkService, type: :service do RSpec.describe VerifyLinkService do
subject { described_class.new } subject { described_class.new }
context 'when given a local account' do context 'when given a local account' do