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

Conflicts:
- `.github/dependabot.yml`:
  Upstream made changes, but we had removed it.
  Discarded upstream changes.
- `.rubocop_todo.yml`:
  Upstream regenerated the file, we had some glitch-soc-specific ignores.
- `app/models/account_statuses_filter.rb`:
  Minor upstream code style change where glitch-soc had slightly different code
  due to handling of local-only posts.
  Updated to match upstream's code style.
- `app/models/status.rb`:
  Upstream moved ActiveRecord callback definitions, glitch-soc had an extra one.
  Moved the definitions as upstream did.
- `app/services/backup_service.rb`:
  Upstream rewrote a lot of the backup service, glitch-soc had changes because
  of exporting local-only posts.
  Took upstream changes and added back code to deal with local-only posts.
- `config/routes.rb`:
  Upstream split the file into different files, while glitch-soc had a few
  extra routes.
  Extra routes added to `config/routes/settings.rb`, `config/routes/api.rb`
  and `config/routes/admin.rb`
- `db/schema.rb`:
  Upstream has new migrations, while glitch-soc had an extra migration.
  Updated the expected serial number to match upstream's.
- `lib/mastodon/version.rb`:
  Upstream added support to set version tags from environment variables, while
  glitch-soc has an extra `+glitch` tag.
  Changed the code to support upstream's feature but prepending a `+glitch`.
- `spec/lib/activitypub/activity/create_spec.rb`:
  Minor code style change upstream, while glitch-soc has extra tests due to
  `directMessage` handling.
  Applied upstream's changes while keeping glitch-soc's extra tests.
- `spec/models/concerns/account_interactions_spec.rb`:
  Minor code style change upstream, while glitch-soc has extra tests.
  Applied upstream's changes while keeping glitch-soc's extra tests.
This commit is contained in:
Claire
2023-05-08 19:05:55 +02:00
429 changed files with 6138 additions and 3323 deletions

View File

@ -43,7 +43,7 @@ RSpec.describe ActivityPub::Activity::Accept do
end
end
context 'given a relay' do
context 'when given a relay' do
subject { described_class.new(json, sender) }
let!(:relay) { Fabricate(:relay, state: :pending, follow_activity_id: 'https://abc-123/456') }

View File

@ -39,7 +39,7 @@ RSpec.describe ActivityPub::Activity::Announce do
subject.perform
end
context 'a known status' do
context 'with known status' do
let(:object_json) do
ActivityPub::TagManager.instance.uri_for(status)
end
@ -49,7 +49,7 @@ RSpec.describe ActivityPub::Activity::Announce do
end
end
context 'an unknown status' do
context 'with unknown status' do
let(:object_json) { 'https://example.com/actor/hello-world' }
it 'creates a reblog by sender of status' do
@ -60,7 +60,7 @@ RSpec.describe ActivityPub::Activity::Announce do
end
end
context 'self-boost of a previously unknown status with correct attributedTo' do
context 'when self-boost of a previously unknown status with correct attributedTo' do
let(:object_json) do
{
id: 'https://example.com/actor#bar',
@ -76,7 +76,7 @@ RSpec.describe ActivityPub::Activity::Announce do
end
end
context 'self-boost of a previously unknown status with correct attributedTo, inlined Collection in audience' do
context 'when self-boost of a previously unknown status with correct attributedTo, inlined Collection in audience' do
let(:object_json) do
{
id: 'https://example.com/actor#bar',
@ -123,7 +123,7 @@ RSpec.describe ActivityPub::Activity::Announce do
stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json))
end
context 'and the relay is enabled' do
context 'when the relay is enabled' do
before do
relay.update(state: :accepted)
subject.perform
@ -135,7 +135,7 @@ RSpec.describe ActivityPub::Activity::Announce do
end
end
context 'and the relay is disabled' do
context 'when the relay is disabled' do
before do
subject.perform
end

View File

