Merge commit 'b320c9e4c901bf99ccbca321bad2ceb2f51de140' into glitch-soc/merge-upstream

This commit is contained in:
Claire
2026-03-17 18:58:19 +01:00
65 changed files with 448 additions and 249 deletions

View File

@@ -27,7 +27,7 @@ gem 'addressable', '~> 2.8'
gem 'bootsnap', require: false gem 'bootsnap', require: false
gem 'browser' gem 'browser'
gem 'charlock_holmes', '~> 0.7.7' gem 'charlock_holmes', '~> 0.7.7'
gem 'chewy', '~> 7.3' gem 'chewy'
gem 'devise' gem 'devise'
gem 'devise-two-factor' gem 'devise-two-factor'

View File

@@ -159,9 +159,9 @@ GEM
cbor (0.5.10.1) cbor (0.5.10.1)
cgi (0.5.1) cgi (0.5.1)
charlock_holmes (0.7.9) charlock_holmes (0.7.9)
chewy (7.6.0) chewy (8.0.1)
activesupport (>= 5.2) activesupport (>= 7.2)
elasticsearch (>= 7.14.0, < 8) elasticsearch (>= 8.14, < 9.0)
elasticsearch-dsl elasticsearch-dsl
childprocess (5.1.0) childprocess (5.1.0)
logger (~> 1.5) logger (~> 1.5)
@@ -214,16 +214,16 @@ GEM
dotenv (3.2.0) dotenv (3.2.0)
drb (2.2.3) drb (2.2.3)
dry-cli (1.4.1) dry-cli (1.4.1)
elasticsearch (7.17.11) elastic-transport (8.4.1)
elasticsearch-api (= 7.17.11) faraday (< 3)
elasticsearch-transport (= 7.17.11) multi_json
elasticsearch-api (7.17.11) elasticsearch (8.19.3)
elastic-transport (~> 8.3)
elasticsearch-api (= 8.19.3)
ostruct
elasticsearch-api (8.19.3)
multi_json multi_json
elasticsearch-dsl (0.1.10) elasticsearch-dsl (0.1.10)
elasticsearch-transport (7.17.11)
base64
faraday (>= 1, < 3)
multi_json
email_validator (2.2.4) email_validator (2.2.4)
activemodel activemodel
erb (6.0.2) erb (6.0.2)
@@ -959,7 +959,7 @@ DEPENDENCIES
capybara (~> 3.39) capybara (~> 3.39)
capybara-playwright-driver capybara-playwright-driver
charlock_holmes (~> 0.7.7) charlock_holmes (~> 0.7.7)
chewy (~> 7.3) chewy
climate_control climate_control
cocoon (~> 1.2) cocoon (~> 1.2)
color_diff (~> 0.1) color_diff (~> 0.1)

View File

