Merge branch 'main' into glitch-soc/merge-upstream

Conflicts:
- `README.md`:
  Discarded upstream changes: we have our own README
- `app/controllers/follower_accounts_controller.rb`:
  Port upstream's minor refactoring
This commit is contained in:
Claire
2022-12-15 20:25:25 +01:00
103 changed files with 1228 additions and 274 deletions

View File

@@ -70,6 +70,53 @@ RSpec.describe Admin::DomainBlocksController, type: :controller do
end
end
describe 'PUT #update' do
let!(:remote_account) { Fabricate(:account, domain: 'example.com') }
let(:domain_block) { Fabricate(:domain_block, domain: 'example.com', severity: original_severity) }
before do
BlockDomainService.new.call(domain_block)
end
let(:subject) do
post :update, params: { id: domain_block.id, domain_block: { domain: 'example.com', severity: new_severity } }
end
context 'downgrading a domain suspension to silence' do
let(:original_severity) { 'suspend' }
let(:new_severity) { 'silence' }
it 'changes the block severity' do
expect { subject }.to change { domain_block.reload.severity }.from('suspend').to('silence')
end
it 'undoes individual suspensions' do
expect { subject }.to change { remote_account.reload.suspended? }.from(true).to(false)
end
it 'performs individual silences' do
expect { subject }.to change { remote_account.reload.silenced? }.from(false).to(true)
end
end
context 'upgrading a domain silence to suspend' do
let(:original_severity) { 'silence' }
let(:new_severity) { 'suspend' }
it 'changes the block severity' do
expect { subject }.to change { domain_block.reload.severity }.from('silence').to('suspend')
end
it 'undoes individual silences' do
expect { subject }.to change { remote_account.reload.silenced? }.from(true).to(false)
end
it 'performs individual suspends' do
expect { subject }.to change { remote_account.reload.suspended? }.from(false).to(true)
end
end
end
describe 'DELETE #destroy' do
it 'unblocks the domain' do
service = double(call: true)

View File

@@ -71,6 +71,53 @@ RSpec.describe Api::V1::Admin::DomainBlocksController, type: :controller do
end
end
describe 'PUT #update' do
let!(:remote_account) { Fabricate(:account, domain: 'example.com') }
let(:domain_block) { Fabricate(:domain_block, domain: 'example.com', severity: original_severity) }
before do
BlockDomainService.new.call(domain_block)
end
let(:subject) do
post :update, params: { id: domain_block.id, domain: 'example.com', severity: new_severity }
end
context 'downgrading a domain suspension to silence' do
let(:original_severity) { 'suspend' }
let(:new_severity) { 'silence' }
it 'changes the block severity' do
expect { subject }.to change { domain_block.reload.severity }.from('suspend').to('silence')
end
it 'undoes individual suspensions' do
expect { subject }.to change { remote_account.reload.suspended? }.from(true).to(false)
end
it 'performs individual silences' do
expect { subject }.to change { remote_account.reload.silenced? }.from(false).to(true)
end
end
context 'upgrading a domain silence to suspend' do
let(:original_severity) { 'silence' }
let(:new_severity) { 'suspend' }
it 'changes the block severity' do
expect { subject }.to change { domain_block.reload.severity }.from('silence').to('suspend')
end
it 'undoes individual silences' do
expect { subject }.to change { remote_account.reload.silenced? }.from(true).to(false)
end
it 'performs individual suspends' do
expect { subject }.to change { remote_account.reload.suspended? }.from(false).to(true)
end
end
end
describe 'DELETE #destroy' do
let!(:block) { Fabricate(:domain_block) }

View File