@ -31,7 +31,7 @@ RSpec.describe ActivityPub::Activity::Create do
subject.perform
end
context 'object has been edited' do
context 'when object has been edited' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -57,7 +57,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'object has update date equal to creation date' do
context 'when object has update date equal to creation date' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -83,7 +83,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'unknown object type' do
context 'with an unknown object type' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -97,7 +97,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'standalone' do
context 'with a standalone' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -121,7 +121,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'public with explicit public address' do
context 'when public with explicit public address' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -139,7 +139,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'public with as:Public' do
context 'when public with as:Public' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -157,7 +157,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'public with Public' do
context 'when public with Public' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -175,7 +175,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'unlisted with explicit public address' do
context 'when unlisted with explicit public address' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -193,7 +193,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'unlisted with as:Public' do
context 'when unlisted with as:Public' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -211,7 +211,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'unlisted with Public' do
context 'when unlisted with Public' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -229,7 +229,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'private' do
context 'when private' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -247,7 +247,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'private with inlined Collection in audience' do
context 'when private with inlined Collection in audience' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
@ -269,7 +269,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'limited' do
context 'when limited' do
let(:recipient) { Fabricate(:account) }
let(:object_json) do
@ -294,7 +294,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'limited when direct message assertion is false' do
context 'when directMessage attribute is false' do
let(:recipient) { Fabricate(:account) }
let(:object_json) do
@ -311,7 +311,7 @@ RSpec.describe ActivityPub::Activity::Create do
}
end
it 'creates status' do
it 'creates status with limited visibility' do
status = sender.statuses.first
expect(status).to_not be_nil
@ -319,7 +319,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'direct' do
context 'when direct' do
let(:recipient) { Fabricate(:account) }
let(:object_json) do
@ -335,7 +335,7 @@ RSpec.describe ActivityPub::Activity::Create do
}
end
it 'creates status' do
it 'creates status with direct visibility' do
status = sender.statuses.first
expect(status).to_not be_nil
@ -343,7 +343,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'direct when direct message assertion is true' do
context 'when directMessage attribute is true' do
let(:recipient) { Fabricate(:account) }
let(:object_json) do
@ -364,7 +364,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
end
context 'as a reply' do
context 'with a reply' do
let(:original_status) { Fabricate(:status) }
let(:object_json) do

View File

@ -20,7 +20,7 @@ RSpec.describe ActivityPub::Activity::Follow do
subject { described_class.new(json, sender) }
context 'with no prior follow' do
context 'unlocked account' do
context 'with an unlocked account' do
before do
subject.perform
end
@ -35,7 +35,7 @@ RSpec.describe ActivityPub::Activity::Follow do
end
end
context 'silenced account following an unlocked account' do
context 'when silenced account following an unlocked account' do
before do
sender.touch(:silenced_at)
subject.perform
@ -51,7 +51,7 @@ RSpec.describe ActivityPub::Activity::Follow do
end
end
context 'unlocked account muting the sender' do
context 'with an unlocked account muting the sender' do
before do
recipient.mute!(sender)
subject.perform
@ -67,7 +67,7 @@ RSpec.describe ActivityPub::Activity::Follow do
end
end
context 'locked account' do
context 'when locked account' do
before do
recipient.update(locked: true)
subject.perform
@ -89,7 +89,7 @@ RSpec.describe ActivityPub::Activity::Follow do
sender.active_relationships.create!(target_account: recipient, uri: 'bar')
end
context 'unlocked account' do
context 'with an unlocked account' do
before do
subject.perform
end
@ -103,7 +103,7 @@ RSpec.describe ActivityPub::Activity::Follow do
end
end
context 'silenced account following an unlocked account' do
context 'when silenced account following an unlocked account' do
before do
sender.touch(:silenced_at)
subject.perform
@ -118,7 +118,7 @@ RSpec.describe ActivityPub::Activity::Follow do
end
end
context 'unlocked account muting the sender' do
context 'with an unlocked account muting the sender' do
before do
recipient.mute!(sender)
subject.perform
@ -133,7 +133,7 @@ RSpec.describe ActivityPub::Activity::Follow do
end
end
context 'locked account' do
context 'when locked account' do
before do
recipient.update(locked: true)
subject.perform
@ -154,7 +154,7 @@ RSpec.describe ActivityPub::Activity::Follow do
sender.follow_requests.create!(target_account: recipient, uri: 'bar')
end
context 'silenced account following an unlocked account' do
context 'when silenced account following an unlocked account' do
before do
sender.touch(:silenced_at)
subject.perform
@ -170,7 +170,7 @@ RSpec.describe ActivityPub::Activity::Follow do
end
end
context 'locked account' do
context 'when locked account' do
before do
recipient.update(locked: true)
subject.perform

View File