@@ -76,6 +76,7 @@ Mastodon is a **free, open-source social network server** based on [ActivityPub]
- **PostgreSQL** 14+ - **PostgreSQL** 14+
- **Redis** 7.0+ - **Redis** 7.0+
- **Node.js** 20+ - **Node.js** 20+
- **FFmpeg** 5.1+
This repository includes deployment configurations for **Docker and docker-compose**, as well as for other environments like Heroku and Scalingo. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). A [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the main documentation. This repository includes deployment configurations for **Docker and docker-compose**, as well as for other environments like Heroku and Scalingo. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). A [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the main documentation.

View File

@@ -1366,6 +1366,9 @@ body > [data-popper-placement] {
.autosuggest-textarea > .autosuggest-textarea__textarea:lang(#{$lang}) { .autosuggest-textarea > .autosuggest-textarea__textarea:lang(#{$lang}) {
writing-mode: vertical-lr; writing-mode: vertical-lr;
min-height: 209px; // writable min-height: 209px; // writable
max-height: 209px; // suppress autosizing by react-textarea-autosize
overflow-x: auto;
scrollbar-color: unset;
} }
.detailed-status > .status__content > .status__content__text:lang(#{$lang}) { .detailed-status > .status__content > .status__content__text:lang(#{$lang}) {

View File

@@ -1257,31 +1257,44 @@ code {
} }
.progress-tracker { .progress-tracker {
--circle-size: 30px;
display: flex; display: flex;
align-items: center; align-items: center;
padding-bottom: 30px; padding-bottom: 30px;
margin-bottom: 30px; margin-bottom: 30px;
li { li {
flex: 0 0 auto;
position: relative; position: relative;
}
.separator { --connector-color: var(--color-border-primary);
height: 2px; --connector-thickness: 2px;
background: var(--color-border-primary);
flex: 1 1 auto;
&.completed { &.completed {
background: var(--color-text-brand); --connector-color: var(--color-bg-brand-base);
}
&:not(:last-child) {
flex-grow: 1;
// Connector line between circles
&::after {
content: '';
display: block;
position: absolute;
inset-inline: var(--circle-size) 0;
background-color: var(--connector-color);
height: 2px;
top: calc((var(--circle-size) - var(--connector-thickness)) / 2);
}
} }
} }
.circle { .circle {
box-sizing: border-box; box-sizing: border-box;
position: relative; position: relative;
width: 30px; width: var(--circle-size);
height: 30px; height: var(--circle-size);
border-radius: 50%; border-radius: 50%;
border: 2px solid var(--color-border-primary); border: 2px solid var(--color-border-primary);
flex: 0 0 auto; flex: 0 0 auto;
@@ -1302,8 +1315,9 @@ code {
padding-top: 10px; padding-top: 10px;
text-align: center; text-align: center;
width: 100px; width: 100px;
left: 50%;
transform: translateX(-50%); // Center-align the label with the circle
transform: translateX(-33.3333%);
} }
li:first-child .label { li:first-child .label {
@@ -1320,15 +1334,15 @@ code {
transform: none; transform: none;
} }
.active .circle { [aria-current='step'] .circle {
border-color: var(--color-text-brand); border-color: var(--color-bg-brand-base);
&::before { &::before {
content: ''; content: '';
width: 10px; width: 10px;
height: 10px; height: 10px;
border-radius: 50%; border-radius: 50%;
background: var(--color-text-brand); background: var(--color-bg-brand-base);
position: absolute; position: absolute;
left: 50%; left: 50%;
top: 50%; top: 50%;
@@ -1337,8 +1351,9 @@ code {
} }
.completed .circle { .completed .circle {
border-color: var(--color-text-brand); color: var(--color-text-on-brand-base);
background: var(--color-text-brand); background: var(--color-bg-brand-base);
border-color: var(--color-bg-brand-base);
} }
} }

View File

@@ -167,6 +167,12 @@ class ActivityPub::Activity
@follow_from_object ||= ::Follow.find_by(target_account: @account, uri: object_uri) unless object_uri.nil? @follow_from_object ||= ::Follow.find_by(target_account: @account, uri: object_uri) unless object_uri.nil?
end end
def feature_request_from_object
return @collection_item if instance_variable_defined?(:@collection_item)
@collection_item = CollectionItem.local.find_by(activity_uri: value_or_id(@object), account_id: @account.id)
end
def fetch_remote_original_status def fetch_remote_original_status
if object_uri.start_with?('http') if object_uri.start_with?('http')
return if ActivityPub::TagManager.instance.local_uri?(object_uri) return if ActivityPub::TagManager.instance.local_uri?(object_uri)

View File

@@ -5,6 +5,7 @@ class ActivityPub::Activity::Accept < ActivityPub::Activity
return accept_follow_for_relay if relay_follow? return accept_follow_for_relay if relay_follow?
return accept_follow!(follow_request_from_object) unless follow_request_from_object.nil? return accept_follow!(follow_request_from_object) unless follow_request_from_object.nil?
return accept_quote!(quote_request_from_object) unless quote_request_from_object.nil? return accept_quote!(quote_request_from_object) unless quote_request_from_object.nil?
return accept_feature_request! if Mastodon::Feature.collections_federation_enabled? && feature_request_from_object.present?
case @object['type'] case @object['type']
when 'Follow' when 'Follow'
@@ -44,6 +45,17 @@ class ActivityPub::Activity::Accept < ActivityPub::Activity
accept_quote!(quote) accept_quote!(quote)
end end
def accept_feature_request!
approval_uri = value_or_id(first_of_value(@json['result']))
return if approval_uri.nil? || unsupported_uri_scheme?(approval_uri) || non_matching_uri_hosts?(approval_uri, @account.uri)
collection_item = feature_request_from_object
collection_item.update!(approval_uri:, state: :accepted)
activity_json = ActiveModelSerializers::SerializableResource.new(collection_item, serializer: ActivityPub::AddFeaturedItemSerializer, adapter: ActivityPub::Adapter).to_json
ActivityPub::AccountRawDistributionWorker.perform_async(activity_json, collection_item.collection.account_id)
end
def accept_quote!(quote) def accept_quote!(quote)
approval_uri = value_or_id(first_of_value(@json['result'])) approval_uri = value_or_id(first_of_value(@json['result']))
return if unsupported_uri_scheme?(approval_uri) || quote.quoted_account != @account || !quote.status.local? || !quote.pending? return if unsupported_uri_scheme?(approval_uri) || quote.quoted_account != @account || !quote.status.local? || !quote.pending?

View File

@@ -6,6 +6,7 @@ class ActivityPub::Activity::Reject < ActivityPub::Activity
return follow_request_from_object.reject! unless follow_request_from_object.nil? return follow_request_from_object.reject! unless follow_request_from_object.nil?
return UnfollowService.new.call(follow_from_object.account, @account) unless follow_from_object.nil? return UnfollowService.new.call(follow_from_object.account, @account) unless follow_from_object.nil?
return reject_quote!(quote_request_from_object) unless quote_request_from_object.nil? return reject_quote!(quote_request_from_object) unless quote_request_from_object.nil?
return reject_feature_request! unless feature_request_from_object.nil?
case @object['type'] case @object['type']
when 'Follow' when 'Follow'
@@ -46,6 +47,13 @@ class ActivityPub::Activity::Reject < ActivityPub::Activity
quote.reject! quote.reject!
end end
def reject_feature_request!
collection_item = feature_request_from_object
return unless collection_item.account == @account && collection_item.local?
collection_item.destroy!
end
def relay def relay
@relay ||= Relay.find_by(follow_activity_id: object_uri) unless object_uri.nil? @relay ||= Relay.find_by(follow_activity_id: object_uri) unless object_uri.nil?
end end

View File

@@ -65,7 +65,7 @@ class Admin::Metrics::Dimension::SoftwareVersionsDimension < Admin::Metrics::Dim
value: version, value: version,
human_value: version, human_value: version,
} }
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error rescue Faraday::ConnectionFailed, Elastic::Transport::Transport::Error
nil nil
end end

View File

@@ -69,7 +69,7 @@ class Admin::Metrics::Dimension::SpaceUsageDimension < Admin::Metrics::Dimension
unit: 'bytes', unit: 'bytes',
human_value: number_to_human_size(value), human_value: number_to_human_size(value),
} }
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error rescue Faraday::ConnectionFailed, Elastic::Transport::Transport::Error
nil nil
end end
end end

View File

@@ -17,7 +17,7 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
return true unless Chewy.enabled? return true unless Chewy.enabled?
running_version.present? && compatible_version? && cluster_health['status'] == 'green' && indexes_match? && specifications_match? && preset_matches? running_version.present? && compatible_version? && cluster_health['status'] == 'green' && indexes_match? && specifications_match? && preset_matches?
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error, HTTPClient::KeepAliveDisconnected rescue Faraday::ConnectionFailed, Elastic::Transport::Transport::Error, HTTPClient::KeepAliveDisconnected
false false
end end
@@ -54,7 +54,7 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
else else
Admin::SystemCheck::Message.new(:elasticsearch_preset, nil, 'https://docs.joinmastodon.org/admin/elasticsearch/#scaling') Admin::SystemCheck::Message.new(:elasticsearch_preset, nil, 'https://docs.joinmastodon.org/admin/elasticsearch/#scaling')
end end
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error, HTTPClient::KeepAliveDisconnected rescue Faraday::ConnectionFailed, Elastic::Transport::Transport::Error, HTTPClient::KeepAliveDisconnected
Admin::SystemCheck::Message.new(:elasticsearch_running_check) Admin::SystemCheck::Message.new(:elasticsearch_running_check)
end end
@@ -67,7 +67,7 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
def running_version def running_version
@running_version ||= begin @running_version ||= begin
Chewy.client.info['version']['number'] Chewy.client.info['version']['number']
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error rescue Faraday::ConnectionFailed, Elastic::Transport::Transport::Error
nil nil
end end
end end

View File

@@ -29,7 +29,7 @@ class CollectionItem < ApplicationRecord
validates :position, numericality: { only_integer: true, greater_than: 0 } validates :position, numericality: { only_integer: true, greater_than: 0 }
validates :activity_uri, presence: true, if: :local_item_with_remote_account? validates :activity_uri, presence: true, if: :local_item_with_remote_account?
validates :approval_uri, presence: true, unless: -> { local? || account&.local? } validates :approval_uri, presence: true, unless: -> { local? || account&.local? || !accepted? }
validates :account, presence: true, if: :accepted? validates :account, presence: true, if: :accepted?
validates :object_uri, presence: true, if: -> { account.nil? } validates :object_uri, presence: true, if: -> { account.nil? }
validates :uri, presence: true, if: :remote_item_with_remote_account? validates :uri, presence: true, if: :remote_item_with_remote_account?

View File

@@ -21,9 +21,9 @@ class ActivityPub::ProcessFeaturedItemService
else else
@collection_item = collection.collection_items.create!( @collection_item = collection.collection_items.create!(
uri: item_json['id'], uri: item_json['id'],
object_uri: item_json['featuredObject'], object_uri: item_json['featuredObject']
approval_uri: item_json['featureAuthorization']
) )
@approval_uri = item_json['featureAuthorization']
verify_authorization! verify_authorization!
end end
@@ -35,8 +35,8 @@ class ActivityPub::ProcessFeaturedItemService
private private
def verify_authorization! def verify_authorization!
ActivityPub::VerifyFeaturedItemService.new.call(@collection_item) ActivityPub::VerifyFeaturedItemService.new.call(@collection_item, @approval_uri)
rescue Mastodon::RecursionLimitExceededError, Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS rescue Mastodon::RecursionLimitExceededError, Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
ActivityPub::VerifyFeaturedItemWorker.perform_in(rand(30..600).seconds, @collection_item.id) ActivityPub::VerifyFeaturedItemWorker.perform_in(rand(30..600).seconds, @collection_item.id, @approval_uri)
end end
end end

View File

@@ -3,23 +3,23 @@
class ActivityPub::VerifyFeaturedItemService class ActivityPub::VerifyFeaturedItemService
include JsonLdHelper include JsonLdHelper
def call(collection_item) def call(collection_item, approval_uri)
@collection_item = collection_item @collection_item = collection_item
@authorization = fetch_resource(@collection_item.approval_uri, true, raise_on_error: :temporary) @authorization = fetch_resource(approval_uri, true, raise_on_error: :temporary)
if @authorization.nil? if @authorization.nil?
@collection_item.update!(state: :rejected) @collection_item.update!(state: :rejected)
return return
end end
return if non_matching_uri_hosts?(@collection_item.approval_uri, @authorization['interactionTarget']) return if non_matching_uri_hosts?(approval_uri, @authorization['interactionTarget'])
return unless matching_type? && matching_collection_uri? return unless matching_type? && matching_collection_uri?
account = Account.where(uri: @collection_item.object_uri).first account = Account.where(uri: @collection_item.object_uri).first
account ||= ActivityPub::FetchRemoteAccountService.new.call(@collection_item.object_uri) account ||= ActivityPub::FetchRemoteAccountService.new.call(@collection_item.object_uri)
return if account.blank? return if account.blank?
@collection_item.update!(account:, state: :accepted) @collection_item.update!(account:, approval_uri:, state: :accepted)
end end
private private

View File

@@ -86,14 +86,14 @@ class FetchOEmbedService
end end
validate(parse_for_format(body)) if body.present? validate(parse_for_format(body)) if body.present?
rescue Oj::ParseError, Ox::ParseError rescue JSON::ParserError, Ox::ParseError
nil nil
end end
def parse_for_format(body) def parse_for_format(body)
case @format case @format
when :json when :json
Oj.load(body, mode: :strict)&.with_indifferent_access JSON.parse(body)&.with_indifferent_access
when :xml when :xml
Ox.load(body, mode: :hash_no_attrs)&.with_indifferent_access&.dig(:oembed) Ox.load(body, mode: :hash_no_attrs)&.with_indifferent_access&.dig(:oembed)
end end

View File

@@ -1,26 +1,35 @@
- progress_index = { rules: 0, details: 1, confirm: 2, confirmed: 3, completed: 4 }[stage.to_sym] - progress_index = { rules: 0, details: 1, confirm: 2, confirmed: 3, completed: 4 }[stage.to_sym]
%ol.progress-tracker %ol.progress-tracker{ role: 'list', 'aria-label': t('auth.progress.list') }
%li{ class: progress_index.positive? ? 'completed' : 'active' } %li{
class: progress_index.positive? ? 'completed' : nil,
'aria-current': progress_index.zero? ? 'step' : nil
}
.circle .circle
- if progress_index.positive? - if progress_index.positive?
= check_icon = check_icon
.label= t('auth.progress.rules') .label= t('auth.progress.rules')
%li.separator{ class: progress_index.positive? ? 'completed' : nil } %li{
%li{ class: [progress_index > 1 && 'completed', progress_index == 1 && 'active'] } class: progress_index > 1 && 'completed',
'aria-current': progress_index == 1 ? 'step' : nil
}
.circle .circle
- if progress_index > 1 - if progress_index > 1
= check_icon = check_icon
.label= t('auth.progress.details') .label= t('auth.progress.details')
%li.separator{ class: progress_index > 1 ? 'completed' : nil } %li{
%li{ class: [progress_index > 2 && 'completed', progress_index == 2 && 'active'] } class: progress_index > 2 && 'completed',
'aria-current': progress_index == 2 ? 'step' : nil
}
.circle .circle
- if progress_index > 2 - if progress_index > 2
= check_icon = check_icon
.label= t('auth.progress.confirm') .label= t('auth.progress.confirm')
- if approved_registrations? - if approved_registrations?
%li.separator{ class: progress_index > 2 ? 'completed' : nil } %li{
%li{ class: [progress_index > 3 && 'completed', progress_index == 3 && 'active'] } class: progress_index > 3 && 'completed',
'aria-current': progress_index == 3 ? 'step' : nil
}
.circle .circle
- if progress_index > 3 - if progress_index > 3
= check_icon = check_icon

View File

@@ -7,10 +7,10 @@ class ActivityPub::VerifyFeaturedItemWorker
sidekiq_options queue: 'pull', retry: 5 sidekiq_options queue: 'pull', retry: 5
def perform(collection_item_id) def perform(collection_item_id, approval_uri)
collection_item = CollectionItem.find(collection_item_id) collection_item = CollectionItem.find(collection_item_id)
ActivityPub::VerifyFeaturedItemService.new.call(collection_item) ActivityPub::VerifyFeaturedItemService.new.call(collection_item, approval_uri)
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
# Do nothing # Do nothing
nil nil

View File

@@ -1279,6 +1279,7 @@ en-GB:
progress: progress:
confirm: Confirm email confirm: Confirm email
details: Your details details: Your details
list: Sign up progress
review: Our review review: Our review
rules: Accept rules rules: Accept rules
providers: providers:

View File

@@ -1279,6 +1279,7 @@ en:
progress: progress:
confirm: Confirm email confirm: Confirm email
details: Your details details: Your details
list: Sign up progress
review: Our review review: Our review
rules: Accept rules rules: Accept rules
providers: providers:

View File

@@ -2,7 +2,9 @@
module Elasticsearch module Elasticsearch
module ClientExtensions module ClientExtensions
def verify_elasticsearch def initialize(arguments = {}, &block)
super
@verified = true @verified = true
end end
end end

View File

@@ -140,13 +140,13 @@ module Mastodon::CLI
Request.new(:get, "https://#{domain}/api/v1/instance").perform do |res| Request.new(:get, "https://#{domain}/api/v1/instance").perform do |res|
next unless res.code == 200 next unless res.code == 200
stats[domain] = Oj.load(res.to_s) stats[domain] = JSON.parse(res.to_s)
end end
Request.new(:get, "https://#{domain}/api/v1/instance/peers").perform do |res| Request.new(:get, "https://#{domain}/api/v1/instance/peers").perform do |res|
next unless res.code == 200 next unless res.code == 200
Oj.load(res.to_s).reject { |peer| stats.key?(peer) }.each do |peer| JSON.parse(res.to_s).reject { |peer| stats.key?(peer) }.each do |peer|
pool.post(peer, &work_unit) pool.post(peer, &work_unit)
end end
end end
@@ -154,7 +154,7 @@ module Mastodon::CLI
Request.new(:get, "https://#{domain}/api/v1/instance/activity").perform do |res| Request.new(:get, "https://#{domain}/api/v1/instance/activity").perform do |res|
next unless res.code == 200 next unless res.code == 200
stats[domain]['activity'] = Oj.load(res.to_s) stats[domain]['activity'] = JSON.parse(res.to_s)
end end
rescue rescue
failed.increment failed.increment

View File

@@ -115,7 +115,7 @@ module Mastodon::CLI
progress.finish progress.finish
say("Indexed #{added} records, de-indexed #{removed}", :green, true) say("Indexed #{added} records, de-indexed #{removed}", :green, true)
rescue Elasticsearch::Transport::Transport::ServerError => e rescue Elastic::Transport::Transport::ServerError => e
fail_with_message <<~ERROR fail_with_message <<~ERROR
There was an issue connecting to the search server. Make sure the There was an issue connecting to the search server. Make sure the
server is configured and running correctly, and that the environment server is configured and running correctly, and that the environment

View File

@@ -51,10 +51,7 @@ module Paperclip
@output_options['maxrate'] = bitrate + 192_000 @output_options['maxrate'] = bitrate + 192_000
@output_options['bufsize'] = bitrate * 5 @output_options['bufsize'] = bitrate * 5
if high_vfr?(metadata) @output_options['fps_mode'] = 'vfr' if high_vfr?(metadata)
# TODO: change to `fps_mode` in the future, as `vsync` is being deprecated
@output_options['vsync'] = 'vfr'
end
end end
end end

View File

@@ -109,7 +109,7 @@ namespace :emojis do
emojis_light = '👽⚾🐔☁️💨🕊️👀🍥👻🐐❕❔⛸️🌩️🔊🔇📃🌧️🐏🍚🍙🐓🐑💀☠️🌨️🔉🔈💬💭🏐🏳️⚪⬜◽◻️▫️🪽🪿' emojis_light = '👽⚾🐔☁️💨🕊️👀🍥👻🐐❕❔⛸️🌩️🔊🔇📃🌧️🐏🍚🍙🐓🐑💀☠️🌨️🔉🔈💬💭🏐🏳️⚪⬜◽◻️▫️🪽🪿'
emojis_dark = '🎱🐜⚫🖤⬛◼️◾◼️✒️▪️💣🎳📷📸♣️🕶️✴️🔌💂‍♀️📽️🍳🦍💂🔪🕳️🕹️🕋🖊️🖋️💂‍♂️🎤🎓🎥🎼♠️🎩🦃📼📹🎮🐃🏴🐞🕺📱📲🚲🪮🐦‍⬛' emojis_dark = '🎱🐜⚫🖤⬛◼️◾◼️✒️▪️💣🎳📷📸♣️🕶️✴️🔌💂‍♀️📽️🍳🦍💂🔪🕳️🕹️🕋🖊️🖋️💂‍♂️🎤🎓🎥🎼♠️🎩🦃📼📹🎮🐃🏴🐞🕺📱📲🚲🪮🐦‍⬛'
map = Oj.load(File.read(src)) map = JSON.parse(File.read(src))
emojis_light.each_grapheme_cluster do |emoji| emojis_light.each_grapheme_cluster do |emoji|
gen_border map[emoji], 'black' gen_border map[emoji], 'black'
@@ -193,7 +193,7 @@ namespace :emojis do
require 'vips' require 'vips'
src = Rails.root.join('app', 'javascript', 'mastodon', 'features', 'emoji', 'emoji_data.json') src = Rails.root.join('app', 'javascript', 'mastodon', 'features', 'emoji', 'emoji_data.json')
sheet = Oj.load(File.read(src)) sheet = JSON.load_file(src)
max = 0 max = 0
sheet['emojis'].each_value do |row| sheet['emojis'].each_value do |row|

View File

@@ -22,7 +22,7 @@ namespace :repo do
while url.present? while url.present?
response = HTTP.get(url) response = HTTP.get(url)
contributors = Oj.load(response.body) contributors = JSON.parse(response.body)
contributors.each do |c| contributors.each do |c|
file << "* [#{c['login']}](#{c['html_url']})\n" if c['login'] file << "* [#{c['login']}](#{c['html_url']})\n" if c['login']
@@ -68,7 +68,7 @@ namespace :repo do
end end
end end
pull_request = Oj.load(response.to_s) pull_request = JSON.parse(response.to_s)
pull_request['user']['login'] pull_request['user']['login']
end end

View File

@@ -15,7 +15,7 @@ module ViteRuby::ManifestIntegrityExtension
end end
def load_name_lookup_cache def load_name_lookup_cache
Oj.load(config.build_output_dir.join('.vite/manifest-lookup.json').read) JSON.load_file(config.build_output_dir.join('.vite/manifest-lookup.json'))
end end
# Upstream's `virtual` type is a hack, re-implement it with efficient exact name lookup # Upstream's `virtual` type is a hack, re-implement it with efficient exact name lookup

View File

@@ -11,6 +11,5 @@ Fabricator(:unverified_remote_collection_item, from: :collection_item) do
account nil account nil
state :pending state :pending
object_uri { Fabricate.build(:remote_account).uri } object_uri { Fabricate.build(:remote_account).uri }
approval_uri { sequence(:uri) { |i| "https://example.com/authorizations/#{i}" } }
uri { sequence(:uri) { |i| "https://example.com/collection_items/#{i}" } } uri { sequence(:uri) { |i| "https://example.com/collection_items/#{i}" } }
end end

View File

@@ -171,5 +171,71 @@ RSpec.describe ActivityPub::Activity::Accept do
end end
end end
end end
context 'with a FeatureRequest', feature: :collections_federation do
let(:collection) { Fabricate(:collection, account: recipient) }
let(:collection_item) { Fabricate(:collection_item, collection:, account: sender, state: :pending) }
let(:object) { collection_item.activity_uri }
let(:approval_uri) { 'https://example.com/stamps/1' }
let(:json) do
{
'id' => 'https://example.com/accepts/1',
'type' => 'Accept',
'actor' => sender.uri,
'to' => ActivityPub::TagManager.instance.uri_for(recipient),
'object' => object,
'result' => approval_uri,
}
end
context 'when activity is valid' do
it 'accepts the collection item, stores the authorization uri and federates an `Add` activity' do
subject.perform
expect(collection_item.reload).to be_accepted
expect(collection_item.approval_uri).to eq 'https://example.com/stamps/1'
expect(ActivityPub::AccountRawDistributionWorker)
.to have_enqueued_sidekiq_job
end
end
context 'when activity is invalid' do
shared_examples 'ignoring activity' do
it 'does not accept the item and does not send out an activity' do
subject.perform
expect(collection_item.reload).to_not be_accepted
expect(collection_item.approval_uri).to be_nil
expect(ActivityPub::AccountRawDistributionWorker)
.to_not have_enqueued_sidekiq_job
end
end
context 'when matching collection item cannot be found' do
let(:object) { 'https://localhost/feature_requests/1' }
it_behaves_like 'ignoring activity'
end
context 'when the sender is not the featured account' do
let(:other_account) { Fabricate(:remote_account) }
let(:collection_item) { Fabricate(:collection_item, collection:, account: other_account, state: :pending) }
it_behaves_like 'ignoring activity'
end
context "when approval_uri does not match the sender's uri" do
let(:approval_uri) { 'https://other.localhost/authorizations/1' }
it_behaves_like 'ignoring activity'
end
context 'when approval_uri is missing' do
let(:approval_uri) { nil }
it_behaves_like 'ignoring activity'
end
end
end
end end
end end

View File

@@ -35,7 +35,7 @@ RSpec.describe ActivityPub::Activity::Announce do
context 'when sender is followed by a local account' do context 'when sender is followed by a local account' do
before do before do
Fabricate(:account).follow!(sender) Fabricate(:account).follow!(sender)
stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: JSON.generate(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: unknown_object_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
subject.perform subject.perform
end end
@@ -120,7 +120,7 @@ RSpec.describe ActivityPub::Activity::Announce do
let(:object_json) { 'https://example.com/actor/hello-world' } let(:object_json) { 'https://example.com/actor/hello-world' }
before do before do
stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: JSON.generate(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: unknown_object_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
context 'when the relay is enabled' do context 'when the relay is enabled' do

View File

@@ -1078,8 +1078,8 @@ RSpec.describe ActivityPub::Activity::Create do
) )
end end
before do let(:quote_authorization_json) do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ {
'@context': [ '@context': [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
{ {
@@ -1104,7 +1104,11 @@ RSpec.describe ActivityPub::Activity::Create do
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account), attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
interactingObject: object_json[:id], interactingObject: object_json[:id],
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status), interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
})) }
end
before do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
end end
it 'creates a status with a verified quote' do it 'creates a status with a verified quote' do
@@ -1134,8 +1138,8 @@ RSpec.describe ActivityPub::Activity::Create do
) )
end end
before do let(:quote_authorization_json) do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ {
'@context': [ '@context': [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
{ {
@@ -1160,7 +1164,11 @@ RSpec.describe ActivityPub::Activity::Create do
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account), attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
interactingObject: object_json[:id], interactingObject: object_json[:id],
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status), interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
})) }
end
before do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
end end
it 'creates a status without the verified quote' do it 'creates a status without the verified quote' do
@@ -1267,7 +1275,7 @@ RSpec.describe ActivityPub::Activity::Create do
before do before do
stub_request(:get, object_json[:id]) stub_request(:get, object_json[:id])
.with(headers: { Authorization: "Bearer #{token}" }) .with(headers: { Authorization: "Bearer #{token}" })
.to_return(body: JSON.generate(object_json), headers: { 'Content-Type': 'application/activity+json' }) .to_return(body: object_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
subject.perform subject.perform
end end

View File

@@ -65,7 +65,7 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do
expect { subject.perform } expect { subject.perform }
.to enqueue_sidekiq_job(ActivityPub::DeliveryWorker) .to enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
.with(satisfying do |body| .with(satisfying do |body|
outgoing_json = Oj.load(body) outgoing_json = JSON.parse(body)
outgoing_json['type'] == 'Reject' && %w(type id actor object instrument).all? { |key| json[key] == outgoing_json['object'][key] } outgoing_json['type'] == 'Reject' && %w(type id actor object instrument).all? { |key| json[key] == outgoing_json['object'][key] }
end, recipient.id, sender.inbox_url) end, recipient.id, sender.inbox_url)
end end
@@ -78,7 +78,7 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do
expect { subject.perform } expect { subject.perform }
.to enqueue_sidekiq_job(ActivityPub::DeliveryWorker) .to enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
.with(satisfying do |body| .with(satisfying do |body|
outgoing_json = Oj.load(body) outgoing_json = JSON.parse(body)
outgoing_json['type'] == 'Reject' && json['instrument']['id'] == outgoing_json['object']['instrument'] && %w(type id actor object).all? { |key| json[key] == outgoing_json['object'][key] } outgoing_json['type'] == 'Reject' && json['instrument']['id'] == outgoing_json['object']['instrument'] && %w(type id actor object).all? { |key| json[key] == outgoing_json['object'][key] }
end, recipient.id, sender.inbox_url) end, recipient.id, sender.inbox_url)
end end
@@ -86,7 +86,7 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do
context 'when trying to quote a quotable local status' do context 'when trying to quote a quotable local status' do
before do before do
stub_request(:get, 'https://example.com/unknown-status').to_return(status: 200, body: JSON.generate(status_json), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/unknown-status').to_return(status: 200, body: status_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
quoted_post.update(quote_approval_policy: InteractionPolicy::POLICY_FLAGS[:public] << 16) quoted_post.update(quote_approval_policy: InteractionPolicy::POLICY_FLAGS[:public] << 16)
end end
@@ -95,7 +95,7 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do
.to change { quoted_post.reload.quotes.accepted.count }.by(1) .to change { quoted_post.reload.quotes.accepted.count }.by(1)
.and enqueue_sidekiq_job(ActivityPub::DeliveryWorker) .and enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
.with(satisfying do |body| .with(satisfying do |body|
outgoing_json = Oj.load(body) outgoing_json = JSON.parse(body)
outgoing_json['type'] == 'Accept' && %w(type id actor object instrument).all? { |key| json[key] == outgoing_json['object'][key] } outgoing_json['type'] == 'Accept' && %w(type id actor object instrument).all? { |key| json[key] == outgoing_json['object'][key] }
end, recipient.id, sender.inbox_url) end, recipient.id, sender.inbox_url)
end end
@@ -113,7 +113,7 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do
.to change { quoted_post.reload.quotes.accepted.count }.by(1) .to change { quoted_post.reload.quotes.accepted.count }.by(1)
.and enqueue_sidekiq_job(ActivityPub::DeliveryWorker) .and enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
.with(satisfying do |body| .with(satisfying do |body|
outgoing_json = Oj.load(body) outgoing_json = JSON.parse(body)
outgoing_json['type'] == 'Accept' && json['instrument']['id'] == outgoing_json['object']['instrument'] && %w(type id actor object).all? { |key| json[key] == outgoing_json['object'][key] } outgoing_json['type'] == 'Accept' && json['instrument']['id'] == outgoing_json['object']['instrument'] && %w(type id actor object).all? { |key| json[key] == outgoing_json['object'][key] }
end, recipient.id, sender.inbox_url) end, recipient.id, sender.inbox_url)
end end

View File

@@ -3,7 +3,7 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ActivityPub::Activity::Reject do RSpec.describe ActivityPub::Activity::Reject do
let(:sender) { Fabricate(:account) } let(:sender) { Fabricate(:remote_account) }
let(:recipient) { Fabricate(:account) } let(:recipient) { Fabricate(:account) }
let(:json) do let(:json) do
@@ -129,12 +129,12 @@ RSpec.describe ActivityPub::Activity::Reject do
context 'with a QuoteRequest' do context 'with a QuoteRequest' do
let(:status) { Fabricate(:status, account: recipient) } let(:status) { Fabricate(:status, account: recipient) }
let(:quoted_status) { Fabricate(:status, account: sender) } let(:quoted_status) { Fabricate(:status, account: sender) }
let(:quote) { Fabricate(:quote, status: status, quoted_status: quoted_status, activity_uri: 'https://abc-123/456') } let!(:quote) { Fabricate(:quote, status: status, quoted_status: quoted_status) }
let(:approval_uri) { "https://#{sender.domain}/approvals/1" } let(:approval_uri) { "https://#{sender.domain}/approvals/1" }
let(:object_json) do let(:object_json) do
{ {
id: 'https://abc-123/456', id: quote.activity_uri,
type: 'QuoteRequest', type: 'QuoteRequest',
actor: ActivityPub::TagManager.instance.uri_for(recipient), actor: ActivityPub::TagManager.instance.uri_for(recipient),
object: ActivityPub::TagManager.instance.uri_for(quoted_status), object: ActivityPub::TagManager.instance.uri_for(quoted_status),
@@ -147,5 +147,23 @@ RSpec.describe ActivityPub::Activity::Reject do
.to change { quote.reload.rejected? }.from(false).to(true) .to change { quote.reload.rejected? }.from(false).to(true)
end end
end end
context 'with a FeatureRequest' do
let(:collection) { Fabricate(:collection, account: recipient) }
let!(:collection_item) { Fabricate(:collection_item, collection:, account: sender, state: :pending) }
let(:json) do
{
'id' => 'https://example.com/accepts/1',
'type' => 'Accept',
'actor' => sender.uri,
'to' => ActivityPub::TagManager.instance.uri_for(recipient),
'object' => collection_item.activity_uri,
}
end
it 'deletes the collection item' do
expect { subject.perform }.to change(collection.collection_items, :count).by(-1)
end
end
end end
end end

View File

@@ -89,7 +89,7 @@ RSpec.describe ActivityPub::Activity do
before do before do
sender.update(uri: ActivityPub::TagManager.instance.uri_for(sender)) sender.update(uri: ActivityPub::TagManager.instance.uri_for(sender))
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate(approval_payload)) stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: approval_payload.to_json)
end end
context 'when getting them in order' do context 'when getting them in order' do

View File

@@ -12,7 +12,7 @@ RSpec.describe ActivityPub::Dereferencer do
let(:uri) { nil } let(:uri) { nil }
before do before do
stub_request(:get, 'https://example.com/foo').to_return(body: JSON.generate(object), headers: { 'Content-Type' => 'application/activity+json' }) stub_request(:get, 'https://example.com/foo').to_return(body: object.to_json, headers: { 'Content-Type' => 'application/activity+json' })
end end
context 'with a URI' do context 'with a URI' do

View File

@@ -54,8 +54,8 @@ RSpec.describe ActivityPub::Forwarder do
it 'correctly forwards to expected remote followers' do it 'correctly forwards to expected remote followers' do
expect { subject.forward! } expect { subject.forward! }
.to enqueue_sidekiq_job(ActivityPub::LowPriorityDeliveryWorker).with(JSON.generate(payload), anything, eve.preferred_inbox_url) .to enqueue_sidekiq_job(ActivityPub::LowPriorityDeliveryWorker).with(payload.to_json, anything, eve.preferred_inbox_url)
.and enqueue_sidekiq_job(ActivityPub::LowPriorityDeliveryWorker).with(JSON.generate(payload), anything, mallory.preferred_inbox_url) .and enqueue_sidekiq_job(ActivityPub::LowPriorityDeliveryWorker).with(payload.to_json, anything, mallory.preferred_inbox_url)
end end
end end
end end

View File

@@ -131,7 +131,7 @@ RSpec.describe Admin::SystemCheck::ElasticsearchCheck do
def stub_elasticsearch_error def stub_elasticsearch_error
client = instance_double(Elasticsearch::Client) client = instance_double(Elasticsearch::Client)
allow(client).to receive(:info).and_raise(Elasticsearch::Transport::Transport::Error) allow(client).to receive(:info).and_raise(Elastic::Transport::Transport::Error)
allow(Chewy).to receive(:client).and_return(client) allow(Chewy).to receive(:client).and_return(client)
end end
end end

View File

@@ -0,0 +1,14 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Elasticsearch::ClientExtensions do
describe '#initialize' do
it 'marks the connection as verified on initialization' do
client = Elasticsearch::Client.new
expect(client.instance_variable_get(:@verified))
.to be(true)
end
end
end

View File

@@ -87,7 +87,7 @@ RSpec.describe Mastodon::CLI::Domains do
end end
def json_summary def json_summary
JSON.generate('host.example': { activity: {} }) { 'host.example': { activity: {} } }.to_json
end end
end end
end end

View File

@@ -36,7 +36,7 @@ RSpec.describe Mastodon::CLI::Search do
context 'when server communication raises an error' do context 'when server communication raises an error' do
let(:options) { { reset_chewy: true } } let(:options) { { reset_chewy: true } }
before { allow(Chewy::Stash::Specification).to receive(:reset!).and_raise(Elasticsearch::Transport::Transport::Errors::InternalServerError) } before { allow(Chewy::Stash::Specification).to receive(:reset!).and_raise(Elastic::Transport::Transport::Errors::InternalServerError) }
it 'Exits with error message' do it 'Exits with error message' do
expect { subject } expect { subject }

View File

@@ -3,27 +3,34 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe Webhooks::PayloadRenderer do RSpec.describe Webhooks::PayloadRenderer do
subject(:renderer) { described_class.new(json) } subject(:renderer) { described_class.new(payload.to_json) }
let(:event) { Webhooks::EventPresenter.new(type, object) } let(:event) { Webhooks::EventPresenter.new(type, object) }
let(:payload) { ActiveModelSerializers::SerializableResource.new(event, serializer: REST::Admin::WebhookEventSerializer, scope: nil, scope_name: :current_user).as_json } let(:payload) { ActiveModelSerializers::SerializableResource.new(event, serializer: REST::Admin::WebhookEventSerializer, scope: nil, scope_name: :current_user).as_json }
let(:json) { JSON.generate(payload) }
describe '#render' do describe '#render' do
subject { renderer.render(template) }
context 'when event is account.approved' do context 'when event is account.approved' do
let(:type) { 'account.approved' } let(:type) { 'account.approved' }
let(:object) { Fabricate(:account, display_name: 'Foo"') } let(:object) { Fabricate(:account, display_name: 'Foo"', username: 'foofoobarbar') }
it 'renders event-related variables into template' do context 'with event-related variables' do
expect(renderer.render('foo={{event}}')).to eq 'foo=account.approved' let(:template) { 'foo={{event}}' }
it { is_expected.to eq('foo=account.approved') }
end end
it 'renders event-specific variables into template' do context 'with event-specific variables' do
expect(renderer.render('foo={{object.username}}')).to eq "foo=#{object.username}" let(:template) { 'foo={{object.username}}' }
it { is_expected.to eq('foo=foofoobarbar') }
end end
it 'escapes values for use in JSON' do context 'with values needing JSON escape' do
expect(renderer.render('foo={{object.account.display_name}}')).to eq 'foo=Foo\\"' let(:template) { 'foo={{object.account.display_name}}' }
it { is_expected.to eq('foo=Foo\\"') }
end end
end end
end end

View File

@@ -1,5 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'rails_helper'
RSpec.describe Account::Avatar do RSpec.describe Account::Avatar do
describe 'static avatars', :attachment_processing do describe 'static avatars', :attachment_processing do
describe 'with a square GIF' do describe 'with a square GIF' do

View File

@@ -1,5 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'rails_helper'
RSpec.describe Account::Header do RSpec.describe Account::Header do
describe 'base64-encoded files', :attachment_processing do describe 'base64-encoded files', :attachment_processing do
let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" } let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" }

View File

@@ -1,5 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'rails_helper'
RSpec.describe Account::Search do RSpec.describe Account::Search do
describe '.search_for' do describe '.search_for' do
before do before do

View File

@@ -91,7 +91,7 @@ RSpec.describe 'Donation campaigns' do
end end
before do before do
stub_request(:get, "#{api_url}?platform=web&seed=#{seed}&locale=en").to_return(body: JSON.generate(campaign_json), status: 200) stub_request(:get, "#{api_url}?platform=web&seed=#{seed}&locale=en").to_return(body: campaign_json.to_json, status: 200)
end end
it 'returns the expected campaign' do it 'returns the expected campaign' do
@@ -109,7 +109,7 @@ RSpec.describe 'Donation campaigns' do
expect(Rails.cache.read("donation_campaign_request:#{seed}:en", raw: true)) expect(Rails.cache.read("donation_campaign_request:#{seed}:en", raw: true))
.to eq 'campaign-1:en' .to eq 'campaign-1:en'
expect(Oj.load(Rails.cache.read('donation_campaign:campaign-1:en', raw: true))) expect(JSON.parse(Rails.cache.read('donation_campaign:campaign-1:en', raw: true)))
.to match(campaign_json) .to match(campaign_json)
end end
end end

View File

@@ -75,11 +75,11 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
shared_examples 'sets pinned posts' do shared_examples 'sets pinned posts' do
before do before do
stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: JSON.generate(status_json_pinned_known), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: status_json_pinned_known.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: JSON.generate(status_json_pinned_unknown_inlined), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: status_json_pinned_unknown_inlined.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/account/pinned/unknown-unreachable').to_return(status: 404) stub_request(:get, 'https://example.com/account/pinned/unknown-unreachable').to_return(status: 404)
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: JSON.generate(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: status_json_pinned_unknown_reachable.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: JSON.generate(featured_with_null), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: featured_with_null.to_json, headers: { 'Content-Type': 'application/activity+json' })
subject subject
end end
@@ -101,7 +101,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
let(:collection_or_uri) { actor.featured_collection_url } let(:collection_or_uri) { actor.featured_collection_url }
before do before do
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'sets pinned posts' it_behaves_like 'sets pinned posts'
@@ -122,7 +122,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
context 'when the endpoint is a Collection' do context 'when the endpoint is a Collection' do
before do before do
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'sets pinned posts' it_behaves_like 'sets pinned posts'
@@ -139,7 +139,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
end end
before do before do
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'sets pinned posts' it_behaves_like 'sets pinned posts'
@@ -148,11 +148,12 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
let(:items) { 'https://example.com/account/pinned/unknown-reachable' } let(:items) { 'https://example.com/account/pinned/unknown-reachable' }
before do before do
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: JSON.generate(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: status_json_pinned_unknown_reachable.to_json, headers: { 'Content-Type': 'application/activity+json' })
subject
end end
it 'sets expected posts as pinned posts' do it 'sets expected posts as pinned posts' do
subject
expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly( expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly(
'https://example.com/account/pinned/unknown-reachable' 'https://example.com/account/pinned/unknown-reachable'
) )
@@ -175,7 +176,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
end end
before do before do
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'sets pinned posts' it_behaves_like 'sets pinned posts'
@@ -184,11 +185,12 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
let(:items) { 'https://example.com/account/pinned/unknown-reachable' } let(:items) { 'https://example.com/account/pinned/unknown-reachable' }
before do before do
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: JSON.generate(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: status_json_pinned_unknown_reachable.to_json, headers: { 'Content-Type': 'application/activity+json' })
subject
end end
it 'sets expected posts as pinned posts' do it 'sets expected posts as pinned posts' do
subject
expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly( expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly(
'https://example.com/account/pinned/unknown-reachable' 'https://example.com/account/pinned/unknown-reachable'
) )

View File

@@ -38,7 +38,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService do
describe '#call' do describe '#call' do
context 'when the endpoint is a Collection' do context 'when the endpoint is a Collection' do
before do before do
stub_request(:get, collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'sets featured tags' it_behaves_like 'sets featured tags'
@@ -46,7 +46,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService do
context 'when the account already has featured tags' do context 'when the account already has featured tags' do
before do before do
stub_request(:get, collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
actor.featured_tags.create!(name: 'FoO') actor.featured_tags.create!(name: 'FoO')
actor.featured_tags.create!(name: 'baz') actor.featured_tags.create!(name: 'baz')
@@ -67,7 +67,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService do
end end
before do before do
stub_request(:get, collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'sets featured tags' it_behaves_like 'sets featured tags'
@@ -88,7 +88,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService do
end end
before do before do
stub_request(:get, collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'sets featured tags' it_behaves_like 'sets featured tags'

View File

@@ -38,8 +38,8 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
before do before do
actor[:inbox] = nil actor[:inbox] = nil
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
it 'fetches resource and looks up webfinger and returns nil' do it 'fetches resource and looks up webfinger and returns nil' do
@@ -54,8 +54,8 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
before do before do
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
it 'fetches resource and looks up webfinger and sets attributes' do it 'fetches resource and looks up webfinger and sets attributes' do
@@ -75,9 +75,9 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
before do before do
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
it 'fetches resource and looks up webfinger and follows redirection and sets attributes' do it 'fetches resource and looks up webfinger and follows redirection and sets attributes' do
@@ -98,8 +98,8 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } } let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
before do before do
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
it 'fetches resource and looks up webfinger and does not create account' do it 'fetches resource and looks up webfinger and does not create account' do
@@ -114,9 +114,9 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } } let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
before do before do
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
it 'fetches resource and looks up webfinger and follows redirect and does not create account' do it 'fetches resource and looks up webfinger and follows redirect and does not create account' do
@@ -130,7 +130,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
context 'with wrong id' do context 'with wrong id' do
it 'does not create account' do it 'does not create account' do
expect(subject.call('https://fake.address/@foo', prefetched_body: JSON.generate(actor))).to be_nil expect(subject.call('https://fake.address/@foo', prefetched_body: actor.to_json)).to be_nil
end end
end end
end end

View File

@@ -38,8 +38,8 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
before do before do
actor[:inbox] = nil actor[:inbox] = nil
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
it 'fetches resource and looks up webfinger and returns nil' do it 'fetches resource and looks up webfinger and returns nil' do
@@ -54,8 +54,8 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
before do before do
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
it 'fetches resource and looks up webfinger and sets values' do it 'fetches resource and looks up webfinger and sets values' do
@@ -75,9 +75,9 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } } let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
before do before do
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
it 'fetches resource and looks up webfinger and follows redirect and sets values' do it 'fetches resource and looks up webfinger and follows redirect and sets values' do
@@ -98,8 +98,8 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } } let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
before do before do
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
it 'fetches resource and looks up webfinger and does not create account' do it 'fetches resource and looks up webfinger and does not create account' do
@@ -114,9 +114,9 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } } let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
before do before do
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
it 'fetches resource and looks up webfinger and follows redirect and does not create account' do it 'fetches resource and looks up webfinger and follows redirect and does not create account' do
@@ -130,7 +130,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
context 'with wrong id' do context 'with wrong id' do
it 'does not create account' do it 'does not create account' do
expect(subject.call('https://fake.address/@foo', prefetched_body: JSON.generate(actor))).to be_nil expect(subject.call('https://fake.address/@foo', prefetched_body: actor.to_json)).to be_nil
end end
end end
end end