@@ -35,4 +35,65 @@ describe Auth::PasswordsController, type: :controller do
end
end
end
describe 'POST #update' do
let(:user) { Fabricate(:user) }
before do
@password = 'reset0password'
request.env['devise.mapping'] = Devise.mappings[:user]
end
context 'with valid reset_password_token' do
let!(:session_activation) { Fabricate(:session_activation, user: user) }
let!(:access_token) { Fabricate(:access_token, resource_owner_id: user.id) }
let!(:web_push_subscription) { Fabricate(:web_push_subscription, access_token: access_token) }
before do
@token = user.send_reset_password_instructions
post :update, params: { user: { password: @password, password_confirmation: @password, reset_password_token: @token } }
end
it 'redirect to sign in' do
expect(response).to redirect_to '/auth/sign_in'
end
it 'changes password' do
this_user = User.find(user.id)
expect(this_user).to_not be_nil
expect(this_user.valid_password?(@password)).to be true
end
it 'deactivates all sessions' do
expect(user.session_activations.count).to eq 0
end
it 'revokes all access tokens' do
expect(Doorkeeper::AccessToken.active_for(user).count).to eq 0
end
it 'removes push subscriptions' do
expect(Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count).to eq 0
end
end
context 'with invalid reset_password_token' do
before do
post :update, params: { user: { password: @password, password_confirmation: @password, reset_password_token: 'some_invalid_value' } }
end
it 'renders reset password' do
expect(response).to render_template(:new)
end
it 'retains password' do
this_user = User.find(user.id)
expect(this_user).to_not be_nil
expect(this_user.external_or_valid_password?(user.password)).to be true
end
end
end
end

View File

@@ -27,6 +27,8 @@ describe WellKnown::NodeInfoController, type: :controller do
json = body_as_json
expect({ "foo" => 0 }).not_to match_json_schema("nodeinfo_2.0")
expect(json).to match_json_schema("nodeinfo_2.0")
expect(json[:version]).to eq '2.0'
expect(json[:usage]).to be_a Hash
expect(json[:software]).to be_a Hash

View File

@@ -113,7 +113,7 @@ describe ApplicationHelper do
Setting.site_title = site_title
end
it 'returns site title on production enviroment' do
it 'returns site title on production environment' do
Setting.site_title = 'site title'
expect(Rails.env).to receive(:production?).and_return(true)
expect(helper.title).to eq 'site title'

View File

@@ -0,0 +1,24 @@
# frozen_string_literal: true
require 'rails_helper'
describe FormattingHelper, type: :helper do
include Devise::Test::ControllerHelpers
describe '#rss_status_content_format' do
let(:status) { Fabricate(:status, text: 'Hello world<>', spoiler_text: 'This is a spoiler<>', poll: Fabricate(:poll, options: %w(Yes<> No))) }
let(:html) { helper.rss_status_content_format(status) }
it 'renders the spoiler text' do
expect(html).to include('<p>This is a spoiler&lt;&gt;</p><hr>')
end
it 'renders the status text' do
expect(html).to include('<p>Hello world&lt;&gt;</p>')
end
it 'renders the poll' do
expect(html).to include('<radio disabled="disabled">Yes&lt;&gt;</radio><br>')
end
end
end

View File

@@ -160,7 +160,7 @@ RSpec.describe Account, type: :model do
expect(account.avatar_remote_url).to eq 'https://remote.test/invalid_avatar'
expect(account.header_remote_url).to eq expectation.header_remote_url
expect(account.avatar_file_name).to eq nil
expect(account.header_file_name).to eq nil
expect(account.header_file_name).to eq expectation.header_file_name
end
end
end
@@ -658,6 +658,12 @@ RSpec.describe Account, type: :model do
end
end
describe '.requested_by_map' do
it 'returns an hash' do
expect(Account.requested_by_map([], 1)).to be_a Hash
end
end
describe 'MENTION_RE' do
subject { Account::MENTION_RE }

View File

@@ -10,6 +10,7 @@ RSpec.describe AccountRelationshipsPresenter do
allow(Account).to receive(:blocking_map).with(account_ids, current_account_id).and_return(default_map)
allow(Account).to receive(:muting_map).with(account_ids, current_account_id).and_return(default_map)
allow(Account).to receive(:requested_map).with(account_ids, current_account_id).and_return(default_map)
allow(Account).to receive(:requested_by_map).with(account_ids, current_account_id).and_return(default_map)
allow(Account).to receive(:domain_blocking_map).with(account_ids, current_account_id).and_return(default_map)
end
@@ -71,6 +72,14 @@ RSpec.describe AccountRelationshipsPresenter do
end
end
context 'options[:requested_by_map] is set' do
let(:options) { { requested_by_map: { 6 => true } } }
it 'sets @requested merged with default_map and options[:requested_by_map]' do
expect(presenter.requested_by).to eq default_map.merge(options[:requested_by_map])
end
end
context 'options[:domain_blocking_map] is set' do
let(:options) { { domain_blocking_map: { 7 => true } } }