@ -27,7 +27,7 @@ RSpec.describe ActivityPub::Activity::Reject do
describe '#perform' do
subject { described_class.new(json, sender) }
context 'rejecting a pending follow request by target' do
context 'when rejecting a pending follow request by target' do
before do
Fabricate(:follow_request, account: recipient, target_account: sender)
subject.perform
@ -42,7 +42,7 @@ RSpec.describe ActivityPub::Activity::Reject do
end
end
context 'rejecting a pending follow request by uri' do
context 'when rejecting a pending follow request by uri' do
before do
Fabricate(:follow_request, account: recipient, target_account: sender, uri: 'bar')
subject.perform
@ -57,7 +57,7 @@ RSpec.describe ActivityPub::Activity::Reject do
end
end
context 'rejecting a pending follow request by uri only' do
context 'when rejecting a pending follow request by uri only' do
let(:object_json) { 'bar' }
before do
@ -74,7 +74,7 @@ RSpec.describe ActivityPub::Activity::Reject do
end
end
context 'rejecting an existing follow relationship by target' do
context 'when rejecting an existing follow relationship by target' do
before do
Fabricate(:follow, account: recipient, target_account: sender)
subject.perform
@ -89,7 +89,7 @@ RSpec.describe ActivityPub::Activity::Reject do
end
end
context 'rejecting an existing follow relationship by uri' do
context 'when rejecting an existing follow relationship by uri' do
before do
Fabricate(:follow, account: recipient, target_account: sender, uri: 'bar')
subject.perform
@ -104,7 +104,7 @@ RSpec.describe ActivityPub::Activity::Reject do
end
end
context 'rejecting an existing follow relationship by uri only' do
context 'when rejecting an existing follow relationship by uri only' do
let(:object_json) { 'bar' }
before do
@ -122,7 +122,7 @@ RSpec.describe ActivityPub::Activity::Reject do
end
end
context 'given a relay' do
context 'when given a relay' do
subject { described_class.new(json, sender) }
let!(:relay) { Fabricate(:relay, state: :pending, follow_activity_id: 'https://abc-123/456') }

View File

@ -3,43 +3,51 @@
require 'rails_helper'
RSpec.describe ActivityPub::Adapter do
class TestObject < ActiveModelSerializers::Model
attributes :foo
end
class TestWithBasicContextSerializer < ActivityPub::Serializer
attributes :foo
end
class TestWithNamedContextSerializer < ActivityPub::Serializer
context :security
attributes :foo
end
class TestWithNestedNamedContextSerializer < ActivityPub::Serializer
attributes :foo
has_one :virtual_object, key: :baz, serializer: TestWithNamedContextSerializer
def virtual_object
object
before do
test_object_class = Class.new(ActiveModelSerializers::Model) do
attributes :foo
end
end
stub_const('TestObject', test_object_class)
class TestWithContextExtensionSerializer < ActivityPub::Serializer
context_extensions :sensitive
attributes :foo
end
class TestWithNestedContextExtensionSerializer < ActivityPub::Serializer
context_extensions :manually_approves_followers
attributes :foo
has_one :virtual_object, key: :baz, serializer: TestWithContextExtensionSerializer
def virtual_object
object
test_with_basic_context_serializer = Class.new(ActivityPub::Serializer) do
attributes :foo
end
stub_const('TestWithBasicContextSerializer', test_with_basic_context_serializer)
test_with_named_context_serializer = Class.new(ActivityPub::Serializer) do
context :security
attributes :foo
end
stub_const('TestWithNamedContextSerializer', test_with_named_context_serializer)
test_with_nested_named_context_serializer = Class.new(ActivityPub::Serializer) do
attributes :foo
has_one :virtual_object, key: :baz, serializer: TestWithNamedContextSerializer
def virtual_object
object
end
end
stub_const('TestWithNestedNamedContextSerializer', test_with_nested_named_context_serializer)
test_with_context_extension_serializer = Class.new(ActivityPub::Serializer) do
context_extensions :sensitive
attributes :foo
end
stub_const('TestWithContextExtensionSerializer', test_with_context_extension_serializer)
test_with_nested_context_extension_serializer = Class.new(ActivityPub::Serializer) do
context_extensions :manually_approves_followers
attributes :foo
has_one :virtual_object, key: :baz, serializer: TestWithContextExtensionSerializer
def virtual_object
object
end
end
stub_const('TestWithNestedContextExtensionSerializer', test_with_nested_context_extension_serializer)
end
describe '#serializable_hash' do

View File

@ -3,22 +3,24 @@
require 'rails_helper'
describe ConnectionPool::SharedConnectionPool do
class MiniConnection
attr_reader :site
subject { described_class.new(size: 5, timeout: 5) { |site| mini_connection_class.new(site) } }
def initialize(site)
@site = site
let(:mini_connection_class) do
Class.new do
attr_reader :site
def initialize(site)
@site = site
end
end
end
subject { described_class.new(size: 5, timeout: 5) { |site| MiniConnection.new(site) } }
describe '#with' do
it 'runs a block with a connection' do
block_run = false
subject.with('foo') do |connection|
expect(connection).to be_a MiniConnection
expect(connection).to be_a mini_connection_class
block_run = true
end

View File

