Merge commit 'a5b4a2b7e7
' into kb-draft-5.21-lts
This commit is contained in:
commit
6896542a76
33 changed files with 338 additions and 109 deletions
|
@ -43,6 +43,11 @@ describe Admin::StatusesController do
|
|||
|
||||
describe 'GET #show' do
|
||||
before do
|
||||
status.media_attachments << Fabricate(:media_attachment, type: :image, account: status.account)
|
||||
status.save!
|
||||
status.snapshot!(at_time: status.created_at, rate_limit: false)
|
||||
status.update!(text: 'Hello, this is an edited post')
|
||||
status.snapshot!(rate_limit: false)
|
||||
get :show, params: { account_id: account.id, id: status.id }
|
||||
end
|
||||
|
||||
|
|
|
@ -13,6 +13,17 @@ describe Api::V1::ScheduledStatusesController do
|
|||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
context 'with an application token' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: 'read:statuses') }
|
||||
|
||||
it 'returns http unprocessable entity' do
|
||||
get :index
|
||||
|
||||
expect(response)
|
||||
.to have_http_status(422)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index
|
||||
|
|
|
@ -9,6 +9,26 @@ describe Api::V1::Statuses::TranslationsController do
|
|||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses', application: app) }
|
||||
|
||||
context 'with an application token' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: 'read:statuses', application: app) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/statuses/:status_id/translate' do
|
||||
let(:status) { Fabricate(:status, account: user.account, text: 'Hola', language: 'es') }
|
||||
|
||||
before do
|
||||
post :create, params: { status_id: status.id }
|
||||
end
|
||||
|
||||
it 'returns http unprocessable entity' do
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
|
|
|
@ -182,6 +182,46 @@ RSpec.describe Api::V1::StatusesController do
|
|||
expect(response.headers['X-RateLimit-Remaining']).to eq '0'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with missing thread' do
|
||||
subject { post :create, params: params }
|
||||
|
||||
let(:params) { { status: 'Hello world', in_reply_to_id: 0 } }
|
||||
|
||||
it 'returns http not found' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when scheduling a status' do
|
||||
subject { post :create, params: params }
|
||||
|
||||
let(:params) { { status: 'Hello world', scheduled_at: 10.minutes.from_now } }
|
||||
let(:account) { user.account }
|
||||
|
||||
it 'returns HTTP 200' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'creates a scheduled status' do
|
||||
expect { subject }.to change { account.scheduled_statuses.count }.from(0).to(1)
|
||||
end
|
||||
|
||||
context 'when the scheduling time is less than 5 minutes' do
|
||||
let(:params) { { status: 'Hello world', scheduled_at: 4.minutes.from_now } }
|
||||
|
||||
it 'does not create a scheduled status', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
expect(account.scheduled_statuses).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
|
|
|
@ -6,7 +6,8 @@ describe Api::V1::Timelines::TagController do
|
|||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }
|
||||
let(:scopes) { 'read:statuses' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
|
@ -48,13 +49,23 @@ describe Api::V1::Timelines::TagController do
|
|||
Form::AdminSettings.new(timeline_preview: false).save
|
||||
end
|
||||
|
||||
context 'when the user is not authenticated' do
|
||||
context 'without an access token' do
|
||||
let(:token) { nil }
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
it 'returns http unprocessable entity' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(401)
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an application access token, not bound to a user' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: scopes) }
|
||||
|
||||
it 'returns http unprocessable entity' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -50,9 +50,11 @@ describe Oauth::AuthorizedApplicationsController do
|
|||
let!(:application) { Fabricate(:application) }
|
||||
let!(:access_token) { Fabricate(:accessible_access_token, application: application, resource_owner_id: user.id) }
|
||||
let!(:web_push_subscription) { Fabricate(:web_push_subscription, user: user, access_token: access_token) }
|
||||
let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) }
|
||||
|
||||
before do
|
||||
sign_in user, scope: :user
|
||||
allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub)
|
||||
post :destroy, params: { id: application.id }
|
||||
end
|
||||
|
||||
|
@ -63,5 +65,13 @@ describe Oauth::AuthorizedApplicationsController do
|
|||
it 'removes subscriptions for the application\'s access tokens' do
|
||||
expect(Web::PushSubscription.where(user: user).count).to eq 0
|
||||
end
|
||||
|
||||
it 'removes the web_push_subscription' do
|
||||
expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
|
||||
it 'sends a session kill payload to the streaming server' do
|
||||
expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -166,7 +166,11 @@ describe Settings::ApplicationsController do
|
|||
end
|
||||
|
||||
describe 'destroy' do
|
||||
let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) }
|
||||
let!(:access_token) { Fabricate(:accessible_access_token, application: app) }
|
||||
|
||||
before do
|
||||
allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub)
|
||||
post :destroy, params: { id: app.id }
|
||||
end
|
||||
|
||||
|
@ -177,6 +181,10 @@ describe Settings::ApplicationsController do
|
|||
it 'removes the app' do
|
||||
expect(Doorkeeper::Application.find_by(id: app.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'sends a session kill payload to the streaming server' do
|
||||
expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'regenerate' do
|
||||
|
|
17
spec/fixtures/requests/low_confidence_latin1.txt
vendored
Normal file
17
spec/fixtures/requests/low_confidence_latin1.txt
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
HTTP/1.1 200 OK
|
||||
server: nginx
|
||||
date: Thu, 13 Jun 2024 14:33:13 GMT
|
||||
content-type: text/html; charset=ISO-8859-1
|
||||
content-length: 158
|
||||
accept-ranges: bytes
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Tofu á l'orange</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Tofu á l'orange</h2>
|
||||
</body>
|
||||
</html>
|
|
@ -32,6 +32,8 @@ describe 'Public' do
|
|||
context 'when the instance allows public preview' do
|
||||
let(:expected_statuses) { [local_status, remote_status, media_status] }
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'profile'
|
||||
|
||||
context 'with an authorized user' do
|
||||
it_behaves_like 'a successful request to the public timeline'
|
||||
end
|
||||
|
@ -96,13 +98,9 @@ describe 'Public' do
|
|||
Form::AdminSettings.new(timeline_preview: false).save
|
||||
end
|
||||
|
||||
context 'with an authenticated user' do
|
||||
let(:expected_statuses) { [local_status, remote_status, media_status] }
|
||||
it_behaves_like 'forbidden for wrong scope', 'profile'
|
||||
|
||||
it_behaves_like 'a successful request to the public timeline'
|
||||
end
|
||||
|
||||
context 'with an unauthenticated user' do
|
||||
context 'without an authentication token' do
|
||||
let(:headers) { {} }
|
||||
|
||||
it 'returns http unprocessable entity' do
|
||||
|
@ -111,6 +109,22 @@ describe 'Public' do
|
|||
expect(response).to have_http_status(422)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an application access token, not bound to a user' do
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: scopes) }
|
||||
|
||||
it 'returns http unprocessable entity' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an authenticated user' do
|
||||
let(:expected_statuses) { [local_status, remote_status, media_status] }
|
||||
|
||||
it_behaves_like 'a successful request to the public timeline'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,9 +56,11 @@ RSpec.describe BackupService, type: :service do
|
|||
end
|
||||
|
||||
def expect_outbox_export
|
||||
json = export_json(:outbox)
|
||||
body = export_json_raw(:outbox)
|
||||
json = Oj.load(body)
|
||||
|
||||
aggregate_failures do
|
||||
expect(body.scan('@context').count).to eq 1
|
||||
expect(json['@context']).to_not be_nil
|
||||
expect(json['type']).to eq 'OrderedCollection'
|
||||
expect(json['totalItems']).to eq 3
|
||||
|
@ -87,8 +89,12 @@ RSpec.describe BackupService, type: :service do
|
|||
end
|
||||
end
|
||||
|
||||
def export_json_raw(type)
|
||||
read_zip_file(backup, "#{type}.json")
|
||||
end
|
||||
|
||||
def export_json(type)
|
||||
Oj.load(read_zip_file(backup, "#{type}.json"))
|
||||
Oj.load(export_json_raw(type))
|
||||
end
|
||||
|
||||
def include_create_item(status)
|
||||
|
|
|
@ -27,6 +27,7 @@ RSpec.describe FetchLinkCardService, type: :service do
|
|||
stub_request(:get, 'http://example.com/sjis_with_wrong_charset').to_return(request_fixture('sjis_with_wrong_charset.txt'))
|
||||
stub_request(:get, 'http://example.com/koi8-r').to_return(request_fixture('koi8-r.txt'))
|
||||
stub_request(:get, 'http://example.com/windows-1251').to_return(request_fixture('windows-1251.txt'))
|
||||
stub_request(:get, 'http://example.com/low_confidence_latin1').to_return(request_fixture('low_confidence_latin1.txt'))
|
||||
|
||||
Rails.cache.write('oembed_endpoint:example.com', oembed_cache) if oembed_cache
|
||||
|
||||
|
@ -149,6 +150,14 @@ RSpec.describe FetchLinkCardService, type: :service do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with a URL of a page in ISO-8859-1 encoding, that charlock_holmes cannot detect' do
|
||||
let(:status) { Fabricate(:status, text: 'Check out http://example.com/low_confidence_latin1') }
|
||||
|
||||
it 'decodes the HTML' do
|
||||
expect(status.preview_card.title).to eq("Tofu á l'orange")
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a Japanese path URL' do
|
||||
let(:status) { Fabricate(:status, text: 'テストhttp://example.com/日本語') }
|
||||
|
||||
|
@ -185,6 +194,19 @@ RSpec.describe FetchLinkCardService, type: :service do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with an URL too long for PostgreSQL unique indexes' do
|
||||
let(:url) { "http://example.com/#{'a' * 2674}" }
|
||||
let(:status) { Fabricate(:status, text: url) }
|
||||
|
||||
it 'does not fetch the URL' do
|
||||
expect(a_request(:get, url)).to_not have_been_made
|
||||
end
|
||||
|
||||
it 'does not create a preview card' do
|
||||
expect(status.preview_card).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a URL of a page with oEmbed support' do
|
||||
let(:html) { '<!doctype html><title>Hello world</title><link rel="alternate" type="application/json+oembed" href="http://example.com/oembed?url=http://example.com/html">' }
|
||||
let(:status) { Fabricate(:status, text: 'http://example.com/html') }
|
||||
|
|
|
@ -61,6 +61,16 @@ RSpec.describe PostStatusService, type: :service do
|
|||
status2 = subject.call(account, text: 'test', idempotency: 'meepmeep', scheduled_at: future)
|
||||
expect(status2.id).to eq status1.id
|
||||
end
|
||||
|
||||
context 'when scheduled_at is less than min offset' do
|
||||
let(:invalid_scheduled_time) { 4.minutes.from_now }
|
||||
|
||||
it 'raises invalid record error' do
|
||||
expect do
|
||||
subject.call(account, text: 'Hi future!', scheduled_at: invalid_scheduled_time)
|
||||
end.to raise_error(ActiveRecord::RecordInvalid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'creates response to the original status of boost' do
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue