Change public accounts pages to mount the web UI (#19319)
* Change public accounts pages to mount the web UI * Fix handling of remote usernames in routes - When logged in, serve web app - When logged out, redirect to permalink - Fix `app-body` class not being set sometimes due to name conflict * Fix missing `multiColumn` prop * Fix failing test * Use `discoverable` attribute to control indexing directives * Fix `<ColumnLoading />` not using `multiColumn` * Add `noindex` to accounts in REST API * Change noindex directive to not be rendered by default before a route is mounted * Add loading indicator for detailed status in web UI * Fix missing indicator appearing while account is loading in web UI
This commit is contained in:
@ -1,64 +0,0 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe AccountFollowController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:alice) { Fabricate(:account, username: 'alice') }
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:service) { double }
|
||||
|
||||
subject { post :create, params: { account_username: alice.username } }
|
||||
|
||||
before do
|
||||
allow(FollowService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call)
|
||||
end
|
||||
|
||||
context 'when account is permanently suspended' do
|
||||
before do
|
||||
alice.suspend!
|
||||
alice.deletion_request.destroy
|
||||
subject
|
||||
end
|
||||
|
||||
it 'returns http gone' do
|
||||
expect(response).to have_http_status(410)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when account is temporarily suspended' do
|
||||
before do
|
||||
alice.suspend!
|
||||
subject
|
||||
end
|
||||
|
||||
it 'returns http forbidden' do
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when signed out' do
|
||||
before do
|
||||
subject
|
||||
end
|
||||
|
||||
it 'does not follow' do
|
||||
expect(FollowService).not_to receive(:new)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when signed in' do
|
||||
before do
|
||||
sign_in(user)
|
||||
subject
|
||||
end
|
||||
|
||||
it 'redirects to account path' do
|
||||
expect(service).to have_received(:call).with(user.account, alice, with_rate_limit: true)
|
||||
expect(response).to redirect_to(account_path(alice))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,64 +0,0 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe AccountUnfollowController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:alice) { Fabricate(:account, username: 'alice') }
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:service) { double }
|
||||
|
||||
subject { post :create, params: { account_username: alice.username } }
|
||||
|
||||
before do
|
||||
allow(UnfollowService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call)
|
||||
end
|
||||
|
||||
context 'when account is permanently suspended' do
|
||||
before do
|
||||
alice.suspend!
|
||||
alice.deletion_request.destroy
|
||||
subject
|
||||
end
|
||||
|
||||
it 'returns http gone' do
|
||||
expect(response).to have_http_status(410)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when account is temporarily suspended' do
|
||||
before do
|
||||
alice.suspend!
|
||||
subject
|
||||
end
|
||||
|
||||
it 'returns http forbidden' do
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when signed out' do
|
||||
before do
|
||||
subject
|
||||
end
|
||||
|
||||
it 'does not unfollow' do
|
||||
expect(UnfollowService).not_to receive(:new)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when signed in' do
|
||||
before do
|
||||
sign_in(user)
|
||||
subject
|
||||
end
|
||||
|
||||
it 'redirects to account path' do
|
||||
expect(service).to have_received(:call).with(user.account, alice)
|
||||
expect(response).to redirect_to(account_path(alice))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -99,100 +99,6 @@ RSpec.describe AccountsController, type: :controller do
|
||||
end
|
||||
|
||||
it_behaves_like 'common response characteristics'
|
||||
|
||||
it 'renders public status' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status))
|
||||
end
|
||||
|
||||
it 'renders self-reply' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_self_reply))
|
||||
end
|
||||
|
||||
it 'renders status with media' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_media))
|
||||
end
|
||||
|
||||
it 'renders reblog' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
|
||||
end
|
||||
|
||||
it 'renders pinned status' do
|
||||
expect(response.body).to include(I18n.t('stream_entries.pinned'))
|
||||
end
|
||||
|
||||
it 'does not render private status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
|
||||
end
|
||||
|
||||
it 'does not render direct status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
|
||||
end
|
||||
|
||||
it 'does not render reply to someone else' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when signed-in' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
context 'when user follows account' do
|
||||
before do
|
||||
user.account.follow!(account)
|
||||
get :show, params: { username: account.username, format: format }
|
||||
end
|
||||
|
||||
it 'does not render private status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is blocked' do
|
||||
before do
|
||||
account.block!(user.account)
|
||||
get :show, params: { username: account.username, format: format }
|
||||
end
|
||||
|
||||
it 'renders unavailable message' do
|
||||
expect(response.body).to include(I18n.t('accounts.unavailable'))
|
||||
end
|
||||
|
||||
it 'does not render public status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status))
|
||||
end
|
||||
|
||||
it 'does not render self-reply' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_self_reply))
|
||||
end
|
||||
|
||||
it 'does not render status with media' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_media))
|
||||
end
|
||||
|
||||
it 'does not render reblog' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
|
||||
end
|
||||
|
||||
it 'does not render pinned status' do
|
||||
expect(response.body).to_not include(I18n.t('stream_entries.pinned'))
|
||||
end
|
||||
|
||||
it 'does not render private status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
|
||||
end
|
||||
|
||||
it 'does not render direct status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
|
||||
end
|
||||
|
||||
it 'does not render reply to someone else' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with replies' do
|
||||
@ -202,38 +108,6 @@ RSpec.describe AccountsController, type: :controller do
|
||||
end
|
||||
|
||||
it_behaves_like 'common response characteristics'
|
||||
|
||||
it 'renders public status' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status))
|
||||
end
|
||||
|
||||
it 'renders self-reply' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_self_reply))
|
||||
end
|
||||
|
||||
it 'renders status with media' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_media))
|
||||
end
|
||||
|
||||
it 'renders reblog' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
|
||||
end
|
||||
|
||||
it 'does not render pinned status' do
|
||||
expect(response.body).to_not include(I18n.t('stream_entries.pinned'))
|
||||
end
|
||||
|
||||
it 'does not render private status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
|
||||
end
|
||||
|
||||
it 'does not render direct status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
|
||||
end
|
||||
|
||||
it 'renders reply to someone else' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_reply))
|
||||
end
|
||||
end
|
||||
|
||||
context 'with media' do
|
||||
@ -243,38 +117,6 @@ RSpec.describe AccountsController, type: :controller do
|
||||
end
|
||||
|
||||
it_behaves_like 'common response characteristics'
|
||||
|
||||
it 'does not render public status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status))
|
||||
end
|
||||
|
||||
it 'does not render self-reply' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_self_reply))
|
||||
end
|
||||
|
||||
it 'renders status with media' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_media))
|
||||
end
|
||||
|
||||
it 'does not render reblog' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
|
||||
end
|
||||
|
||||
it 'does not render pinned status' do
|
||||
expect(response.body).to_not include(I18n.t('stream_entries.pinned'))
|
||||
end
|
||||
|
||||
it 'does not render private status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
|
||||
end
|
||||
|
||||
it 'does not render direct status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
|
||||
end
|
||||
|
||||
it 'does not render reply to someone else' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
|
||||
end
|
||||
end
|
||||
|
||||
context 'with tag' do
|
||||
@ -289,42 +131,6 @@ RSpec.describe AccountsController, type: :controller do
|
||||
end
|
||||
|
||||
it_behaves_like 'common response characteristics'
|
||||
|
||||
it 'does not render public status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status))
|
||||
end
|
||||
|
||||
it 'does not render self-reply' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_self_reply))
|
||||
end
|
||||
|
||||
it 'does not render status with media' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_media))
|
||||
end
|
||||
|
||||
it 'does not render reblog' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
|
||||
end
|
||||
|
||||
it 'does not render pinned status' do
|
||||
expect(response.body).to_not include(I18n.t('stream_entries.pinned'))
|
||||
end
|
||||
|
||||
it 'does not render private status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
|
||||
end
|
||||
|
||||
it 'does not render direct status' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
|
||||
end
|
||||
|
||||
it 'does not render reply to someone else' do
|
||||
expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
|
||||
end
|
||||
|
||||
it 'renders status with tag' do
|
||||
expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_tag))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -39,7 +39,7 @@ describe AuthorizeInteractionsController do
|
||||
end
|
||||
|
||||
it 'sets resource from url' do
|
||||
account = Account.new
|
||||
account = Fabricate(:account)
|
||||
service = double
|
||||
allow(ResolveURLService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call).with('http://example.com').and_return(account)
|
||||
@ -51,7 +51,7 @@ describe AuthorizeInteractionsController do
|
||||
end
|
||||
|
||||
it 'sets resource from acct uri' do
|
||||
account = Account.new
|
||||
account = Fabricate(:account)
|
||||
service = double
|
||||
allow(ResolveAccountService).to receive(:new).and_return(service)
|
||||
allow(service).to receive(:call).with('found@hostname').and_return(account)
|
||||
|
@ -34,27 +34,6 @@ describe FollowerAccountsController do
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
|
||||
it 'assigns follows' do
|
||||
expect(response).to have_http_status(200)
|
||||
|
||||
assigned = assigns(:follows).to_a
|
||||
expect(assigned.size).to eq 2
|
||||
expect(assigned[0]).to eq follow1
|
||||
expect(assigned[1]).to eq follow0
|
||||
end
|
||||
|
||||
it 'does not assign blocked users' do
|
||||
user = Fabricate(:user)
|
||||
user.account.block!(follower0)
|
||||
sign_in(user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
|
||||
assigned = assigns(:follows).to_a
|
||||
expect(assigned.size).to eq 1
|
||||
expect(assigned[0]).to eq follow1
|
||||
end
|
||||
end
|
||||
|
||||
context 'when format is json' do
|
||||
|
@ -34,27 +34,6 @@ describe FollowingAccountsController do
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
|
||||
it 'assigns follows' do
|
||||
expect(response).to have_http_status(200)
|
||||
|
||||
assigned = assigns(:follows).to_a
|
||||
expect(assigned.size).to eq 2
|
||||
expect(assigned[0]).to eq follow1
|
||||
expect(assigned[1]).to eq follow0
|
||||
end
|
||||
|
||||
it 'does not assign blocked users' do
|
||||
user = Fabricate(:user)
|
||||
user.account.block!(followee0)
|
||||
sign_in(user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
|
||||
assigned = assigns(:follows).to_a
|
||||
expect(assigned.size).to eq 1
|
||||
expect(assigned[0]).to eq follow1
|
||||
end
|
||||
end
|
||||
|
||||
context 'when format is json' do
|
||||
|
@ -1,135 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe RemoteFollowController do
|
||||
render_views
|
||||
|
||||
describe '#new' do
|
||||
it 'returns success when session is empty' do
|
||||
account = Fabricate(:account)
|
||||
get :new, params: { account_username: account.to_param }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response).to render_template(:new)
|
||||
expect(assigns(:remote_follow).acct).to be_nil
|
||||
end
|
||||
|
||||
it 'populates the remote follow with session data when session exists' do
|
||||
session[:remote_follow] = 'user@example.com'
|
||||
account = Fabricate(:account)
|
||||
get :new, params: { account_username: account.to_param }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response).to render_template(:new)
|
||||
expect(assigns(:remote_follow).acct).to eq 'user@example.com'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
before do
|
||||
@account = Fabricate(:account, username: 'test_user')
|
||||
end
|
||||
|
||||
context 'with a valid acct' do
|
||||
context 'when webfinger values are wrong' do
|
||||
it 'renders new when redirect url is nil' do
|
||||
resource_with_nil_link = double(link: nil)
|
||||
allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_return(resource_with_nil_link)
|
||||
post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
|
||||
|
||||
expect(response).to render_template(:new)
|
||||
expect(response.body).to include(I18n.t('remote_follow.missing_resource'))
|
||||
end
|
||||
|
||||
it 'renders new when template is nil' do
|
||||
resource_with_link = double(link: nil)
|
||||
allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_return(resource_with_link)
|
||||
post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
|
||||
|
||||
expect(response).to render_template(:new)
|
||||
expect(response.body).to include(I18n.t('remote_follow.missing_resource'))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when webfinger values are good' do
|
||||
before do
|
||||
resource_with_link = double(link: 'http://example.com/follow_me?acct={uri}')
|
||||
allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_return(resource_with_link)
|
||||
post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
|
||||
end
|
||||
|
||||
it 'saves the session' do
|
||||
expect(session[:remote_follow]).to eq 'user@example.com'
|
||||
end
|
||||
|
||||
it 'redirects to the remote location' do
|
||||
expect(response).to redirect_to("http://example.com/follow_me?acct=https%3A%2F%2F#{Rails.configuration.x.local_domain}%2Fusers%2Ftest_user")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an invalid acct' do
|
||||
it 'renders new when acct is missing' do
|
||||
post :create, params: { account_username: @account.to_param, remote_follow: { acct: '' } }
|
||||
|
||||
expect(response).to render_template(:new)
|
||||
end
|
||||
|
||||
it 'renders new with error when webfinger fails' do
|
||||
allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_raise(Webfinger::Error)
|
||||
post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
|
||||
|
||||
expect(response).to render_template(:new)
|
||||
expect(response.body).to include(I18n.t('remote_follow.missing_resource'))
|
||||
end
|
||||
|
||||
it 'renders new when occur HTTP::ConnectionError' do
|
||||
allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@unknown').and_raise(HTTP::ConnectionError)
|
||||
post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@unknown' } }
|
||||
|
||||
expect(response).to render_template(:new)
|
||||
expect(response.body).to include(I18n.t('remote_follow.missing_resource'))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a permanently suspended account' do
|
||||
before do
|
||||
@account = Fabricate(:account)
|
||||
@account.suspend!
|
||||
@account.deletion_request.destroy
|
||||
end
|
||||
|
||||
it 'returns http gone on GET to #new' do
|
||||
get :new, params: { account_username: @account.to_param }
|
||||
|
||||
expect(response).to have_http_status(410)
|
||||
end
|
||||
|
||||
it 'returns http gone on POST to #create' do
|
||||
post :create, params: { account_username: @account.to_param }
|
||||
|
||||
expect(response).to have_http_status(410)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a temporarily suspended account' do
|
||||
before do
|
||||
@account = Fabricate(:account)
|
||||
@account.suspend!
|
||||
end
|
||||
|
||||
it 'returns http forbidden on GET to #new' do
|
||||
get :new, params: { account_username: @account.to_param }
|
||||
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
|
||||
it 'returns http forbidden on POST to #create' do
|
||||
post :create, params: { account_username: @account.to_param }
|
||||
|
||||
expect(response).to have_http_status(403)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,39 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe RemoteInteractionController, type: :controller do
|
||||
render_views
|
||||
|
||||
let(:status) { Fabricate(:status) }
|
||||
|
||||
describe 'GET #new' do
|
||||
it 'returns 200' do
|
||||
get :new, params: { id: status.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
context '@remote_follow is valid' do
|
||||
it 'returns 302' do
|
||||
allow_any_instance_of(RemoteFollow).to receive(:valid?) { true }
|
||||
allow_any_instance_of(RemoteFollow).to receive(:addressable_template) do
|
||||
Addressable::Template.new('https://hoge.com')
|
||||
end
|
||||
|
||||
post :create, params: { id: status.id, remote_follow: { acct: '@hoge' } }
|
||||
expect(response).to have_http_status(302)
|
||||
end
|
||||
end
|
||||
|
||||
context '@remote_follow is invalid' do
|
||||
it 'returns 200' do
|
||||
allow_any_instance_of(RemoteFollow).to receive(:valid?) { false }
|
||||
post :create, params: { id: status.id, remote_follow: { acct: '@hoge' } }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -10,16 +10,15 @@ RSpec.describe TagsController, type: :controller do
|
||||
let!(:late) { Fabricate(:status, tags: [tag], text: 'late #test') }
|
||||
|
||||
context 'when tag exists' do
|
||||
it 'redirects to web version' do
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: 'test', max_id: late.id }
|
||||
expect(response).to redirect_to('/web/tags/test')
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when tag does not exist' do
|
||||
it 'returns http missing for non-existent tag' do
|
||||
it 'returns http not found' do
|
||||
get :show, params: { id: 'none' }
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user