@ -3,30 +3,32 @@
require 'rails_helper'
describe ConnectionPool::SharedTimedStack do
class MiniConnection
attr_reader :site
subject { described_class.new(5) { |site| mini_connection_class.new(site) } }
def initialize(site)
@site = site
let(:mini_connection_class) do
Class.new do
attr_reader :site
def initialize(site)
@site = site
end
end
end
subject { described_class.new(5) { |site| MiniConnection.new(site) } }
describe '#push' do
it 'keeps the connection in the stack' do
subject.push(MiniConnection.new('foo'))
subject.push(mini_connection_class.new('foo'))
expect(subject.size).to eq 1
end
end
describe '#pop' do
it 'returns a connection' do
expect(subject.pop('foo')).to be_a MiniConnection
expect(subject.pop('foo')).to be_a mini_connection_class
end
it 'returns the same connection that was pushed in' do
connection = MiniConnection.new('foo')
connection = mini_connection_class.new('foo')
subject.push(connection)
expect(subject.pop('foo')).to be connection
end
@ -36,8 +38,8 @@ describe ConnectionPool::SharedTimedStack do
end
it 'repurposes a connection for a different site when maximum amount is reached' do
5.times { subject.push(MiniConnection.new('foo')) }
expect(subject.pop('bar')).to be_a MiniConnection
5.times { subject.push(mini_connection_class.new('foo')) }
expect(subject.pop('bar')).to be_a mini_connection_class
end
end
@ -47,14 +49,14 @@ describe ConnectionPool::SharedTimedStack do
end
it 'returns false when there are connections on the stack' do
subject.push(MiniConnection.new('foo'))
subject.push(mini_connection_class.new('foo'))
expect(subject.empty?).to be false
end
end
describe '#size' do
it 'returns the number of connections on the stack' do
2.times { subject.push(MiniConnection.new('foo')) }
2.times { subject.push(mini_connection_class.new('foo')) }
expect(subject.size).to eq 2
end
end

View File

@ -14,7 +14,7 @@ RSpec.describe EmojiFormatter do
let(:emojis) { [emoji] }
context 'given text that is not marked as html-safe' do
context 'when given text that is not marked as html-safe' do
let(:text) { 'Foo' }
it 'raises an argument error' do
@ -22,7 +22,7 @@ RSpec.describe EmojiFormatter do
end
end
context 'given text with an emoji shortcode at the start' do
context 'when given text with an emoji shortcode at the start' do
let(:text) { preformat_text(':coolcat: Beep boop') }
it 'converts the shortcode to an image tag' do
@ -30,7 +30,7 @@ RSpec.describe EmojiFormatter do
end
end
context 'given text with an emoji shortcode in the middle' do
context 'when given text with an emoji shortcode in the middle' do
let(:text) { preformat_text('Beep :coolcat: boop') }
it 'converts the shortcode to an image tag' do
@ -38,7 +38,7 @@ RSpec.describe EmojiFormatter do
end
end
context 'given text with concatenated emoji shortcodes' do
context 'when given text with concatenated emoji shortcodes' do
let(:text) { preformat_text(':coolcat::coolcat:') }
it 'does not touch the shortcodes' do
@ -46,7 +46,7 @@ RSpec.describe EmojiFormatter do
end
end
context 'given text with an emoji shortcode at the end' do
context 'when given text with an emoji shortcode at the end' do
let(:text) { preformat_text('Beep boop :coolcat:') }
it 'converts the shortcode to an image tag' do

View File

@ -9,7 +9,7 @@ RSpec.describe EntityCache do
describe '#emoji' do
subject { EntityCache.instance.emoji(shortcodes, domain) }
context 'called with an empty list of shortcodes' do
context 'when called with an empty list of shortcodes' do
let(:shortcodes) { [] }
let(:domain) { 'example.org' }

View File