View File

@@ -50,8 +50,8 @@ RSpec.describe ActivityPub::FetchRemoteKeyService do
end end
before do before do
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
end end
describe '#call' do describe '#call' do
@@ -59,7 +59,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService do
context 'when the key is a sub-object from the actor' do context 'when the key is a sub-object from the actor' do
before do before do
stub_request(:get, public_key_id).to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, public_key_id).to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it 'returns the expected account' do it 'returns the expected account' do
@@ -71,7 +71,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService do
let(:public_key_id) { 'https://example.com/alice-public-key.json' } let(:public_key_id) { 'https://example.com/alice-public-key.json' }
before do before do
stub_request(:get, public_key_id).to_return(body: JSON.generate(key_json.merge({ '@context': ['https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, public_key_id).to_return(body: key_json.merge({ '@context': ['https://w3id.org/security/v1'] }).to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it 'returns the expected account' do it 'returns the expected account' do
@@ -84,7 +84,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService do
let(:actor_public_key) { 'https://example.com/alice-public-key.json' } let(:actor_public_key) { 'https://example.com/alice-public-key.json' }
before do before do
stub_request(:get, public_key_id).to_return(body: JSON.generate(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, public_key_id).to_return(body: key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }).to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it 'returns the nil' do it 'returns the nil' do

View File

@@ -11,7 +11,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
let(:follower) { Fabricate(:account, username: 'alice') } let(:follower) { Fabricate(:account, username: 'alice') }
let(:follow) { nil } let(:follow) { nil }
let(:response) { { body: JSON.generate(object), headers: { 'content-type': 'application/activity+json' } } } let(:response) { { body: object.to_json, headers: { 'content-type': 'application/activity+json' } } }
let(:existing_status) { nil } let(:existing_status) { nil }
let(:note) do let(:note) do
@@ -369,7 +369,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
end end
it 'creates statuses but not more than limit allows' do it 'creates statuses but not more than limit allows' do
expect { subject.call(object[:id], prefetched_body: JSON.generate(object)) } expect { subject.call(object[:id], prefetched_body: object.to_json) }
.to change { sender.statuses.count }.by_at_least(2) .to change { sender.statuses.count }.by_at_least(2)
.and change { sender.statuses.count }.by_at_most(3) .and change { sender.statuses.count }.by_at_most(3)
end end
@@ -419,7 +419,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
end end
it 'creates statuses but not more than limit allows' do it 'creates statuses but not more than limit allows' do
expect { subject.call(object[:id], prefetched_body: JSON.generate(object)) } expect { subject.call(object[:id], prefetched_body: object.to_json) }
.to change { sender.statuses.count }.by_at_least(2) .to change { sender.statuses.count }.by_at_least(2)
.and change { sender.statuses.count }.by_at_most(3) .and change { sender.statuses.count }.by_at_most(3)
end end

View File

@@ -58,7 +58,7 @@ RSpec.describe ActivityPub::FetchRepliesService do
context 'when passing the URL to the collection' do context 'when passing the URL to the collection' do
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it 'spawns workers for up to 5 replies on the same server' do it 'spawns workers for up to 5 replies on the same server' do
@@ -93,7 +93,7 @@ RSpec.describe ActivityPub::FetchRepliesService do
context 'when passing the URL to the collection' do context 'when passing the URL to the collection' do
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it 'spawns workers for up to 5 replies on the same server' do it 'spawns workers for up to 5 replies on the same server' do
@@ -132,7 +132,7 @@ RSpec.describe ActivityPub::FetchRepliesService do
context 'when passing the URL to the collection' do context 'when passing the URL to the collection' do
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it 'spawns workers for up to 5 replies on the same server' do it 'spawns workers for up to 5 replies on the same server' do

View File

@@ -21,7 +21,7 @@ RSpec.describe ActivityPub::ProcessCollectionService do
} }
end end
let(:json) { JSON.generate(payload) } let(:json) { payload.to_json }
describe '#call' do describe '#call' do
context 'when actor is suspended' do context 'when actor is suspended' do

View File

@@ -52,7 +52,7 @@ RSpec.describe ActivityPub::ProcessFeaturedItemService do
new_item = collection.collection_items.last new_item = collection.collection_items.last
expect(new_item.object_uri).to eq 'https://example.com/actor/1' expect(new_item.object_uri).to eq 'https://example.com/actor/1'
expect(new_item.approval_uri).to eq 'https://example.com/auth/1' expect(new_item.approval_uri).to be_nil
end end
context 'when an item exists for a local featured account' do context 'when an item exists for a local featured account' do
@@ -93,7 +93,7 @@ RSpec.describe ActivityPub::ProcessFeaturedItemService do
new_item = collection.collection_items.last new_item = collection.collection_items.last
expect(new_item.object_uri).to eq 'https://example.com/actor/1' expect(new_item.object_uri).to eq 'https://example.com/actor/1'
expect(new_item.approval_uri).to eq 'https://example.com/auth/1' expect(new_item.approval_uri).to be_nil
end end
end end
end end

View File

@@ -23,7 +23,7 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
], ],
} }
end end
let(:json) { Oj.load(JSON.generate(payload)) } let(:json) { JSON.parse(payload.to_json) }
let(:alice) { Fabricate(:account) } let(:alice) { Fabricate(:account) }
let(:bob) { Fabricate(:account) } let(:bob) { Fabricate(:account) }
@@ -544,8 +544,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
} }
end end
before do let(:quote_authorization_json) do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ {
'@context': [ '@context': [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
{ {
@@ -570,7 +570,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account), attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
interactingObject: ActivityPub::TagManager.instance.uri_for(status), interactingObject: ActivityPub::TagManager.instance.uri_for(status),
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status), interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
})) }
end
before do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
end end
it 'updates the approval URI and verifies the quote' do it 'updates the approval URI and verifies the quote' do
@@ -609,8 +613,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
} }
end end
before do let(:quote_authorization_json) do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ {
'@context': [ '@context': [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
{ {
@@ -635,7 +639,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account), attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
interactingObject: ActivityPub::TagManager.instance.uri_for(status), interactingObject: ActivityPub::TagManager.instance.uri_for(status),
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status), interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
})) }
end
before do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
end end
it 'updates the approval URI and verifies the quote' do it 'updates the approval URI and verifies the quote' do
@@ -818,8 +826,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
} }
end end
before do let(:quote_authorization_json) do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ {
'@context': [ '@context': [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
{ {
@@ -844,7 +852,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account), attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
interactingObject: ActivityPub::TagManager.instance.uri_for(status), interactingObject: ActivityPub::TagManager.instance.uri_for(status),
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status), interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
})) }
end
before do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
end end
it 'updates the approval URI and verifies the quote' do it 'updates the approval URI and verifies the quote' do
@@ -883,8 +895,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
} }
end end
before do let(:quote_authorization_json) do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ {
'@context': [ '@context': [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
{ {
@@ -909,7 +921,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account), attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
interactingObject: ActivityPub::TagManager.instance.uri_for(status), interactingObject: ActivityPub::TagManager.instance.uri_for(status),
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status), interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
})) }
end
before do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
end end
it 'updates the approval URI but does not verify the quote' do it 'updates the approval URI but does not verify the quote' do
@@ -1126,8 +1142,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
} }
end end
before do let(:quote_authorization_json) do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ {
'@context': [ '@context': [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
{ {
@@ -1152,7 +1168,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account), attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
interactingObject: ActivityPub::TagManager.instance.uri_for(status), interactingObject: ActivityPub::TagManager.instance.uri_for(status),
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status), interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
})) }
end
before do
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
end end
it 'updates the URI and unverifies the quote' do it 'updates the URI and unverifies the quote' do
@@ -1234,8 +1254,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
} }
end end
before do let(:quote_authorization_json) do
stub_request(:get, second_approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ {
'@context': [ '@context': [
'https://www.w3.org/ns/activitystreams', 'https://www.w3.org/ns/activitystreams',
{ {
@@ -1260,7 +1280,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
attributedTo: ActivityPub::TagManager.instance.uri_for(second_quoted_status.account), attributedTo: ActivityPub::TagManager.instance.uri_for(second_quoted_status.account),
interactingObject: ActivityPub::TagManager.instance.uri_for(status), interactingObject: ActivityPub::TagManager.instance.uri_for(status),
interactionTarget: ActivityPub::TagManager.instance.uri_for(second_quoted_status), interactionTarget: ActivityPub::TagManager.instance.uri_for(second_quoted_status),
})) }
end
before do
stub_request(:get, second_approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
end end
it 'updates the URI and unverifies the quote' do it 'updates the URI and unverifies the quote' do

View File

@@ -55,7 +55,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
context 'when the endpoint is a Collection of actor URIs' do context 'when the endpoint is a Collection of actor URIs' do
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'synchronizes followers' it_behaves_like 'synchronizes followers'
@@ -72,7 +72,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
end end
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'synchronizes followers' it_behaves_like 'synchronizes followers'
@@ -93,7 +93,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
end end
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'synchronizes followers' it_behaves_like 'synchronizes followers'
@@ -102,31 +102,31 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
context 'when the endpoint is a paginated Collection of actor URIs split across multiple pages' do context 'when the endpoint is a paginated Collection of actor URIs split across multiple pages' do
before do before do
stub_request(:get, 'https://example.com/partial-followers') stub_request(:get, 'https://example.com/partial-followers')
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ .to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: {
'@context': 'https://www.w3.org/ns/activitystreams', '@context': 'https://www.w3.org/ns/activitystreams',
type: 'Collection', type: 'Collection',
id: 'https://example.com/partial-followers', id: 'https://example.com/partial-followers',
first: 'https://example.com/partial-followers/1', first: 'https://example.com/partial-followers/1',
})) }.to_json)
stub_request(:get, 'https://example.com/partial-followers/1') stub_request(:get, 'https://example.com/partial-followers/1')
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ .to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: {
'@context': 'https://www.w3.org/ns/activitystreams', '@context': 'https://www.w3.org/ns/activitystreams',
type: 'CollectionPage', type: 'CollectionPage',
id: 'https://example.com/partial-followers/1', id: 'https://example.com/partial-followers/1',
partOf: 'https://example.com/partial-followers', partOf: 'https://example.com/partial-followers',
next: 'https://example.com/partial-followers/2', next: 'https://example.com/partial-followers/2',
items: [alice, eve].map { |account| ActivityPub::TagManager.instance.uri_for(account) }, items: [alice, eve].map { |account| ActivityPub::TagManager.instance.uri_for(account) },
})) }.to_json)
stub_request(:get, 'https://example.com/partial-followers/2') stub_request(:get, 'https://example.com/partial-followers/2')
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ .to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: {
'@context': 'https://www.w3.org/ns/activitystreams', '@context': 'https://www.w3.org/ns/activitystreams',
type: 'CollectionPage', type: 'CollectionPage',
id: 'https://example.com/partial-followers/2', id: 'https://example.com/partial-followers/2',
partOf: 'https://example.com/partial-followers', partOf: 'https://example.com/partial-followers',
items: ActivityPub::TagManager.instance.uri_for(mallory), items: ActivityPub::TagManager.instance.uri_for(mallory),
})) }.to_json)
end end
it_behaves_like 'synchronizes followers' it_behaves_like 'synchronizes followers'
@@ -135,22 +135,22 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
context 'when the endpoint is a paginated Collection of actor URIs split across, but one page errors out' do context 'when the endpoint is a paginated Collection of actor URIs split across, but one page errors out' do
before do before do
stub_request(:get, 'https://example.com/partial-followers') stub_request(:get, 'https://example.com/partial-followers')
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ .to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: {
'@context': 'https://www.w3.org/ns/activitystreams', '@context': 'https://www.w3.org/ns/activitystreams',
type: 'Collection', type: 'Collection',
id: 'https://example.com/partial-followers', id: 'https://example.com/partial-followers',
first: 'https://example.com/partial-followers/1', first: 'https://example.com/partial-followers/1',
})) }.to_json)
stub_request(:get, 'https://example.com/partial-followers/1') stub_request(:get, 'https://example.com/partial-followers/1')
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({ .to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: {
'@context': 'https://www.w3.org/ns/activitystreams', '@context': 'https://www.w3.org/ns/activitystreams',
type: 'CollectionPage', type: 'CollectionPage',
id: 'https://example.com/partial-followers/1', id: 'https://example.com/partial-followers/1',
partOf: 'https://example.com/partial-followers', partOf: 'https://example.com/partial-followers',
next: 'https://example.com/partial-followers/2', next: 'https://example.com/partial-followers/2',
items: [mallory].map { |account| ActivityPub::TagManager.instance.uri_for(account) }, items: [mallory].map { |account| ActivityPub::TagManager.instance.uri_for(account) },
})) }.to_json)
stub_request(:get, 'https://example.com/partial-followers/2') stub_request(:get, 'https://example.com/partial-followers/2')
.to_return(status: 404) .to_return(status: 404)
@@ -185,7 +185,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
before do before do
stub_const('ActivityPub::SynchronizeFollowersService::MAX_COLLECTION_PAGES', 1) stub_const('ActivityPub::SynchronizeFollowersService::MAX_COLLECTION_PAGES', 1)
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it 'confirms pending follow request but does not remove extra followers' do it 'confirms pending follow request but does not remove extra followers' do
@@ -213,7 +213,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
context 'when the endpoint is a Collection of actor URIs' do context 'when the endpoint is a Collection of actor URIs' do
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'synchronizes followers' it_behaves_like 'synchronizes followers'
@@ -230,7 +230,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
end end
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'synchronizes followers' it_behaves_like 'synchronizes followers'
@@ -251,7 +251,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
end end
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'synchronizes followers' it_behaves_like 'synchronizes followers'
@@ -263,7 +263,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
context 'when the endpoint is a Collection of actor URIs' do context 'when the endpoint is a Collection of actor URIs' do
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it 'does not remove followers' do it 'does not remove followers' do
@@ -286,7 +286,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
end end
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it 'does not remove followers' do it 'does not remove followers' do
@@ -313,7 +313,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
end end
before do before do
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it 'does not remove followers' do it 'does not remove followers' do

