From 62a39d60cedc073b3190b9ba2f2f6f3173057eb2 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 19 Sep 2024 11:50:06 +0200 Subject: [PATCH 01/10] Fix rolling updates by moving DropEndToEndMessageTables to post-deployment migrations (#31963) --- .../20240720140205_drop_end_to_end_message_tables.rb | 0 .../20240916190140_remove_crypto_scope_values.rb | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename db/{migrate => post_migrate}/20240720140205_drop_end_to_end_message_tables.rb (100%) rename db/{migrate => post_migrate}/20240916190140_remove_crypto_scope_values.rb (100%) diff --git a/db/migrate/20240720140205_drop_end_to_end_message_tables.rb b/db/post_migrate/20240720140205_drop_end_to_end_message_tables.rb similarity index 100% rename from db/migrate/20240720140205_drop_end_to_end_message_tables.rb rename to db/post_migrate/20240720140205_drop_end_to_end_message_tables.rb diff --git a/db/migrate/20240916190140_remove_crypto_scope_values.rb b/db/post_migrate/20240916190140_remove_crypto_scope_values.rb similarity index 100% rename from db/migrate/20240916190140_remove_crypto_scope_values.rb rename to db/post_migrate/20240916190140_remove_crypto_scope_values.rb From 90db524a90ea5fee8b791b15501c7348f8a87c39 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:50:58 +0000 Subject: [PATCH 02/10] Update dependency puma to v6.4.3 (#31975) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5ed8fe78eb..b19c5bb578 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -609,7 +609,7 @@ GEM psych (5.1.2) stringio public_suffix (6.0.1) - puma (6.4.2) + puma (6.4.3) nio4r (~> 2.0) pundit (2.4.0) activesupport (>= 3.0.0) From 1fce55cf5dc63d944f45b938eb3df28742ca7d77 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:51:14 +0000 Subject: [PATCH 03/10] Update dependency aws-sdk-s3 to v1.163.0 (#31972) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b19c5bb578..41a8b68fae 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -100,8 +100,8 @@ GEM attr_required (1.0.2) awrence (1.2.1) aws-eventstream (1.3.0) - aws-partitions (1.974.0) - aws-sdk-core (3.205.0) + aws-partitions (1.977.0) + aws-sdk-core (3.206.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.9) @@ -109,11 +109,11 @@ GEM aws-sdk-kms (1.91.0) aws-sdk-core (~> 3, >= 3.205.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.162.0) + aws-sdk-s3 (1.163.0) aws-sdk-core (~> 3, >= 3.205.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.9.1) + aws-sigv4 (1.10.0) aws-eventstream (~> 1, >= 1.0.2) azure-storage-blob (2.0.3) azure-storage-common (~> 2.0) From b071e618e7c53a89ee332ae4c7afe9c5b4e9d176 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 19 Sep 2024 06:15:21 -0400 Subject: [PATCH 04/10] Combine API request spec assertions (#31970) --- spec/requests/api/v1/admin/accounts_spec.rb | 6 +-- spec/requests/api/v1/admin/tags_spec.rb | 12 +----- spec/requests/api/v1/apps/credentials_spec.rb | 12 +----- spec/requests/api/v1/blocks_spec.rb | 7 +--- spec/requests/api/v1/bookmarks_spec.rb | 7 +--- spec/requests/api/v1/favourites_spec.rb | 14 +------ spec/requests/api/v1/featured_tags_spec.rb | 19 +--------- spec/requests/api/v1/followed_tags_spec.rb | 7 +--- .../api/v1/instances/languages_spec.rb | 5 +-- spec/requests/api/v1/lists/accounts_spec.rb | 7 +--- spec/requests/api/v1/media_spec.rb | 7 +--- spec/requests/api/v1/mutes_spec.rb | 14 +------ .../api/v1/notifications/requests_spec.rb | 7 +--- spec/requests/api/v1/profiles_spec.rb | 38 +------------------ .../api/v1/statuses/bookmarks_spec.rb | 18 ++------- .../api/v1/statuses/favourites_spec.rb | 18 ++------- spec/requests/api/v1/statuses/pins_spec.rb | 12 +----- spec/requests/api/v1/suggestions_spec.rb | 14 +------ spec/requests/api/v1/timelines/home_spec.rb | 12 +----- spec/requests/api/v1/timelines/link_spec.rb | 6 +-- spec/requests/api/v2/filters_spec.rb | 26 ++----------- 21 files changed, 36 insertions(+), 232 deletions(-) diff --git a/spec/requests/api/v1/admin/accounts_spec.rb b/spec/requests/api/v1/admin/accounts_spec.rb index 2dc45d5eb2..f557b61403 100644 --- a/spec/requests/api/v1/admin/accounts_spec.rb +++ b/spec/requests/api/v1/admin/accounts_spec.rb @@ -193,15 +193,11 @@ RSpec.describe 'Accounts' do it_behaves_like 'forbidden for wrong scope', 'write write:accounts read admin:read' it_behaves_like 'forbidden for wrong role', '' - it 'removes the user successfully', :aggregate_failures do + it 'removes the user successfully and logs action', :aggregate_failures do subject expect(response).to have_http_status(200) expect(User.where(id: account.user.id)).to_not exist - end - - it 'logs action', :aggregate_failures do - subject expect(latest_admin_action_log) .to be_present diff --git a/spec/requests/api/v1/admin/tags_spec.rb b/spec/requests/api/v1/admin/tags_spec.rb index 2f730cdeb8..fda9227acf 100644 --- a/spec/requests/api/v1/admin/tags_spec.rb +++ b/spec/requests/api/v1/admin/tags_spec.rb @@ -73,14 +73,10 @@ RSpec.describe 'Tags' do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do + it 'returns http success and expected tag content' do subject expect(response).to have_http_status(200) - end - - it 'returns expected tag content' do - subject expect(response.parsed_body[:id].to_i).to eq(tag.id) expect(response.parsed_body[:name]).to eq(tag.name) @@ -107,14 +103,10 @@ RSpec.describe 'Tags' do it_behaves_like 'forbidden for wrong scope', 'admin:read' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do + it 'returns http success and updates tag' do subject expect(response).to have_http_status(200) - end - - it 'returns updated tag' do - subject expect(response.parsed_body[:id].to_i).to eq(tag.id) expect(response.parsed_body[:name]).to eq(tag.name.upcase) diff --git a/spec/requests/api/v1/apps/credentials_spec.rb b/spec/requests/api/v1/apps/credentials_spec.rb index 1cd6a4178f..6fd885eb86 100644 --- a/spec/requests/api/v1/apps/credentials_spec.rb +++ b/spec/requests/api/v1/apps/credentials_spec.rb @@ -47,14 +47,10 @@ RSpec.describe 'Credentials' do let(:token) { Fabricate(:accessible_access_token, application: application) } let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } - it 'returns http success' do + it 'returns http success and returns app information' do subject expect(response).to have_http_status(200) - end - - it 'returns the app information correctly' do - subject expect(response.parsed_body).to match( a_hash_including( @@ -108,14 +104,10 @@ RSpec.describe 'Credentials' do let(:token) { Fabricate(:accessible_access_token, application: application) } let(:headers) { { 'Authorization' => "Bearer #{token.token}-invalid" } } - it 'returns http authorization error' do + it 'returns http authorization error with json error' do subject expect(response).to have_http_status(401) - end - - it 'returns the error in the json response' do - subject expect(response.parsed_body).to match( a_hash_including( diff --git a/spec/requests/api/v1/blocks_spec.rb b/spec/requests/api/v1/blocks_spec.rb index d2f1c46a5b..fc028f9bac 100644 --- a/spec/requests/api/v1/blocks_spec.rb +++ b/spec/requests/api/v1/blocks_spec.rb @@ -32,15 +32,10 @@ RSpec.describe 'Blocks' do context 'with limit param' do let(:params) { { limit: 2 } } - it 'returns only the requested number of blocked accounts' do + it 'returns only the requested number of blocked accounts and sets link header pagination' do subject expect(response.parsed_body.size).to eq(params[:limit]) - end - - it 'sets correct link header pagination' do - subject - expect(response) .to include_pagination_headers( prev: api_v1_blocks_url(limit: params[:limit], since_id: blocks.last.id), diff --git a/spec/requests/api/v1/bookmarks_spec.rb b/spec/requests/api/v1/bookmarks_spec.rb index 95a71abcac..5955de6652 100644 --- a/spec/requests/api/v1/bookmarks_spec.rb +++ b/spec/requests/api/v1/bookmarks_spec.rb @@ -24,15 +24,10 @@ RSpec.describe 'Bookmarks' do it_behaves_like 'forbidden for wrong scope', 'write' - it 'returns http success' do + it 'returns http success and the bookmarked statuses' do subject expect(response).to have_http_status(200) - end - - it 'returns the bookmarked statuses' do - subject - expect(response.parsed_body).to match_array(expected_response) end diff --git a/spec/requests/api/v1/favourites_spec.rb b/spec/requests/api/v1/favourites_spec.rb index 78e9d61551..2f8bef1190 100644 --- a/spec/requests/api/v1/favourites_spec.rb +++ b/spec/requests/api/v1/favourites_spec.rb @@ -24,30 +24,20 @@ RSpec.describe 'Favourites' do it_behaves_like 'forbidden for wrong scope', 'write' - it 'returns http success' do + it 'returns http success and includes the favourites' do subject expect(response).to have_http_status(200) - end - - it 'returns the favourites' do - subject - expect(response.parsed_body).to match_array(expected_response) end context 'with limit param' do let(:params) { { limit: 1 } } - it 'returns only the requested number of favourites' do + it 'returns only the requested number of favourites and sets pagination headers' do subject expect(response.parsed_body.size).to eq(params[:limit]) - end - - it 'sets the correct pagination headers' do - subject - expect(response) .to include_pagination_headers( prev: api_v1_favourites_url(limit: params[:limit], min_id: favourites.last.id), diff --git a/spec/requests/api/v1/featured_tags_spec.rb b/spec/requests/api/v1/featured_tags_spec.rb index 423cc0c560..f0e939d42a 100644 --- a/spec/requests/api/v1/featured_tags_spec.rb +++ b/spec/requests/api/v1/featured_tags_spec.rb @@ -58,15 +58,10 @@ RSpec.describe 'FeaturedTags' do describe 'POST /api/v1/featured_tags' do let(:params) { { name: 'tag' } } - it 'returns http success' do + it 'returns http success and includes correct tag name' do post '/api/v1/featured_tags', headers: headers, params: params expect(response).to have_http_status(200) - end - - it 'returns the correct tag name' do - post '/api/v1/featured_tags', headers: headers, params: params - expect(response.parsed_body) .to include( name: params[:name] @@ -132,23 +127,13 @@ RSpec.describe 'FeaturedTags' do let!(:featured_tag) { FeaturedTag.create(name: 'tag', account: user.account) } let(:id) { featured_tag.id } - it 'returns http success' do + it 'returns http success with an empty body and deletes the featured tag', :inline_jobs do delete "/api/v1/featured_tags/#{id}", headers: headers expect(response).to have_http_status(200) - end - - it 'returns an empty body' do - delete "/api/v1/featured_tags/#{id}", headers: headers - expect(response.parsed_body).to be_empty - end - - it 'deletes the featured tag', :inline_jobs do - delete "/api/v1/featured_tags/#{id}", headers: headers featured_tag = FeaturedTag.find_by(id: id) - expect(featured_tag).to be_nil end diff --git a/spec/requests/api/v1/followed_tags_spec.rb b/spec/requests/api/v1/followed_tags_spec.rb index f7787cb763..f15c0d7f44 100644 --- a/spec/requests/api/v1/followed_tags_spec.rb +++ b/spec/requests/api/v1/followed_tags_spec.rb @@ -28,15 +28,10 @@ RSpec.describe 'Followed tags' do it_behaves_like 'forbidden for wrong scope', 'write write:follows' - it 'returns http success' do + it 'returns http success and includes followed tags' do subject expect(response).to have_http_status(:success) - end - - it 'returns the followed tags correctly' do - subject - expect(response.parsed_body).to match_array(expected_response) end diff --git a/spec/requests/api/v1/instances/languages_spec.rb b/spec/requests/api/v1/instances/languages_spec.rb index 79ea62c599..3ab1ba57b8 100644 --- a/spec/requests/api/v1/instances/languages_spec.rb +++ b/spec/requests/api/v1/instances/languages_spec.rb @@ -8,11 +8,8 @@ RSpec.describe 'Languages' do get '/api/v1/instance/languages' end - it 'returns http success' do + it 'returns http success and includes supported languages' do expect(response).to have_http_status(200) - end - - it 'returns the supported languages' do expect(response.parsed_body.pluck(:code)).to match_array LanguagesHelper::SUPPORTED_LOCALES.keys.map(&:to_s) end end diff --git a/spec/requests/api/v1/lists/accounts_spec.rb b/spec/requests/api/v1/lists/accounts_spec.rb index d147b21ee7..6e5f9e4e9d 100644 --- a/spec/requests/api/v1/lists/accounts_spec.rb +++ b/spec/requests/api/v1/lists/accounts_spec.rb @@ -139,16 +139,11 @@ RSpec.describe 'Accounts' do list.accounts << [bob, peter] end - it 'removes the specified account from the list', :aggregate_failures do + it 'removes the specified account from the list but keeps other accounts in the list', :aggregate_failures do subject expect(response).to have_http_status(200) expect(list.accounts).to_not include(bob) - end - - it 'does not remove any other account from the list' do - subject - expect(list.accounts).to include(peter) end diff --git a/spec/requests/api/v1/media_spec.rb b/spec/requests/api/v1/media_spec.rb index d0af334825..a10bbb31ef 100644 --- a/spec/requests/api/v1/media_spec.rb +++ b/spec/requests/api/v1/media_spec.rb @@ -17,15 +17,10 @@ RSpec.describe 'Media' do it_behaves_like 'forbidden for wrong scope', 'read' - it 'returns http success' do + it 'returns http success with media information' do subject expect(response).to have_http_status(200) - end - - it 'returns the media information' do - subject - expect(response.parsed_body).to match( a_hash_including( id: media.id.to_s, diff --git a/spec/requests/api/v1/mutes_spec.rb b/spec/requests/api/v1/mutes_spec.rb index 6402c908ff..316d455d28 100644 --- a/spec/requests/api/v1/mutes_spec.rb +++ b/spec/requests/api/v1/mutes_spec.rb @@ -18,32 +18,22 @@ RSpec.describe 'Mutes' do it_behaves_like 'forbidden for wrong scope', 'write write:mutes' - it 'returns http success' do + it 'returns http success with muted accounts' do subject expect(response).to have_http_status(200) - end - - it 'returns the muted accounts' do - subject muted_accounts = mutes.map(&:target_account) - expect(response.parsed_body.pluck(:id)).to match_array(muted_accounts.map { |account| account.id.to_s }) end context 'with limit param' do let(:params) { { limit: 1 } } - it 'returns only the requested number of muted accounts' do + it 'returns only the requested number of muted accounts with pagination headers' do subject expect(response.parsed_body.size).to eq(params[:limit]) - end - - it 'sets the correct pagination headers', :aggregate_failures do - subject - expect(response) .to include_pagination_headers( prev: api_v1_mutes_url(limit: params[:limit], since_id: mutes.last.id), diff --git a/spec/requests/api/v1/notifications/requests_spec.rb b/spec/requests/api/v1/notifications/requests_spec.rb index dc125bc7aa..030b7cfa21 100644 --- a/spec/requests/api/v1/notifications/requests_spec.rb +++ b/spec/requests/api/v1/notifications/requests_spec.rb @@ -39,15 +39,10 @@ RSpec.describe 'Requests' do it_behaves_like 'forbidden for wrong scope', 'read read:notifications' - it 'returns http success' do + it 'returns http success and creates notification permission' do subject expect(response).to have_http_status(200) - end - - it 'creates notification permission' do - subject - expect(NotificationPermission.find_by(account: notification_request.account, from_account: notification_request.from_account)).to_not be_nil end diff --git a/spec/requests/api/v1/profiles_spec.rb b/spec/requests/api/v1/profiles_spec.rb index 26a9b848e5..9616f41559 100644 --- a/spec/requests/api/v1/profiles_spec.rb +++ b/spec/requests/api/v1/profiles_spec.rb @@ -28,31 +28,14 @@ RSpec.describe 'Deleting profile images' do it_behaves_like 'forbidden for wrong scope', 'read' end - it 'returns http success' do + it 'returns http success and deletes the avatar, preserves the header, queues up distribution' do delete '/api/v1/profile/avatar', headers: headers expect(response).to have_http_status(200) - end - - it 'deletes the avatar' do - delete '/api/v1/profile/avatar', headers: headers account.reload - expect(account.avatar).to_not exist - end - - it 'does not delete the header' do - delete '/api/v1/profile/avatar', headers: headers - - account.reload - expect(account.header).to exist - end - - it 'queues up an account update distribution' do - delete '/api/v1/profile/avatar', headers: headers - expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id) end end @@ -66,31 +49,14 @@ RSpec.describe 'Deleting profile images' do it_behaves_like 'forbidden for wrong scope', 'read' end - it 'returns http success' do + it 'returns http success, preserves the avatar, deletes the header, queues up distribution' do delete '/api/v1/profile/header', headers: headers expect(response).to have_http_status(200) - end - - it 'does not delete the avatar' do - delete '/api/v1/profile/header', headers: headers account.reload - expect(account.avatar).to exist - end - - it 'deletes the header' do - delete '/api/v1/profile/header', headers: headers - - account.reload - expect(account.header).to_not exist - end - - it 'queues up an account update distribution' do - delete '/api/v1/profile/header', headers: headers - expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id) end end diff --git a/spec/requests/api/v1/statuses/bookmarks_spec.rb b/spec/requests/api/v1/statuses/bookmarks_spec.rb index f1bcfda0ff..6401a4370d 100644 --- a/spec/requests/api/v1/statuses/bookmarks_spec.rb +++ b/spec/requests/api/v1/statuses/bookmarks_spec.rb @@ -18,15 +18,11 @@ RSpec.describe 'Bookmarks' do it_behaves_like 'forbidden for wrong scope', 'read' context 'with public status' do - it 'bookmarks the status successfully', :aggregate_failures do + it 'bookmarks the status successfully and includes updated json', :aggregate_failures do subject expect(response).to have_http_status(200) expect(user.account.bookmarked?(status)).to be true - end - - it 'returns json with updated attributes' do - subject expect(response.parsed_body).to match( a_hash_including(id: status.id.to_s, bookmarked: true) @@ -93,15 +89,11 @@ RSpec.describe 'Bookmarks' do Bookmark.find_or_create_by!(account: user.account, status: status) end - it 'unbookmarks the status successfully', :aggregate_failures do + it 'unbookmarks the status successfully and includes updated json', :aggregate_failures do subject expect(response).to have_http_status(200) expect(user.account.bookmarked?(status)).to be false - end - - it 'returns json with updated attributes' do - subject expect(response.parsed_body).to match( a_hash_including(id: status.id.to_s, bookmarked: false) @@ -117,15 +109,11 @@ RSpec.describe 'Bookmarks' do status.account.block!(user.account) end - it 'unbookmarks the status successfully', :aggregate_failures do + it 'unbookmarks the status successfully and includes updated json', :aggregate_failures do subject expect(response).to have_http_status(200) expect(user.account.bookmarked?(status)).to be false - end - - it 'returns json with updated attributes' do - subject expect(response.parsed_body).to match( a_hash_including(id: status.id.to_s, bookmarked: false) diff --git a/spec/requests/api/v1/statuses/favourites_spec.rb b/spec/requests/api/v1/statuses/favourites_spec.rb index f9f0ff6299..c3acf0413e 100644 --- a/spec/requests/api/v1/statuses/favourites_spec.rb +++ b/spec/requests/api/v1/statuses/favourites_spec.rb @@ -18,15 +18,11 @@ RSpec.describe 'Favourites', :inline_jobs do it_behaves_like 'forbidden for wrong scope', 'read read:favourites' context 'with public status' do - it 'favourites the status successfully', :aggregate_failures do + it 'favourites the status successfully and includes updated json', :aggregate_failures do subject expect(response).to have_http_status(200) expect(user.account.favourited?(status)).to be true - end - - it 'returns json with updated attributes' do - subject expect(response.parsed_body).to match( a_hash_including(id: status.id.to_s, favourites_count: 1, favourited: true) @@ -84,16 +80,12 @@ RSpec.describe 'Favourites', :inline_jobs do FavouriteService.new.call(user.account, status) end - it 'unfavourites the status successfully', :aggregate_failures do + it 'unfavourites the status successfully and includes updated json', :aggregate_failures do subject expect(response).to have_http_status(200) expect(user.account.favourited?(status)).to be false - end - - it 'returns json with updated attributes' do - subject expect(response.parsed_body).to match( a_hash_including(id: status.id.to_s, favourites_count: 0, favourited: false) @@ -107,16 +99,12 @@ RSpec.describe 'Favourites', :inline_jobs do status.account.block!(user.account) end - it 'unfavourites the status successfully', :aggregate_failures do + it 'unfavourites the status successfully and includes updated json', :aggregate_failures do subject expect(response).to have_http_status(200) expect(user.account.favourited?(status)).to be false - end - - it 'returns json with updated attributes' do - subject expect(response.parsed_body).to match( a_hash_including(id: status.id.to_s, favourites_count: 0, favourited: false) diff --git a/spec/requests/api/v1/statuses/pins_spec.rb b/spec/requests/api/v1/statuses/pins_spec.rb index 56e60c6d36..409c50e7c2 100644 --- a/spec/requests/api/v1/statuses/pins_spec.rb +++ b/spec/requests/api/v1/statuses/pins_spec.rb @@ -18,15 +18,11 @@ RSpec.describe 'Pins' do it_behaves_like 'forbidden for wrong scope', 'read read:accounts' context 'when the status is public' do - it 'pins the status successfully', :aggregate_failures do + it 'pins the status successfully and returns updated json', :aggregate_failures do subject expect(response).to have_http_status(200) expect(user.account.pinned?(status)).to be true - end - - it 'return json with updated attributes' do - subject expect(response.parsed_body).to match( a_hash_including(id: status.id.to_s, pinned: true) @@ -86,15 +82,11 @@ RSpec.describe 'Pins' do Fabricate(:status_pin, status: status, account: user.account) end - it 'unpins the status successfully', :aggregate_failures do + it 'unpins the status successfully and includes updated json', :aggregate_failures do subject expect(response).to have_http_status(200) expect(user.account.pinned?(status)).to be false - end - - it 'return json with updated attributes' do - subject expect(response.parsed_body).to match( a_hash_including(id: status.id.to_s, pinned: false) diff --git a/spec/requests/api/v1/suggestions_spec.rb b/spec/requests/api/v1/suggestions_spec.rb index 8267bb92a0..b971f88129 100644 --- a/spec/requests/api/v1/suggestions_spec.rb +++ b/spec/requests/api/v1/suggestions_spec.rb @@ -23,15 +23,10 @@ RSpec.describe 'Suggestions' do it_behaves_like 'forbidden for wrong scope', 'write' - it 'returns http success' do + it 'returns http success with accounts' do subject expect(response).to have_http_status(200) - end - - it 'returns accounts' do - subject - expect(response.parsed_body) .to contain_exactly(include(id: bob.id.to_s), include(id: jeff.id.to_s)) end @@ -72,15 +67,10 @@ RSpec.describe 'Suggestions' do it_behaves_like 'forbidden for wrong scope', 'read' - it 'returns http success' do + it 'returns http success and removes suggestion' do subject expect(response).to have_http_status(200) - end - - it 'removes the specified suggestion' do - subject - expect(FollowRecommendationMute.exists?(account: user.account, target_account: jeff)).to be true end diff --git a/spec/requests/api/v1/timelines/home_spec.rb b/spec/requests/api/v1/timelines/home_spec.rb index afad2988ca..19a6f3adbc 100644 --- a/spec/requests/api/v1/timelines/home_spec.rb +++ b/spec/requests/api/v1/timelines/home_spec.rb @@ -31,14 +31,10 @@ RSpec.describe 'Home', :inline_jobs do PostStatusService.new.call(ana, text: 'New toot from ana.') end - it 'returns http success' do + it 'returns http success and statuses of followed users' do subject expect(response).to have_http_status(200) - end - - it 'returns the statuses of followed users' do - subject expect(response.parsed_body.pluck(:id)).to match_array(home_statuses.map { |status| status.id.to_s }) end @@ -46,14 +42,10 @@ RSpec.describe 'Home', :inline_jobs do context 'with limit param' do let(:params) { { limit: 1 } } - it 'returns only the requested number of statuses' do + it 'returns only the requested number of statuses with pagination headers', :aggregate_failures do subject expect(response.parsed_body.size).to eq(params[:limit]) - end - - it 'sets the correct pagination headers', :aggregate_failures do - subject expect(response) .to include_pagination_headers( diff --git a/spec/requests/api/v1/timelines/link_spec.rb b/spec/requests/api/v1/timelines/link_spec.rb index 8999364703..e1d421fb7a 100644 --- a/spec/requests/api/v1/timelines/link_spec.rb +++ b/spec/requests/api/v1/timelines/link_spec.rb @@ -123,15 +123,11 @@ RSpec.describe 'Link' do context 'with limit param' do let(:params) { { limit: 1, url: url } } - it 'returns only the requested number of statuses', :aggregate_failures do + it 'returns only the requested number of statuses with pagination headers', :aggregate_failures do subject expect(response).to have_http_status(200) expect(response.parsed_body.size).to eq(params[:limit]) - end - - it 'sets the correct pagination headers', :aggregate_failures do - subject expect(response) .to include_pagination_headers( diff --git a/spec/requests/api/v2/filters_spec.rb b/spec/requests/api/v2/filters_spec.rb index 850c773df3..ad8b55973e 100644 --- a/spec/requests/api/v2/filters_spec.rb +++ b/spec/requests/api/v2/filters_spec.rb @@ -49,14 +49,10 @@ RSpec.describe 'Filters' do context 'with valid params' do let(:params) { { title: 'magic', context: %w(home), filter_action: 'hide', keywords_attributes: [keyword: 'magic'] } } - it 'returns http success' do + it 'returns http success with a filter with keywords in json and creates a filter', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns a filter with keywords', :aggregate_failures do - subject expect(response.parsed_body) .to include( @@ -67,10 +63,6 @@ RSpec.describe 'Filters' do include(keyword: 'magic', whole_word: true) ) ) - end - - it 'creates a filter', :aggregate_failures do - subject filter = user.account.custom_filters.first @@ -189,20 +181,12 @@ RSpec.describe 'Filters' do allow(redis).to receive_messages(publish: nil) end - it 'returns http success' do + it 'returns http success and updates keyword and sends a filters_changed event' do subject expect(response).to have_http_status(200) - end - - it 'updates the keyword' do - subject expect(keyword.reload.keyword).to eq 'updated' - end - - it 'sends exactly one filters_changed event' do - subject expect(redis).to have_received(:publish).with("timeline:#{user.account.id}", Oj.dump(event: :filters_changed)).once end @@ -229,14 +213,10 @@ RSpec.describe 'Filters' do it_behaves_like 'forbidden for wrong scope', 'read read:filters' it_behaves_like 'unauthorized for invalid token' - it 'returns http success' do + it 'returns http success and removes the filter' do subject expect(response).to have_http_status(200) - end - - it 'removes the filter' do - subject expect { filter.reload }.to raise_error ActiveRecord::RecordNotFound end From 5d573c976e8f02e67014154232d2c7f936d8f717 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 19 Sep 2024 06:23:58 -0400 Subject: [PATCH 05/10] Remove unused E2EE-related methods (#31964) --- app/javascript/mastodon/stream.js | 1 - app/presenters/activitypub/activity_presenter.rb | 11 ----------- 2 files changed, 12 deletions(-) diff --git a/app/javascript/mastodon/stream.js b/app/javascript/mastodon/stream.js index 40d69136a8..59b2fd7582 100644 --- a/app/javascript/mastodon/stream.js +++ b/app/javascript/mastodon/stream.js @@ -209,7 +209,6 @@ const KNOWN_EVENT_TYPES = [ 'notification', 'conversation', 'filters_changed', - 'encrypted_message', 'announcement', 'announcement.delete', 'announcement.reaction', diff --git a/app/presenters/activitypub/activity_presenter.rb b/app/presenters/activitypub/activity_presenter.rb index 38e8527e8e..994cbeaf48 100644 --- a/app/presenters/activitypub/activity_presenter.rb +++ b/app/presenters/activitypub/activity_presenter.rb @@ -26,16 +26,5 @@ class ActivityPub::ActivityPresenter < ActiveModelSerializers::Model end end end - - def from_encrypted_message(encrypted_message) - new.tap do |presenter| - presenter.id = ActivityPub::TagManager.instance.generate_uri_for(nil) - presenter.type = 'Create' - presenter.actor = ActivityPub::TagManager.instance.uri_for(encrypted_message.source_account) - presenter.published = Time.now.utc - presenter.to = ActivityPub::TagManager.instance.uri_for(encrypted_message.target_account) - presenter.virtual_object = encrypted_message - end - end end end From efdc17513d4f929259f5d92b9ba2718e280295e3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:34:19 +0000 Subject: [PATCH 06/10] New Crowdin Translations (automated) (#31974) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ko.json | 3 +++ app/javascript/mastodon/locales/lv.json | 1 + config/locales/activerecord.ko.yml | 6 ++++++ config/locales/ko.yml | 8 ++++++++ config/locales/lv.yml | 2 +- config/locales/simple_form.ko.yml | 2 ++ 6 files changed, 21 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 6795bc647c..cf2082e105 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -778,6 +778,7 @@ "status.bookmark": "북마크", "status.cancel_reblog_private": "부스트 취소", "status.cannot_reblog": "이 게시물은 부스트 할 수 없습니다", + "status.continued_thread": "이어지는 글타래", "status.copy": "게시물 링크 복사", "status.delete": "삭제", "status.detailed_status": "대화 자세히 보기", @@ -786,6 +787,7 @@ "status.edit": "수정", "status.edited": "{date}에 마지막으로 편집됨", "status.edited_x_times": "{count, plural, other {{count}}} 번 수정됨", + "status.embed": "임베드 코드 받기", "status.favourite": "좋아요", "status.favourites": "{count, plural, other {좋아요}}", "status.filter": "이 게시물을 필터", @@ -810,6 +812,7 @@ "status.reblogs.empty": "아직 아무도 이 게시물을 부스트하지 않았습니다. 부스트 한 사람들이 여기에 표시 됩니다.", "status.redraft": "지우고 다시 쓰기", "status.remove_bookmark": "북마크 삭제", + "status.replied_in_thread": "글타래에 답장", "status.replied_to": "{name} 님에게", "status.reply": "답장", "status.replyAll": "글타래에 답장", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index b53f65ab43..53b3c0fcaa 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -409,6 +409,7 @@ "lists.subheading": "Tavi saraksti", "load_pending": "{count, plural, one {# jauna lieta} other {# jaunas lietas}}", "loading_indicator.label": "Ielādē…", + "media_gallery.hide": "Paslēpt", "moved_to_account_banner.text": "Tavs konts {disabledAccount} pašlaik ir atspējots, jo Tu pārcēlies uz kontu {movedToAccount}.", "mute_modal.hide_from_notifications": "Paslēpt paziņojumos", "mute_modal.hide_options": "Paslēpt iespējas", diff --git a/config/locales/activerecord.ko.yml b/config/locales/activerecord.ko.yml index 294d614bca..6d437b72b0 100644 --- a/config/locales/activerecord.ko.yml +++ b/config/locales/activerecord.ko.yml @@ -15,6 +15,12 @@ ko: user/invite_request: text: 이유 errors: + attributes: + domain: + invalid: 올바른 도메인 네임이 아닙니다 + messages: + invalid_domain_on_line: "%{value}는 올바른 도메인 네임이 아닙니다" + too_many_lines: "%{limit}줄 제한을 초과합니다" models: account: attributes: diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 3217a8e49a..216e468762 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -22,6 +22,7 @@ ko: admin: account_actions: action: 조치 취하기 + already_silenced: 이 계정은 이미 제한되었습니다. already_suspended: 이 계정은 이미 정지되었습니다. title: "%{acct} 계정에 중재 취하기" account_moderation_notes: @@ -1143,6 +1144,12 @@ ko: view_strikes: 내 계정에 대한 과거 중재 기록 보기 too_fast: 너무 빠르게 양식이 제출되었습니다, 다시 시도하세요. use_security_key: 보안 키 사용 + author_attribution: + example_title: 예시 텍스트 + hint_html: 링크가 마스토돈에 공유될 때 내가 어떻게 표시될 지를 제어합니다. + more_from_html: "%{name}의 게시물 더 보기" + s_blog: "%{name}의 블로그" + title: 작성자 기여 challenge: confirm: 계속 hint_html: "팁: 한 시간 동안 다시 암호를 묻지 않을 것입니다." @@ -1906,6 +1913,7 @@ ko: instructions_html: 웹사이트에 아래 코드를 복사해 붙여 넣으세요. 그리고 "프로필 수정" 탭에서 그 웹사이트 주소를 프로필의 추가 필드 중 하나에 넣고 변경사항을 저장하세요. verification: 검증 verified_links: 인증된 링크들 + website_verification: 웹사이트 인증 webauthn_credentials: add: 보안 키 추가 create: diff --git a/config/locales/lv.yml b/config/locales/lv.yml index be6555a386..4aeec5ceca 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -1114,7 +1114,7 @@ lv: new_confirmation_instructions_sent: Pēc dažām minūtēm saņemsi jaunu e-pasta ziņojumu ar apstiprinājuma saiti. title: Pārbaudi savu iesūtni sign_in: - preamble_html: Jāpiesakās ar saviem %{domain} piekļuves datiem. Ja Tavs konts tiek mitināts citā serverī, Tu nevarēsi šeit pieteikties. + preamble_html: Jāpiesakās ar saviem %{domain} piekļuves datiem. Ja konts tiek mitināts citā serverī, šeit nevarēs pieteikties. title: Pierakstīties %{domain} sign_up: manual_review: Reģistrācijas domēnā %{domain} manuāli pārbauda mūsu moderatori. Lai palīdzētu mums apstrādāt tavu reģistrāciju, uzraksti mazliet par sevi un to, kāpēc vēlies kontu %{domain}. diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml index fee07fa5e0..a649b4ec5a 100644 --- a/config/locales/simple_form.ko.yml +++ b/config/locales/simple_form.ko.yml @@ -3,6 +3,7 @@ ko: simple_form: hints: account: + attribution_domains_as_text: 가짜 기여로부터 보호합니다. discoverable: 내 공개 게시물과 프로필이 마스토돈의 다양한 추천 기능에 나타날 수 있고 프로필이 다른 사용자에게 제안될 수 있습니다 display_name: 진짜 이름 또는 재미난 이름. fields: 홈페이지, 호칭, 나이, 뭐든지 적고 싶은 것들. @@ -143,6 +144,7 @@ ko: url: 이벤트가 어디로 전송될 지 labels: account: + attribution_domains_as_text: 특정 웹사이트만 허용하기 discoverable: 발견하기 알고리즘에 프로필과 게시물을 추천하기 fields: name: 라벨 From ef4d6ab98875891716fa2b9ce22ed34afc58a53f Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 19 Sep 2024 12:52:46 +0200 Subject: [PATCH 07/10] Fix browser glitch caused by two overlapping scroll animations in web UI (#31960) --- .../features/ui/components/columns_area.jsx | 32 +------------------ app/javascript/mastodon/scroll.ts | 25 +++++++++------ app/javascript/mastodon/test_helpers.tsx | 8 +++++ 3 files changed, 25 insertions(+), 40 deletions(-) diff --git a/app/javascript/mastodon/features/ui/components/columns_area.jsx b/app/javascript/mastodon/features/ui/components/columns_area.jsx index 5a2ea8c2c8..ff76d5bcb2 100644 --- a/app/javascript/mastodon/features/ui/components/columns_area.jsx +++ b/app/javascript/mastodon/features/ui/components/columns_area.jsx @@ -4,8 +4,6 @@ import { Children, cloneElement, useCallback } from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { supportsPassiveEvents } from 'detect-passive-events'; - import { scrollRight } from '../../../scroll'; import BundleContainer from '../containers/bundle_container'; import { @@ -71,10 +69,6 @@ export default class ColumnsArea extends ImmutablePureComponent { }; componentDidMount() { - if (!this.props.singleColumn) { - this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); - } - if (this.mediaQuery) { if (this.mediaQuery.addEventListener) { this.mediaQuery.addEventListener('change', this.handleLayoutChange); @@ -87,23 +81,7 @@ export default class ColumnsArea extends ImmutablePureComponent { this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl'); } - UNSAFE_componentWillUpdate(nextProps) { - if (this.props.singleColumn !== nextProps.singleColumn && nextProps.singleColumn) { - this.node.removeEventListener('wheel', this.handleWheel); - } - } - - componentDidUpdate(prevProps) { - if (this.props.singleColumn !== prevProps.singleColumn && !this.props.singleColumn) { - this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); - } - } - componentWillUnmount () { - if (!this.props.singleColumn) { - this.node.removeEventListener('wheel', this.handleWheel); - } - if (this.mediaQuery) { if (this.mediaQuery.removeEventListener) { this.mediaQuery.removeEventListener('change', this.handleLayoutChange); @@ -116,7 +94,7 @@ export default class ColumnsArea extends ImmutablePureComponent { handleChildrenContentChange() { if (!this.props.singleColumn) { const modifier = this.isRtlLayout ? -1 : 1; - this._interruptScrollAnimation = scrollRight(this.node, (this.node.scrollWidth - window.innerWidth) * modifier); + scrollRight(this.node, (this.node.scrollWidth - window.innerWidth) * modifier); } } @@ -124,14 +102,6 @@ export default class ColumnsArea extends ImmutablePureComponent { this.setState({ renderComposePanel: !e.matches }); }; - handleWheel = () => { - if (typeof this._interruptScrollAnimation !== 'function') { - return; - } - - this._interruptScrollAnimation(); - }; - setRef = (node) => { this.node = node; }; diff --git a/app/javascript/mastodon/scroll.ts b/app/javascript/mastodon/scroll.ts index 35e13a4527..0756edb4ce 100644 --- a/app/javascript/mastodon/scroll.ts +++ b/app/javascript/mastodon/scroll.ts @@ -38,13 +38,20 @@ const scroll = ( const isScrollBehaviorSupported = 'scrollBehavior' in document.documentElement.style; -export const scrollRight = (node: Element, position: number) => { - if (isScrollBehaviorSupported) - node.scrollTo({ left: position, behavior: 'smooth' }); - else scroll(node, 'scrollLeft', position); -}; +export const scrollRight = (node: Element, position: number) => + requestIdleCallback(() => { + if (isScrollBehaviorSupported) { + node.scrollTo({ left: position, behavior: 'smooth' }); + } else { + scroll(node, 'scrollLeft', position); + } + }); -export const scrollTop = (node: Element) => { - if (isScrollBehaviorSupported) node.scrollTo({ top: 0, behavior: 'smooth' }); - else scroll(node, 'scrollTop', 0); -}; +export const scrollTop = (node: Element) => + requestIdleCallback(() => { + if (isScrollBehaviorSupported) { + node.scrollTo({ top: 0, behavior: 'smooth' }); + } else { + scroll(node, 'scrollTop', 0); + } + }); diff --git a/app/javascript/mastodon/test_helpers.tsx b/app/javascript/mastodon/test_helpers.tsx index f405090730..8a6f5a3377 100644 --- a/app/javascript/mastodon/test_helpers.tsx +++ b/app/javascript/mastodon/test_helpers.tsx @@ -8,6 +8,14 @@ import { render as rtlRender } from '@testing-library/react'; import { IdentityContext } from './identity_context'; +beforeEach(() => { + global.requestIdleCallback = jest + .fn() + .mockImplementation((fn: () => void) => { + fn(); + }); +}); + function render( ui: React.ReactElement, { From 6801afa12f3611c86aeec78a2d43ffa8323ecec6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:56:09 +0000 Subject: [PATCH 08/10] Update dependency devise-two-factor to v6 [SECURITY] (#31957) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: David Roetzel --- Gemfile.lock | 2 +- spec/models/user_spec.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 41a8b68fae..79e542014c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -197,7 +197,7 @@ GEM railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-two-factor (5.1.0) + devise-two-factor (6.0.0) activesupport (~> 7.0) devise (~> 4.0) railties (~> 7.0) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index fcff4c0d3b..972453cd69 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -4,6 +4,8 @@ require 'rails_helper' require 'devise_two_factor/spec_helpers' RSpec.describe User do + subject { described_class.new(account: account) } + let(:password) { 'abcd1234' } let(:account) { Fabricate(:account, username: 'alice') } From 2946a9286b1b4a5323f9f7ea6e7b29b6ca5d309d Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 19 Sep 2024 09:38:32 -0400 Subject: [PATCH 09/10] Use `headers` shorthand in mailers (#31956) --- app/mailers/admin_mailer.rb | 8 +++++--- app/mailers/application_mailer.rb | 8 +++++--- app/mailers/notification_mailer.rb | 28 ++++++++++++++++------------ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/app/mailers/admin_mailer.rb b/app/mailers/admin_mailer.rb index 8dd7b6e59f..72a2c2e64e 100644 --- a/app/mailers/admin_mailer.rb +++ b/app/mailers/admin_mailer.rb @@ -56,9 +56,11 @@ class AdminMailer < ApplicationMailer def new_critical_software_updates @software_updates = SoftwareUpdate.where(urgent: true).to_a.sort_by(&:gem_version) - headers['Priority'] = 'urgent' - headers['X-Priority'] = '1' - headers['Importance'] = 'high' + headers( + 'Importance' => 'high', + 'Priority' => 'urgent', + 'X-Priority' => '1' + ) locale_for_account(@me) do mail subject: default_i18n_subject(instance: @instance) diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 35f0b5fee1..9a209aa77b 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -16,8 +16,10 @@ class ApplicationMailer < ActionMailer::Base end def set_autoreply_headers! - headers['Precedence'] = 'list' - headers['X-Auto-Response-Suppress'] = 'All' - headers['Auto-Submitted'] = 'auto-generated' + headers( + 'Auto-Submitted' => 'auto-generated', + 'Precedence' => 'list', + 'X-Auto-Response-Suppress' => 'All' + ) end end diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb index 4eb38ec340..6b21b4bedd 100644 --- a/app/mailers/notification_mailer.rb +++ b/app/mailers/notification_mailer.rb @@ -6,7 +6,10 @@ class NotificationMailer < ApplicationMailer :routing before_action :process_params - before_action :set_status, only: [:mention, :favourite, :reblog] + with_options only: %i(mention favourite reblog) do + before_action :set_status + after_action :thread_by_conversation! + end before_action :set_account, only: [:follow, :favourite, :reblog, :follow_request] after_action :set_list_headers! @@ -18,7 +21,6 @@ class NotificationMailer < ApplicationMailer return unless @user.functional? && @status.present? locale_for_account(@me) do - thread_by_conversation(@status.conversation) mail subject: default_i18n_subject(name: @status.account.acct) end end @@ -35,7 +37,6 @@ class NotificationMailer < ApplicationMailer return unless @user.functional? && @status.present? locale_for_account(@me) do - thread_by_conversation(@status.conversation) mail subject: default_i18n_subject(name: @account.acct) end end @@ -44,7 +45,6 @@ class NotificationMailer < ApplicationMailer return unless @user.functional? && @status.present? locale_for_account(@me) do - thread_by_conversation(@status.conversation) mail subject: default_i18n_subject(name: @account.acct) end end @@ -76,17 +76,21 @@ class NotificationMailer < ApplicationMailer end def set_list_headers! - headers['List-ID'] = "<#{@type}.#{@me.username}.#{Rails.configuration.x.local_domain}>" - headers['List-Unsubscribe'] = "<#{@unsubscribe_url}>" - headers['List-Unsubscribe-Post'] = 'List-Unsubscribe=One-Click' + headers( + 'List-ID' => "<#{@type}.#{@me.username}.#{Rails.configuration.x.local_domain}>", + 'List-Unsubscribe-Post' => 'List-Unsubscribe=One-Click', + 'List-Unsubscribe' => "<#{@unsubscribe_url}>" + ) end - def thread_by_conversation(conversation) - return if conversation.nil? + def thread_by_conversation! + return if @status.conversation.nil? - msg_id = "" + conversation_message_id = "" - headers['In-Reply-To'] = msg_id - headers['References'] = msg_id + headers( + 'In-Reply-To' => conversation_message_id, + 'References' => conversation_message_id + ) end end From 5a8f2fe31d15a2a07384d118b5cbcd10ad714be4 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 19 Sep 2024 09:43:40 -0400 Subject: [PATCH 10/10] Convert `settings/exports` controller spec to system/request specs (#31965) --- .../settings/exports_controller_spec.rb | 47 ------------------- spec/requests/settings/exports_spec.rb | 25 ++++++++++ spec/system/settings/exports_spec.rb | 40 ++++++++++++++++ 3 files changed, 65 insertions(+), 47 deletions(-) delete mode 100644 spec/controllers/settings/exports_controller_spec.rb create mode 100644 spec/requests/settings/exports_spec.rb create mode 100644 spec/system/settings/exports_spec.rb diff --git a/spec/controllers/settings/exports_controller_spec.rb b/spec/controllers/settings/exports_controller_spec.rb deleted file mode 100644 index 1eafabc7e5..0000000000 --- a/spec/controllers/settings/exports_controller_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Settings::ExportsController do - render_views - - describe 'GET #show' do - context 'when signed in' do - let(:user) { Fabricate(:user) } - - before do - sign_in user, scope: :user - get :show - end - - it 'returns http success with private cache control headers', :aggregate_failures do - expect(response).to have_http_status(200) - expect(response.headers['Cache-Control']).to include('private, no-store') - end - end - - context 'when not signed in' do - it 'redirects' do - get :show - expect(response).to redirect_to '/auth/sign_in' - end - end - end - - describe 'POST #create' do - before do - sign_in Fabricate(:user), scope: :user - end - - it 'redirects to settings_export_path' do - post :create - expect(response).to redirect_to(settings_export_path) - end - - it 'queues BackupWorker job by 1' do - expect do - post :create - end.to change(BackupWorker.jobs, :size).by(1) - end - end -end diff --git a/spec/requests/settings/exports_spec.rb b/spec/requests/settings/exports_spec.rb new file mode 100644 index 0000000000..db823ac770 --- /dev/null +++ b/spec/requests/settings/exports_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Settings / Exports' do + context 'when not signed in' do + describe 'GET /settings/export' do + it 'redirects to sign in page' do + get settings_export_path + + expect(response) + .to redirect_to new_user_session_path + end + end + + describe 'POST /settings/export' do + it 'redirects to sign in page' do + post settings_export_path + + expect(response) + .to redirect_to new_user_session_path + end + end + end +end diff --git a/spec/system/settings/exports_spec.rb b/spec/system/settings/exports_spec.rb new file mode 100644 index 0000000000..2cc2961a0b --- /dev/null +++ b/spec/system/settings/exports_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Export page' do + let(:user) { Fabricate :user } + + before { sign_in user } + + describe 'Viewing the export page' do + context 'when signed in' do + it 'shows the export page', :aggregate_failures do + visit settings_export_path + + expect(page) + .to have_content(takeout_summary) + .and have_private_cache_control + end + end + end + + describe 'Creating a new archive' do + it 'queues a worker and redirects' do + visit settings_export_path + + expect { request_archive } + .to change(BackupWorker.jobs, :size).by(1) + expect(page) + .to have_content(takeout_summary) + end + + def request_archive + click_on I18n.t('exports.archive_takeout.request') + end + end + + def takeout_summary + I18n.t('settings.export') + end +end