@ -27,7 +27,7 @@ RSpec.describe FeedManager do
let(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') }
let(:jeff) { Fabricate(:account, username: 'jeff') }
context 'for home feed' do
context 'with home feed' do
it 'returns false for followee\'s status' do
status = Fabricate(:status, text: 'Hello world', account: alice)
bob.follow!(alice)
@ -162,7 +162,7 @@ RSpec.describe FeedManager do
end
end
context 'for mentions feed' do
context 'with mentions feed' do
it 'returns true for status that mentions blocked account' do
bob.block!(jeff)
status = PostStatusService.new.call(alice, text: 'Hey @jeff')
@ -195,7 +195,7 @@ RSpec.describe FeedManager do
it 'trims timelines if they will have more than FeedManager::MAX_ITEMS' do
account = Fabricate(:account)
status = Fabricate(:status)
members = FeedManager::MAX_ITEMS.times.map { |count| [count, count] }
members = Array.new(FeedManager::MAX_ITEMS) { |count| [count, count] }
redis.zadd("feed:home:#{account.id}", members)
FeedManager.instance.push_to_home(account, status)
@ -203,7 +203,7 @@ RSpec.describe FeedManager do
expect(redis.zcard("feed:home:#{account.id}")).to eq FeedManager::MAX_ITEMS
end
context 'reblogs' do
context 'with reblogs' do
it 'saves reblogs of unseen statuses' do
account = Fabricate(:account)
reblogged = Fabricate(:status)
@ -240,7 +240,7 @@ RSpec.describe FeedManager do
it 'does not save a new reblog of a recently-reblogged status' do
account = Fabricate(:account)
reblogged = Fabricate(:status)
reblogs = 2.times.map { Fabricate(:status, reblog: reblogged) }
reblogs = Array.new(2) { Fabricate(:status, reblog: reblogged) }
# The first reblog will be accepted
FeedManager.instance.push_to_home(account, reblogs.first)
@ -269,7 +269,7 @@ RSpec.describe FeedManager do
it 'does not save a new reblog of a multiply-reblogged-then-unreblogged status' do
account = Fabricate(:account)
reblogged = Fabricate(:status)
reblogs = 3.times.map { Fabricate(:status, reblog: reblogged) }
reblogs = Array.new(3) { Fabricate(:status, reblog: reblogged) }
# Accept the reblogs
FeedManager.instance.push_to_home(account, reblogs[0])
@ -285,7 +285,7 @@ RSpec.describe FeedManager do
it 'saves a new reblog of a long-ago-reblogged status' do
account = Fabricate(:account)
reblogged = Fabricate(:status)
reblogs = 2.times.map { Fabricate(:status, reblog: reblogged) }
reblogs = Array.new(2) { Fabricate(:status, reblog: reblogged) }
# The first reblog will be accepted
FeedManager.instance.push_to_home(account, reblogs.first)
@ -466,7 +466,7 @@ RSpec.describe FeedManager do
it 'leaves a multiply-reblogged status if another reblog was in feed' do
reblogged = Fabricate(:status)
reblogs = 3.times.map { Fabricate(:status, reblog: reblogged) }
reblogs = Array.new(3) { Fabricate(:status, reblog: reblogged) }
reblogs.each do |reblog|
FeedManager.instance.push_to_home(receiver, reblog)

View File

@ -18,7 +18,7 @@ RSpec.describe HtmlAwareFormatter do
context 'when remote' do
let(:local) { false }
context 'given plain text' do
context 'when given plain text' do
let(:text) { 'Beep boop' }
it 'keeps the plain text' do
@ -26,7 +26,7 @@ RSpec.describe HtmlAwareFormatter do
end
end
context 'given text containing script tags' do
context 'when given text containing script tags' do
let(:text) { '<script>alert("Hello")</script>' }
it 'strips the scripts' do
@ -34,7 +34,7 @@ RSpec.describe HtmlAwareFormatter do
end
end
context 'given text containing malicious classes' do
context 'when given text containing malicious classes' do
let(:text) { '<span class="mention status__content__spoiler-link">Show more</span>' }
it 'strips the malicious classes' do

View File

@ -40,7 +40,7 @@ RSpec.describe LinkDetailsExtractor do
context 'when structured data is present' do
let(:original_url) { 'https://example.com/page.html' }
context 'and is wrapped in CDATA tags' do
context 'when is wrapped in CDATA tags' do
let(:html) { <<~HTML }
<!doctype html>
<html>
@ -79,7 +79,7 @@ RSpec.describe LinkDetailsExtractor do
end
end
context 'but the first tag is invalid JSON' do
context 'with the first tag is invalid JSON' do
let(:html) { <<~HTML }
<!doctype html>
<html>

View File

@ -0,0 +1,64 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/settings_cli'
RSpec.describe Mastodon::SettingsCLI do
describe 'subcommand "registrations"' do
let(:cli) { Mastodon::RegistrationsCLI.new }
before do
Setting.registrations_mode = nil
end
describe '#open' do
it 'changes "registrations_mode" to "open"' do
expect { cli.open }.to change(Setting, :registrations_mode).from(nil).to('open')
end
it 'displays success message' do
expect { cli.open }.to output(
a_string_including('OK')
).to_stdout
end
end
describe '#approved' do
it 'changes "registrations_mode" to "approved"' do
expect { cli.approved }.to change(Setting, :registrations_mode).from(nil).to('approved')
end
it 'displays success message' do
expect { cli.approved }.to output(
a_string_including('OK')
).to_stdout
end
context 'with --require-reason' do
before do
cli.options = { require_reason: true }
end
it 'changes "registrations_mode" to "approved"' do
expect { cli.approved }.to change(Setting, :registrations_mode).from(nil).to('approved')
end
it 'sets "require_invite_text" to "true"' do
expect { cli.approved }.to change(Setting, :require_invite_text).from(false).to(true)
end
end
end
describe '#close' do
it 'changes "registrations_mode" to "none"' do
expect { cli.close }.to change(Setting, :registrations_mode).from(nil).to('none')
end
it 'displays success message' do
expect { cli.close }.to output(
a_string_including('OK')
).to_stdout
end
end
end
end

View File

@ -40,7 +40,7 @@ describe OStatus::TagManager do
describe '#uri_for' do
subject { OStatus::TagManager.instance.uri_for(target) }
context 'comment object' do
context 'with comment object' do
let(:target) { Fabricate(:status, created_at: '2000-01-01T00:00:00Z', reply: true) }
it 'returns the unique tag for status' do
@ -49,7 +49,7 @@ describe OStatus::TagManager do
end
end
context 'note object' do
context 'with note object' do
let(:target) { Fabricate(:status, created_at: '2000-01-01T00:00:00Z', reply: false, thread: nil) }
it 'returns the unique tag for status' do
@ -58,7 +58,7 @@ describe OStatus::TagManager do
end
end
context 'person object' do
context 'when person object' do
let(:target) { Fabricate(:account, username: 'alice') }
it 'returns the URL for account' do

View File

@ -33,7 +33,7 @@ describe RequestPool do
subject
threads = 20.times.map do |_i|
threads = Array.new(20) do |_i|
Thread.new do
20.times do
subject.with('http://example.com') do |http_client|

View File

@ -20,67 +20,67 @@ describe ScopeTransformer do
end
end
context 'for scope "read"' do
context 'with scope "read"' do
let(:input) { 'read' }
it_behaves_like 'a scope', nil, 'all', 'read'
end
context 'for scope "write"' do
context 'with scope "write"' do
let(:input) { 'write' }
it_behaves_like 'a scope', nil, 'all', 'write'
end
context 'for scope "follow"' do
context 'with scope "follow"' do
let(:input) { 'follow' }
it_behaves_like 'a scope', nil, 'follow', 'read/write'
end
context 'for scope "crypto"' do
context 'with scope "crypto"' do
let(:input) { 'crypto' }
it_behaves_like 'a scope', nil, 'crypto', 'read/write'
end
context 'for scope "push"' do
context 'with scope "push"' do
let(:input) { 'push' }
it_behaves_like 'a scope', nil, 'push', 'read/write'
end
context 'for scope "admin:read"' do
context 'with scope "admin:read"' do
let(:input) { 'admin:read' }
it_behaves_like 'a scope', 'admin', 'all', 'read'
end
context 'for scope "admin:write"' do
context 'with scope "admin:write"' do
let(:input) { 'admin:write' }
it_behaves_like 'a scope', 'admin', 'all', 'write'
end
context 'for scope "admin:read:accounts"' do
context 'with scope "admin:read:accounts"' do
let(:input) { 'admin:read:accounts' }
it_behaves_like 'a scope', 'admin', 'accounts', 'read'
end
context 'for scope "admin:write:accounts"' do
context 'with scope "admin:write:accounts"' do
let(:input) { 'admin:write:accounts' }
it_behaves_like 'a scope', 'admin', 'accounts', 'write'
end
context 'for scope "read:accounts"' do
context 'with scope "read:accounts"' do
let(:input) { 'read:accounts' }
it_behaves_like 'a scope', nil, 'accounts', 'read'
end
context 'for scope "write:accounts"' do
context 'with scope "write:accounts"' do
let(:input) { 'write:accounts' }
it_behaves_like 'a scope', nil, 'accounts', 'write'

View File

@ -44,7 +44,7 @@ describe StatusCacheHydrator do
let(:reblog) { Fabricate(:status) }
let(:status) { Fabricate(:status, reblog: reblog) }
context 'that has been favourited' do
context 'when it has been favourited' do
before do
FavouriteService.new.call(account, reblog)
end
@ -54,7 +54,7 @@ describe StatusCacheHydrator do
end
end
context 'that has been reblogged' do
context 'when it has been reblogged' do
before do
ReblogService.new.call(account, reblog)
end
@ -64,7 +64,7 @@ describe StatusCacheHydrator do
end
end
context 'that has been pinned' do
context 'when it has been pinned' do
let(:reblog) { Fabricate(:status, account: account) }
before do
@ -76,7 +76,7 @@ describe StatusCacheHydrator do
end
end
context 'that has been followed tags' do
context 'when it has been followed tags' do
let(:followed_tag) { Fabricate(:tag) }
before do
@ -90,7 +90,7 @@ describe StatusCacheHydrator do
end
end
context 'that has a poll authored by the user' do
context 'when it has a poll authored by the user' do
let(:poll) { Fabricate(:poll, account: account) }
let(:reblog) { Fabricate(:status, poll: poll, account: account) }
@ -99,7 +99,7 @@ describe StatusCacheHydrator do
end
end
context 'that has been voted in' do
context 'when it has been voted in' do
let(:poll) { Fabricate(:poll, options: %w(Yellow Blue)) }
let(:reblog) { Fabricate(:status, poll: poll) }
@ -112,7 +112,7 @@ describe StatusCacheHydrator do
end
end
context 'that matches account filters' do
context 'when it matches account filters' do
let(:reblog) { Fabricate(:status, text: 'this toot is about that banned word') }
before do

View File

@ -4,7 +4,7 @@ require 'rails_helper'
describe StatusReachFinder do
describe '#inboxes' do
context 'for a local status' do
context 'with a local status' do
subject { described_class.new(status) }
let(:parent_status) { nil }

View File

@ -8,7 +8,7 @@ RSpec.describe TextFormatter do
let(:preloaded_accounts) { nil }
context 'given text containing plain text' do
context 'when given text containing plain text' do
let(:text) { 'text' }
it 'paragraphizes the text' do
@ -16,7 +16,7 @@ RSpec.describe TextFormatter do
end
end
context 'given text containing line feeds' do
context 'when given text containing line feeds' do
let(:text) { "line\nfeed" }
it 'removes line feeds' do
@ -24,7 +24,7 @@ RSpec.describe TextFormatter do
end
end
context 'given text containing linkable mentions' do
context 'when given text containing linkable mentions' do
let(:preloaded_accounts) { [Fabricate(:account, username: 'alice')] }
let(:text) { '@alice' }
@ -33,7 +33,7 @@ RSpec.describe TextFormatter do
end
end
context 'given text containing unlinkable mentions' do
context 'when given text containing unlinkable mentions' do
let(:preloaded_accounts) { [] }
let(:text) { '@alice' }
@ -42,7 +42,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a stand-alone medium URL' do
context 'when given a stand-alone medium URL' do
let(:text) { 'https://hackernoon.com/the-power-to-build-communities-a-response-to-mark-zuckerberg-3f2cac9148a4' }
it 'matches the full URL' do
@ -50,7 +50,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a stand-alone google URL' do
context 'when given a stand-alone google URL' do
let(:text) { 'http://google.com' }
it 'matches the full URL' do
@ -58,7 +58,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a stand-alone URL with a newer TLD' do
context 'when given a stand-alone URL with a newer TLD' do
let(:text) { 'http://example.gay' }
it 'matches the full URL' do
@ -66,7 +66,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a stand-alone IDN URL' do
context 'when given a stand-alone IDN URL' do
let(:text) { 'https://nic.みんな/' }
it 'matches the full URL' do
@ -78,7 +78,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with a trailing period' do
context 'when given a URL with a trailing period' do
let(:text) { 'http://www.mcmansionhell.com/post/156408871451/50-states-of-mcmansion-hell-scottsdale-arizona. ' }
it 'matches the full URL but not the period' do
@ -86,7 +86,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL enclosed with parentheses' do
context 'when given a URL enclosed with parentheses' do
let(:text) { '(http://google.com/)' }
it 'matches the full URL but not the parentheses' do
@ -94,7 +94,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with a trailing exclamation point' do
context 'when given a URL with a trailing exclamation point' do
let(:text) { 'http://www.google.com!' }
it 'matches the full URL but not the exclamation point' do
@ -102,7 +102,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with a trailing single quote' do
context 'when given a URL with a trailing single quote' do
let(:text) { "http://www.google.com'" }
it 'matches the full URL but not the single quote' do
@ -110,7 +110,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with a trailing angle bracket' do
context 'when given a URL with a trailing angle bracket' do
let(:text) { 'http://www.google.com>' }
it 'matches the full URL but not the angle bracket' do
@ -118,7 +118,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with a query string' do
context 'when given a URL with a query string' do
context 'with escaped unicode character' do
let(:text) { 'https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&q=autolink' }
@ -152,7 +152,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with parentheses in it' do
context 'when given a URL with parentheses in it' do
let(:text) { 'https://en.wikipedia.org/wiki/Diaspora_(software)' }
it 'matches the full URL' do
@ -160,7 +160,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL in quotation marks' do
context 'when given a URL in quotation marks' do
let(:text) { '"https://example.com/"' }
it 'does not match the quotation marks' do
@ -168,7 +168,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL in angle brackets' do
context 'when given a URL in angle brackets' do
let(:text) { '<https://example.com/>' }
it 'does not match the angle brackets' do
@ -176,7 +176,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with Japanese path string' do
context 'when given a URL with Japanese path string' do
let(:text) { 'https://ja.wikipedia.org/wiki/日本' }
it 'matches the full URL' do
@ -184,7 +184,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with Korean path string' do
context 'when given a URL with Korean path string' do
let(:text) { 'https://ko.wikipedia.org/wiki/대한민국' }
it 'matches the full URL' do
@ -192,7 +192,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with a full-width space' do
context 'when given a URL with a full-width space' do
let(:text) { 'https://example.com/ abc123' }
it 'does not match the full-width space' do
@ -200,7 +200,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL in Japanese quotation marks' do
context 'when given a URL in Japanese quotation marks' do
let(:text) { '「[https://example.org/」' }
it 'does not match the quotation marks' do
@ -208,7 +208,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with Simplified Chinese path string' do
context 'when given a URL with Simplified Chinese path string' do
let(:text) { 'https://baike.baidu.com/item/中华人民共和国' }
it 'matches the full URL' do
@ -216,7 +216,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL with Traditional Chinese path string' do
context 'when given a URL with Traditional Chinese path string' do
let(:text) { 'https://zh.wikipedia.org/wiki/臺灣' }
it 'matches the full URL' do
@ -224,7 +224,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL containing unsafe code (XSS attack, visible part)' do
context 'when given a URL containing unsafe code (XSS attack, visible part)' do
let(:text) { 'http://example.com/b<del>b</del>' }
it 'does not include the HTML in the URL' do
@ -236,7 +236,7 @@ RSpec.describe TextFormatter do
end
end
context 'given a URL containing unsafe code (XSS attack, invisible part)' do
context 'when given a URL containing unsafe code (XSS attack, invisible part)' do
let(:text) { 'http://example.com/blahblahblahblah/a<script>alert("Hello")</script>' }
it 'does not include the HTML in the URL' do
@ -248,7 +248,7 @@ RSpec.describe TextFormatter do
end
end
context 'given text containing HTML code (script tag)' do
context 'when given text containing HTML code (script tag)' do
let(:text) { '<script>alert("Hello")</script>' }
it 'escapes the HTML' do
@ -256,7 +256,7 @@ RSpec.describe TextFormatter do
end
end
context 'given text containing HTML (XSS attack)' do
context 'when given text containing HTML (XSS attack)' do
let(:text) { %q{<img src="javascript:alert('XSS');">} }
it 'escapes the HTML' do
@ -264,7 +264,7 @@ RSpec.describe TextFormatter do
end
end
context 'given an invalid URL' do
context 'when given an invalid URL' do
let(:text) { 'http://www\.google\.com' }
it 'outputs the raw URL' do
@ -272,7 +272,7 @@ RSpec.describe TextFormatter do
end
end
context 'given text containing a hashtag' do
context 'when given text containing a hashtag' do
let(:text) { '#hashtag' }
it 'creates a hashtag link' do
@ -280,7 +280,7 @@ RSpec.describe TextFormatter do
end
end
context 'given text containing a hashtag with Unicode chars' do
context 'when given text containing a hashtag with Unicode chars' do
let(:text) { '#hashtagタグ' }
it 'creates a hashtag link' do
@ -288,7 +288,7 @@ RSpec.describe TextFormatter do
end
end
context 'given text with a stand-alone xmpp: URI' do
context 'when given text with a stand-alone xmpp: URI' do
let(:text) { 'xmpp:user@instance.com' }
it 'matches the full URI' do
@ -296,7 +296,7 @@ RSpec.describe TextFormatter do
end
end
context 'given text with an xmpp: URI with a query-string' do
context 'when given text with an xmpp: URI with a query-string' do
let(:text) { 'please join xmpp:muc@instance.com?join right now' }
it 'matches the full URI' do
@ -304,7 +304,7 @@ RSpec.describe TextFormatter do
end
end
context 'given text containing a magnet: URI' do
context 'when given text containing a magnet: URI' do
let(:text) { 'wikipedia gives this example of a magnet uri: magnet:?xt=urn:btih:c12fe1c06bba254a9dc9f519b335aa7c1367a88a' }
it 'matches the full URI' do

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Vacuum::ImportsVacuum do
subject { described_class.new }
let!(:old_unconfirmed) { Fabricate(:bulk_import, state: :unconfirmed, created_at: 2.days.ago) }
let!(:new_unconfirmed) { Fabricate(:bulk_import, state: :unconfirmed, created_at: 10.seconds.ago) }
let!(:recent_ongoing) { Fabricate(:bulk_import, state: :in_progress, created_at: 20.minutes.ago) }
let!(:recent_finished) { Fabricate(:bulk_import, state: :finished, created_at: 1.day.ago) }
let!(:old_finished) { Fabricate(:bulk_import, state: :finished, created_at: 2.months.ago) }
describe '#perform' do
it 'cleans up the expected imports' do
expect { subject.perform }.to change { BulkImport.all.pluck(:id) }.from([old_unconfirmed, new_unconfirmed, recent_ongoing, recent_finished, old_finished].map(&:id)).to([new_unconfirmed, recent_ongoing, recent_finished].map(&:id))
end
end
end