View File

@@ -12,14 +12,14 @@ RSpec.describe ActivityPub::VerifyFeaturedItemService do
account: nil, account: nil,
state: :pending, state: :pending,
uri: 'https://other.example.com/items/1', uri: 'https://other.example.com/items/1',
object_uri: 'https://example.com/actor/1', object_uri: 'https://example.com/actor/1')
approval_uri: verification_json['id'])
end end
let(:approval_uri) { 'https://example.com/auth/1' }
let(:verification_json) do let(:verification_json) do
{ {
'@context' => 'https://www.w3.org/ns/activitystreams', '@context' => 'https://www.w3.org/ns/activitystreams',
'type' => 'FeatureAuthorization', 'type' => 'FeatureAuthorization',
'id' => 'https://example.com/auth/1', 'id' => approval_uri,
'interactionTarget' => 'https://example.com/actor/1', 'interactionTarget' => 'https://example.com/actor/1',
'interactingObject' => collection.uri, 'interactingObject' => collection.uri,
} }
@@ -41,12 +41,13 @@ RSpec.describe ActivityPub::VerifyFeaturedItemService do
before { featured_account } before { featured_account }
it 'verifies and creates the item' do it 'verifies and creates the item' do
subject.call(collection_item) subject.call(collection_item, approval_uri)
expect(verification_request).to have_been_requested expect(verification_request).to have_been_requested
expect(collection_item.account_id).to eq featured_account.id expect(collection_item.account_id).to eq featured_account.id
expect(collection_item).to be_accepted expect(collection_item).to be_accepted
expect(collection_item.approval_uri).to eq approval_uri
end end
end end
@@ -59,13 +60,14 @@ RSpec.describe ActivityPub::VerifyFeaturedItemService do
end end
it 'fetches the actor and creates the item' do it 'fetches the actor and creates the item' do
subject.call(collection_item) subject.call(collection_item, approval_uri)
expect(stubbed_service).to have_received(:call) expect(stubbed_service).to have_received(:call)
expect(verification_request).to have_been_requested expect(verification_request).to have_been_requested
expect(collection_item.account_id).to eq featured_account.id expect(collection_item.account_id).to eq featured_account.id
expect(collection_item).to be_accepted expect(collection_item).to be_accepted
expect(collection_item.approval_uri).to eq approval_uri
end end
end end
end end
@@ -77,7 +79,7 @@ RSpec.describe ActivityPub::VerifyFeaturedItemService do
end end
it 'creates item without attached account and in proper state' do it 'creates item without attached account and in proper state' do
subject.call(collection_item) subject.call(collection_item, approval_uri)
expect(collection_item.account_id).to be_nil expect(collection_item.account_id).to be_nil
expect(collection_item).to be_rejected expect(collection_item).to be_rejected