View File

@@ -0,0 +1,6 @@
RSpec::Matchers.define :match_json_schema do |schema|
match do |input_json|
schema_path = Rails.root.join('spec', 'support', 'schema', "#{schema}.json").to_s
JSON::Validator.validate(schema_path, input_json, validate_schema: true)
end
end

View File

@@ -0,0 +1,170 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://nodeinfo.diaspora.software/ns/schema/2.0#",
"description": "NodeInfo schema version 2.0.",
"type": "object",
"additionalProperties": false,
"required": [
"version",
"software",
"protocols",
"services",
"openRegistrations",
"usage",
"metadata"
],
"properties": {
"version": {
"description": "The schema version, must be 2.0.",
"enum": ["2.0"]
},
"software": {
"description": "Metadata about server software in use.",
"type": "object",
"additionalProperties": false,
"required": ["name", "version"],
"properties": {
"name": {
"description": "The canonical name of this server software.",
"type": "string",
"pattern": "^[a-z0-9-]+$"
},
"version": {
"description": "The version of this server software.",
"type": "string"
}
}
},
"protocols": {
"description": "The protocols supported on this server.",
"type": "array",
"minItems": 1,
"items": {
"enum": [
"activitypub",
"buddycloud",
"dfrn",
"diaspora",
"libertree",
"ostatus",
"pumpio",
"tent",
"xmpp",
"zot"
]
}
},
"services": {
"description": "The third party sites this server can connect to via their application API.",
"type": "object",
"additionalProperties": false,
"required": ["inbound", "outbound"],
"properties": {
"inbound": {
"description": "The third party sites this server can retrieve messages from for combined display with regular traffic.",
"type": "array",
"minItems": 0,
"items": {
"enum": [
"atom1.0",
"gnusocial",
"imap",
"pnut",
"pop3",
"pumpio",
"rss2.0",
"twitter"
]
}
},
"outbound": {
"description": "The third party sites this server can publish messages to on the behalf of a user.",
"type": "array",
"minItems": 0,
"items": {
"enum": [
"atom1.0",
"blogger",
"buddycloud",
"diaspora",
"dreamwidth",
"drupal",
"facebook",
"friendica",
"gnusocial",
"google",
"insanejournal",
"libertree",
"linkedin",
"livejournal",
"mediagoblin",
"myspace",
"pinterest",
"pnut",
"posterous",
"pumpio",
"redmatrix",
"rss2.0",
"smtp",
"tent",
"tumblr",
"twitter",
"wordpress",
"xmpp"
]
}
}
}
},
"openRegistrations": {
"description": "Whether this server allows open self-registration.",
"type": "boolean"
},
"usage": {
"description": "Usage statistics for this server.",
"type": "object",
"additionalProperties": false,
"required": ["users"],
"properties": {
"users": {
"description": "statistics about the users of this server.",
"type": "object",
"additionalProperties": false,
"properties": {
"total": {
"description": "The total amount of on this server registered users.",
"type": "integer",
"minimum": 0
},
"activeHalfyear": {
"description": "The amount of users that signed in at least once in the last 180 days.",
"type": "integer",
"minimum": 0
},
"activeMonth": {
"description": "The amount of users that signed in at least once in the last 30 days.",
"type": "integer",
"minimum": 0
}
}
},
"localPosts": {
"description": "The amount of posts that were made by users that are registered on this server.",
"type": "integer",
"minimum": 0
},
"localComments": {
"description": "The amount of comments that were made by users that are registered on this server.",
"type": "integer",
"minimum": 0
}
}
},
"metadata": {
"description": "Free form key value pairs for software specific values. Clients should not rely on any specific key present.",
"type": "object",
"minProperties": 0,
"additionalProperties": true
}
}
}