View File

@@ -76,7 +76,7 @@ RSpec.describe ActivityPub::VerifyQuoteService do
before do before do
stub_request(:get, approval_uri) stub_request(:get, approval_uri)
.to_return(status: 200, body: JSON.generate(json), headers: { 'Content-Type': 'application/activity+json' }) .to_return(status: 200, body: json.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
context 'with a valid activity for already-fetched posts' do context 'with a valid activity for already-fetched posts' do
@@ -179,7 +179,7 @@ RSpec.describe ActivityPub::VerifyQuoteService do
context 'with a valid activity for already-fetched posts, with a pre-fetched approval' do context 'with a valid activity for already-fetched posts, with a pre-fetched approval' do
it 'updates the status without fetching the activity' do it 'updates the status without fetching the activity' do
expect { subject.call(quote, prefetched_approval: JSON.generate(json)) } expect { subject.call(quote, prefetched_approval: json.to_json) }
.to change(quote, :state).to('accepted') .to change(quote, :state).to('accepted')
expect(a_request(:get, approval_uri)) expect(a_request(:get, approval_uri))

View File

@@ -19,17 +19,15 @@ RSpec.describe FetchRemoteStatusService do
context 'when protocol is :activitypub' do context 'when protocol is :activitypub' do
subject { described_class.new.call(note[:id], prefetched_body: prefetched_body) } subject { described_class.new.call(note[:id], prefetched_body: prefetched_body) }
let(:prefetched_body) { JSON.generate(note) } let(:prefetched_body) { note.to_json }
before do
subject
end
it 'creates status' do it 'creates status' do
status = account.statuses.first expect { subject }
.to change(Status, :count).by(1)
expect(status).to_not be_nil expect(account.statuses.first)
expect(status.text).to eq 'Lorem ipsum' .to be_present
.and have_attributes(text: 'Lorem ipsum')
end end
end end
end end

View File

@@ -150,7 +150,7 @@ RSpec.describe ResolveAccountService do
end end
context 'with webfinger response subject missing a host value' do context 'with webfinger response subject missing a host value' do
let(:body) { JSON.generate({ subject: 'user@' }) } let(:body) { { subject: 'user@' }.to_json }
let(:url) { 'https://host.example/.well-known/webfinger?resource=acct:user@host.example' } let(:url) { 'https://host.example/.well-known/webfinger?resource=acct:user@host.example' }
before do before do

View File

@@ -92,7 +92,7 @@ RSpec.describe SoftwareUpdateCheckService do
end end
before do before do
stub_request(:get, full_update_check_url).to_return(body: JSON.generate(server_json)) stub_request(:get, full_update_check_url).to_return(body: server_json.to_json)
end end
it 'updates the list of known updates' do it 'updates the list of known updates' do

View File

@@ -161,8 +161,8 @@ class StreamingClient
def wait_for_message def wait_for_message
message = @connection.wait_for_event(:message) message = @connection.wait_for_event(:message)
event = Oj.load(message) event = JSON.parse(message)
event['payload'] = Oj.load(event['payload']) if event['payload'] event['payload'] = JSON.parse(event['payload']) if event['payload']
event.deep_symbolize_keys event.deep_symbolize_keys
end end

View File

@@ -126,11 +126,11 @@ RSpec.describe ActivityPub::FetchAllRepliesWorker do
all_items.each do |item| all_items.each do |item|
next if [top_note_uri, reply_note_uri].include? item next if [top_note_uri, reply_note_uri].include? item
stub_request(:get, item).to_return(status: 200, body: JSON.generate(empty_object), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, item).to_return(status: 200, body: empty_object.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
stub_request(:get, top_note_uri).to_return(status: 200, body: JSON.generate(top_object), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, top_note_uri).to_return(status: 200, body: top_object.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, reply_note_uri).to_return(status: 200, body: JSON.generate(reply_object), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, reply_note_uri).to_return(status: 200, body: reply_object.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
shared_examples 'fetches all replies' do shared_examples 'fetches all replies' do
@@ -180,8 +180,8 @@ RSpec.describe ActivityPub::FetchAllRepliesWorker do
end end
before do before do
stub_request(:get, top_collection_uri).to_return(status: 200, body: JSON.generate(replies_top), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, top_collection_uri).to_return(status: 200, body: replies_top.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, reply_collection_uri).to_return(status: 200, body: JSON.generate(replies_nested), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, reply_collection_uri).to_return(status: 200, body: replies_nested.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'fetches all replies' it_behaves_like 'fetches all replies'
@@ -254,8 +254,8 @@ RSpec.describe ActivityPub::FetchAllRepliesWorker do
end end
before do before do
stub_request(:get, top_page_2_uri).to_return(status: 200, body: JSON.generate(top_page_two), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, top_page_2_uri).to_return(status: 200, body: top_page_two.to_json, headers: { 'Content-Type': 'application/activity+json' })
stub_request(:get, reply_page_2_uri).to_return(status: 200, body: JSON.generate(reply_page_two), headers: { 'Content-Type': 'application/activity+json' }) stub_request(:get, reply_page_2_uri).to_return(status: 200, body: reply_page_two.to_json, headers: { 'Content-Type': 'application/activity+json' })
end end
it_behaves_like 'fetches all replies' it_behaves_like 'fetches all replies'

View File

@@ -17,7 +17,7 @@ RSpec.describe ActivityPub::FetchRepliesWorker do
} }
end end
let(:json) { JSON.generate(payload) } let(:json) { payload.to_json }
describe 'perform' do describe 'perform' do
it 'performs a request if the collection URI is from the same host' do it 'performs a request if the collection URI is from the same host' do

View File

@@ -12,13 +12,13 @@ RSpec.describe ActivityPub::VerifyFeaturedItemWorker do
before { stub_service } before { stub_service }
it 'sends the status to the service' do it 'sends the status to the service' do
worker.perform(collection_item.id) worker.perform(collection_item.id, 'https://example.com/authorizations/1')
expect(service).to have_received(:call).with(collection_item) expect(service).to have_received(:call).with(collection_item, 'https://example.com/authorizations/1')
end end
it 'returns nil for non-existent record' do it 'returns nil for non-existent record' do
result = worker.perform(123_123_123) result = worker.perform(123_123_123, 'https://example.com/authorizations/1')
expect(result).to be_nil expect(result).to be_nil
end end

View File

@@ -10715,10 +10715,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"pg-connection-string@npm:^2.11.0, pg-connection-string@npm:^2.6.0": "pg-connection-string@npm:^2.12.0, pg-connection-string@npm:^2.6.0":
version: 2.11.0 version: 2.12.0
resolution: "pg-connection-string@npm:2.11.0" resolution: "pg-connection-string@npm:2.12.0"
checksum: 10c0/7a4bcf9b4f1e1fee6482e2bd814f544d451240059be6b8a186f24f73f163f1c599bb8c4984c398254869f744f6c3659b83e285c3d525fc640e99c60c453bd0df checksum: 10c0/3a26c62884a9f0464718f652bd5d6bce276ebda830c0fef4de4f88ae73c2507d70cae1d45c2f5b49bebd76187fb4c94f889d07c53fca6acd06b2eecbebcdc336
languageName: node languageName: node
linkType: hard linkType: hard
@@ -10729,19 +10729,19 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"pg-pool@npm:^3.12.0": "pg-pool@npm:^3.13.0":
version: 3.12.0 version: 3.13.0
resolution: "pg-pool@npm:3.12.0" resolution: "pg-pool@npm:3.13.0"
peerDependencies: peerDependencies:
pg: ">=8.0" pg: ">=8.0"
checksum: 10c0/b09da392ae2d0dae7bdf62b8557d3643bb7d84335894bc536f16ddd0da116b44c2f2770c88ff71a80252988ca115ec95a480cc047a75df34fbbbb2432b3a75da checksum: 10c0/2756f79cda14e3834356f2ca035deab806bca2172a38a488b62ada54bd3e65d33f583661bbe96da0c0e75e6bc59807ada733c37efca6e24ae2893429936a1549
languageName: node languageName: node
linkType: hard linkType: hard
"pg-protocol@npm:*, pg-protocol@npm:^1.12.0": "pg-protocol@npm:*, pg-protocol@npm:^1.13.0":
version: 1.12.0 version: 1.13.0
resolution: "pg-protocol@npm:1.12.0" resolution: "pg-protocol@npm:1.13.0"
checksum: 10c0/577f33c756f6503682d9ac17fd813f9edbe4a1716e497f17d36b6edaf9bf8383accaf8cd7422c49e2fbe4eb28ef275bc52fbd8287e154d4510f50b9ccefe4165 checksum: 10c0/a4e851e6bb8ff404ca19d561cf49b6b0caf45163bd3f289889edaf6c4e9fb25b08fb57f50d37a8cc86007efcf2cbb3dd2372c97a353a546f45eb49ddebc84fa9
languageName: node languageName: node
linkType: hard linkType: hard
@@ -10759,13 +10759,13 @@ __metadata:
linkType: hard linkType: hard
"pg@npm:^8.5.0": "pg@npm:^8.5.0":
version: 8.19.0 version: 8.20.0
resolution: "pg@npm:8.19.0" resolution: "pg@npm:8.20.0"
dependencies: dependencies:
pg-cloudflare: "npm:^1.3.0" pg-cloudflare: "npm:^1.3.0"
pg-connection-string: "npm:^2.11.0" pg-connection-string: "npm:^2.12.0"
pg-pool: "npm:^3.12.0" pg-pool: "npm:^3.13.0"
pg-protocol: "npm:^1.12.0" pg-protocol: "npm:^1.13.0"
pg-types: "npm:2.2.0" pg-types: "npm:2.2.0"
pgpass: "npm:1.0.5" pgpass: "npm:1.0.5"
peerDependencies: peerDependencies:
@@ -10776,7 +10776,7 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
pg-native: pg-native:
optional: true optional: true
checksum: 10c0/7713d6ef9f32746370f2bd599ebfa54d22bbdbb3a256a64b76997dd8a7279a5734dde260d6a1da22047171604fba88bd273d570c77b16f08ebe32a47ffbe2aba checksum: 10c0/e21d44b9fb3ec188e67778d7abd32d945a546f2da5128b6c8c16da8ae1e42fdc953c0d6f0a2ee65d11f31808c1dffaf908cb9c880cd2e8f0ae05525e4b8bc832
languageName: node languageName: node
linkType: hard linkType: hard