diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 13fb25d333..275334a7a0 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --auto-gen-only-exclude --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.75.2. +# using RuboCop version 1.75.3. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new diff --git a/Gemfile b/Gemfile index 9e5955e0b8..b55ec1d730 100644 --- a/Gemfile +++ b/Gemfile @@ -79,7 +79,7 @@ gem 'rails-i18n', '~> 8.0' gem 'redcarpet', '~> 3.6' gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis'] gem 'redis-namespace', '~> 1.10' -gem 'rqrcode', '~> 2.2' +gem 'rqrcode', '~> 3.0' gem 'ruby-progressbar', '~> 1.13' gem 'sanitize', '~> 7.0' gem 'scenic', '~> 1.7' diff --git a/Gemfile.lock b/Gemfile.lock index 1c1f752ec3..4eb975c6c0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -160,7 +160,7 @@ GEM cocoon (1.2.15) color_diff (0.1) concurrent-ruby (1.3.5) - connection_pool (2.5.1) + connection_pool (2.5.2) cose (1.3.1) cbor (~> 0.5.9) openssl-signature_algorithm (~> 1.0) @@ -711,10 +711,10 @@ GEM rotp (6.3.0) rouge (4.5.1) rpam2 (4.0.2) - rqrcode (2.2.0) + rqrcode (3.0.0) chunky_png (~> 1.0) - rqrcode_core (~> 1.0) - rqrcode_core (1.2.0) + rqrcode_core (~> 2.0) + rqrcode_core (2.0.0) rspec (3.13.0) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) @@ -743,7 +743,7 @@ GEM rspec-mocks (~> 3.0) sidekiq (>= 5, < 9) rspec-support (3.13.2) - rubocop (1.75.2) + rubocop (1.75.3) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) @@ -773,7 +773,7 @@ GEM rack (>= 1.1) rubocop (>= 1.75.0, < 2.0) rubocop-ast (>= 1.38.0, < 2.0) - rubocop-rspec (3.5.0) + rubocop-rspec (3.6.0) lint_roller (~> 1.1) rubocop (~> 1.72, >= 1.72.1) rubocop-rspec_rails (2.31.0) @@ -1043,7 +1043,7 @@ DEPENDENCIES redcarpet (~> 3.6) redis (~> 4.5) redis-namespace (~> 1.10) - rqrcode (~> 2.2) + rqrcode (~> 3.0) rspec-github (~> 3.0) rspec-rails (~> 7.0) rspec-sidekiq (~> 5.0) diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 06a113511c..b73dae17e5 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -72,6 +72,13 @@ class Api::BaseController < ApplicationController end end + # Redefine `require_functional!` to properly output JSON instead of HTML redirects + def require_functional! + return if current_user.functional? + + require_user! + end + def render_empty render json: {}, status: 200 end diff --git a/app/controllers/api/v1/featured_tags_controller.rb b/app/controllers/api/v1/featured_tags_controller.rb index 516046f009..15c5de67a2 100644 --- a/app/controllers/api/v1/featured_tags_controller.rb +++ b/app/controllers/api/v1/featured_tags_controller.rb @@ -18,7 +18,7 @@ class Api::V1::FeaturedTagsController < Api::BaseController end def destroy - RemoveFeaturedTagWorker.perform_async(current_account.id, @featured_tag.id) + RemoveFeaturedTagService.new.call(current_account, @featured_tag) render_empty end diff --git a/app/controllers/api/v1/tags_controller.rb b/app/controllers/api/v1/tags_controller.rb index 672535a018..67a4d8ef49 100644 --- a/app/controllers/api/v1/tags_controller.rb +++ b/app/controllers/api/v1/tags_controller.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true class Api::V1::TagsController < Api::BaseController - before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, except: :show + before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, only: [:follow, :unfollow] + before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:feature, :unfeature] before_action :require_user!, except: :show before_action :set_or_create_tag @@ -23,6 +24,16 @@ class Api::V1::TagsController < Api::BaseController render json: @tag, serializer: REST::TagSerializer end + def feature + CreateFeaturedTagService.new.call(current_account, @tag) + render json: @tag, serializer: REST::TagSerializer + end + + def unfeature + RemoveFeaturedTagService.new.call(current_account, @tag) + render json: @tag, serializer: REST::TagSerializer + end + private def set_or_create_tag diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1b071e8655..c11fd2a635 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -72,10 +72,24 @@ class ApplicationController < ActionController::Base def require_functional! return if current_user.functional? - if current_user.confirmed? - redirect_to edit_user_registration_path - else - redirect_to auth_setup_path + respond_to do |format| + format.any do + if current_user.confirmed? + redirect_to edit_user_registration_path + else + redirect_to auth_setup_path + end + end + + format.json do + if !current_user.confirmed? + render json: { error: 'Your login is missing a confirmed e-mail address' }, status: 403 + elsif !current_user.approved? + render json: { error: 'Your login is currently pending approval' }, status: 403 + elsif !current_user.functional? + render json: { error: 'Your login is currently disabled' }, status: 403 + end + end end end diff --git a/app/controllers/concerns/localized.rb b/app/controllers/concerns/localized.rb index 14742e3b5c..fa452c12b5 100644 --- a/app/controllers/concerns/localized.rb +++ b/app/controllers/concerns/localized.rb @@ -16,7 +16,7 @@ module Localized def requested_locale requested_locale_name = available_locale_or_nil(params[:lang]) requested_locale_name ||= available_locale_or_nil(current_user.locale) if respond_to?(:user_signed_in?) && user_signed_in? - requested_locale_name ||= http_accept_language if ENV['DEFAULT_LOCALE'].blank? + requested_locale_name ||= http_accept_language unless ENV['FORCE_DEFAULT_LOCALE'] == 'true' requested_locale_name end diff --git a/app/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb index 0f352e1913..d2fbd1f0f3 100644 --- a/app/controllers/settings/featured_tags_controller.rb +++ b/app/controllers/settings/featured_tags_controller.rb @@ -12,7 +12,7 @@ class Settings::FeaturedTagsController < Settings::BaseController end def create - @featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name], force: false) + @featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name], raise_error: false) if @featured_tag.valid? redirect_to settings_featured_tags_path diff --git a/app/javascript/entrypoints/sign_up.ts b/app/javascript/entrypoints/sign_up.ts index 880738fcb7..87100be56d 100644 --- a/app/javascript/entrypoints/sign_up.ts +++ b/app/javascript/entrypoints/sign_up.ts @@ -4,9 +4,12 @@ import axios from 'axios'; import ready from '../mastodon/ready'; async function checkConfirmation() { - const response = await axios.get('/api/v1/emails/check_confirmation'); + const response = await axios.get('/api/v1/emails/check_confirmation', { + headers: { Accept: 'application/json' }, + withCredentials: true, + }); - if (response.data) { + if (response.status === 200 && response.data === true) { window.location.href = '/start'; } } diff --git a/app/javascript/images/logo-symbol-icon.svg b/app/javascript/images/logo-symbol-icon.svg index c4c14f098a..40216cb769 100644 --- a/app/javascript/images/logo-symbol-icon.svg +++ b/app/javascript/images/logo-symbol-icon.svg @@ -1,2 +1,2 @@ - + diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index de30325e69..c778666ceb 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -412,14 +412,7 @@ class Status extends ImmutablePureComponent { let visibilityName = status.get('limited_scope') || status.get('visibility_ex') || status.get('visibility'); - if (featured) { - prepend = ( -
-
- -
- ); - } else if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') { + if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') { const display_name_html = { __html: status.getIn(['account', 'display_name_html']) }; prepend = ( diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index f806f64023..9a121dce96 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -292,7 +292,7 @@ "column.local": "Local", "column.mutes": "Muted users", "column.notifications": "Notifications", - "column.pins": "Pinned posts", + "column.pins": "Featured posts", "column.public": "Federated timeline", "column.reaction_deck": "Reaction deck", "column_back_button.label": "Back", @@ -623,7 +623,7 @@ "keyboard_shortcuts.my_profile": "Open your profile", "keyboard_shortcuts.notifications": "Open notifications column", "keyboard_shortcuts.open_media": "Open media", - "keyboard_shortcuts.pinned": "Open pinned posts list", + "keyboard_shortcuts.pinned": "Open featured posts list", "keyboard_shortcuts.profile": "Open author's profile", "keyboard_shortcuts.reply": "Reply to post", "keyboard_shortcuts.requests": "Open follow requests list", @@ -718,7 +718,7 @@ "navigation_bar.mutes": "Muted users", "navigation_bar.opened_in_classic_interface": "Posts, accounts, and other specific pages are opened by default in the classic web interface.", "navigation_bar.personal": "Personal", - "navigation_bar.pins": "Pinned posts", + "navigation_bar.pins": "Featured posts", "navigation_bar.preferences": "Preferences", "navigation_bar.public_timeline": "Federated timeline", "navigation_bar.reaction_deck": "Reaction deck", @@ -1069,8 +1069,7 @@ "status.mute": "Mute @{name}", "status.mute_conversation": "Mute conversation", "status.open": "Expand this post", - "status.pin": "Pin on profile", - "status.pinned": "Pinned post", + "status.pin": "Feature on profile", "status.read_more": "Read more", "status.reblog": "Boost", "status.reblog_private": "Boost with original visibility", @@ -1098,7 +1097,7 @@ "status.translated_from_with": "Translated from {lang} using {provider}", "status.uncached_media_warning": "Preview not available", "status.unmute_conversation": "Unmute conversation", - "status.unpin": "Unpin from profile", + "status.unpin": "Don't feature on profile", "subscribed_languages.lead": "Only posts in selected languages will appear on your home and list timelines after the change. Select none to receive posts in all languages.", "subscribed_languages.save": "Save changes", "subscribed_languages.target": "Change subscribed languages for {target}", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 7e207d917e..ff44e4ab96 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -19,13 +19,16 @@ "account.block_domain": "Blokir domain {domain}", "account.block_short": "Blokir", "account.blocked": "Terblokir", + "account.blocking": "Memblokir", "account.cancel_follow_request": "Batalkan permintaan ikut", "account.copy": "Salin tautan ke profil", "account.direct": "Sebut secara pribadi @{name}", "account.disable_notifications": "Berhenti memberitahu saya ketika @{name} memposting", + "account.domain_blocking": "Memblokir domain", "account.edit_profile": "Ubah profil", "account.enable_notifications": "Beritahu saya saat @{name} memposting", "account.endorse": "Tampilkan di profil", + "account.featured": "", "account.featured_tags.last_status_at": "Kiriman terakhir pada {date}", "account.featured_tags.last_status_never": "Tidak ada kiriman", "account.follow": "Ikuti", @@ -36,6 +39,7 @@ "account.following": "Mengikuti", "account.following_counter": "{count, plural, other {{counter} following}}", "account.follows.empty": "Pengguna ini belum mengikuti siapa pun.", + "account.follows_you": "Mengikuti Anda", "account.go_to_profile": "Buka profil", "account.hide_reblogs": "Sembunyikan boosts dari @{name}", "account.in_memoriam": "Mengenang.", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 111c78db0f..94e561cb28 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -19,10 +19,12 @@ "account.block_domain": "{domain} 도메인 차단", "account.block_short": "차단", "account.blocked": "차단함", + "account.blocking": "차단함", "account.cancel_follow_request": "팔로우 취소", "account.copy": "프로필 링크 복사", "account.direct": "@{name} 님에게 개인적으로 멘션", "account.disable_notifications": "@{name} 의 게시물 알림 끄기", + "account.domain_blocking": "도메인 차단함", "account.edit_profile": "프로필 편집", "account.enable_notifications": "@{name} 의 게시물 알림 켜기", "account.endorse": "프로필에 추천하기", @@ -39,6 +41,7 @@ "account.following": "팔로잉", "account.following_counter": "{count, plural, other {팔로잉 {counter}명}}", "account.follows.empty": "이 사용자는 아직 아무도 팔로우하고 있지 않습니다.", + "account.follows_you": "나를 팔로우", "account.go_to_profile": "프로필로 이동", "account.hide_reblogs": "@{name}의 부스트를 숨기기", "account.in_memoriam": "고인의 계정입니다.", @@ -53,13 +56,17 @@ "account.mute_notifications_short": "알림 뮤트", "account.mute_short": "뮤트", "account.muted": "뮤트됨", + "account.muting": "뮤트함", + "account.mutual": "서로 팔로우", "account.no_bio": "제공된 설명이 없습니다.", "account.open_original_page": "원본 페이지 열기", "account.posts": "게시물", "account.posts_with_replies": "게시물과 답장", + "account.remove_from_followers": "팔로워에서 {name} 제거", "account.report": "@{name} 신고", "account.requested": "승인 대기 중. 클릭해서 취소하기", "account.requested_follow": "{name} 님이 팔로우 요청을 보냈습니다", + "account.requests_to_follow_you": "팔로우 요청", "account.share": "@{name}의 프로필 공유", "account.show_reblogs": "@{name}의 부스트 보기", "account.statuses_counter": "{count, plural, other {게시물 {counter}개}}", @@ -227,6 +234,9 @@ "confirmations.redraft.confirm": "삭제하고 다시 쓰기", "confirmations.redraft.message": "정말로 이 게시물을 삭제하고 다시 쓰시겠습니까? 해당 게시물에 대한 부스트와 좋아요를 잃게 되고 원본에 대한 답장은 연결 되지 않습니다.", "confirmations.redraft.title": "삭제하고 다시 작성할까요?", + "confirmations.remove_from_followers.confirm": "팔로워 제거", + "confirmations.remove_from_followers.message": "{name} 님이 나를 팔로우하지 않게 됩니다. 계속할까요?", + "confirmations.remove_from_followers.title": "팔로워를 제거할까요?", "confirmations.reply.confirm": "답글", "confirmations.reply.message": "지금 답장하면 작성 중인 메시지를 덮어쓰게 됩니다. 정말 진행합니까?", "confirmations.reply.title": "게시물을 덮어쓸까요?", @@ -294,6 +304,9 @@ "emoji_button.search_results": "검색 결과", "emoji_button.symbols": "기호", "emoji_button.travel": "여행과 장소", + "empty_column.account_featured.me": "아직 아무 것도 추천하지 않았습니다. 게시물, 자주 사용하는 해시태그, 친구의 계정까지 내 계정에서 추천할 수 있다는 것을 알고 계신가요?", + "empty_column.account_featured.other": "{acct} 님은 아직 아무 것도 추천하지 않았습니다. 게시물, 자주 사용하는 해시태그, 친구의 계정까지 내 계정에서 추천할 수 있다는 것을 알고 계신가요?", + "empty_column.account_featured_other.unknown": "이 계정은 아직 아무 것도 추천하지 않았습니다.", "empty_column.account_hides_collections": "이 사용자는 이 정보를 사용할 수 없도록 설정했습니다", "empty_column.account_suspended": "계정 정지됨", "empty_column.account_timeline": "이곳에는 게시물이 없습니다!", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index e1e3ee98ab..cc008e06a1 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -6,10 +6,10 @@ "about.domain_blocks.preamble": "Mastodon parasti ļauj apskatīt saturu un mijiedarboties ar lietotājiem no jebkura cita fediversa servera. Šie ir izņēmumi, kas veikti tieši šajā serverī.", "about.domain_blocks.silenced.explanation": "Parasti tu neredzēsi profilus un saturu no šī servera, ja vien tu nepārprotami izvēlēsies to pārskatīt vai sekot.", "about.domain_blocks.silenced.title": "Ierobežotie", - "about.domain_blocks.suspended.explanation": "Nekādi dati no šī servera netiks apstrādāti, uzglabāti vai apmainīti, padarot neiespējamu mijiedarbību vai saziņu ar lietotājiem no šī servera.", + "about.domain_blocks.suspended.explanation": "Nekādi dati no šī servera netiks apstrādāti, uzglabāti vai apmainīti, padarot neiespējamu jebkādu mijiedarbību vai saziņu ar šī servera lietotājiem.", "about.domain_blocks.suspended.title": "Apturētie", "about.not_available": "Šī informācija nav padarīta pieejama šajā serverī.", - "about.powered_by": "Decentralizētu sociālo tīklu nodrošina {mastodon}", + "about.powered_by": "Decentralizētu sabiedrisko tīklu darbina {mastodon}", "about.rules": "Servera noteikumi", "account.account_note_header": "Personīga piezīme", "account.add_or_remove_from_list": "Pievienot vai Noņemt no sarakstiem", @@ -22,12 +22,14 @@ "account.cancel_follow_request": "Atsaukt sekošanas pieprasījumu", "account.copy": "Ievietot saiti uz profilu starpliktuvē", "account.direct": "Pieminēt @{name} privāti", - "account.disable_notifications": "Pārtraukt man paziņot, kad @{name} publicē ierakstu", + "account.disable_notifications": "Pārtraukt man paziņot, kad @{name} izveido ierakstu", "account.edit_profile": "Labot profilu", - "account.enable_notifications": "Paziņot man, kad @{name} publicē ierakstu", + "account.enable_notifications": "Paziņot man, kad @{name} izveido ierakstu", "account.endorse": "Izcelts profilā", - "account.featured_tags.last_status_at": "Beidzamā ziņa {date}", - "account.featured_tags.last_status_never": "Ierakstu nav", + "account.featured.hashtags": "Tēmturi", + "account.featured.posts": "Ieraksti", + "account.featured_tags.last_status_at": "Pēdējais ieraksts {date}", + "account.featured_tags.last_status_never": "Nav ierakstu", "account.follow": "Sekot", "account.follow_back": "Sekot atpakaļ", "account.followers": "Sekotāji", @@ -36,6 +38,7 @@ "account.following": "Seko", "account.following_counter": "{count, plural, one {seko {counter}} other {seko {counter}}}", "account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.", + "account.follows_you": "Seko tev", "account.go_to_profile": "Doties uz profilu", "account.hide_reblogs": "Paslēpt @{name} pastiprinātos ierakstus", "account.in_memoriam": "Piemiņai.", @@ -47,17 +50,19 @@ "account.mention": "Pieminēt @{name}", "account.moved_to": "{name} norādīja, ka viņu jaunais konts tagad ir:", "account.mute": "Apklusināt @{name}", - "account.mute_notifications_short": "Izslēgt paziņojumu skaņu", + "account.mute_notifications_short": "Apklusināt paziņojumus", "account.mute_short": "Apklusināt", "account.muted": "Apklusināts", + "account.mutual": "Jūs sekojat viens otram", "account.no_bio": "Apraksts nav sniegts.", "account.open_original_page": "Atvērt pirmavota lapu", "account.posts": "Ieraksti", "account.posts_with_replies": "Ieraksti un atbildes", "account.remove_from_followers": "Dzēst sekotāju {name}", - "account.report": "Sūdzēties par @{name}", + "account.report": "Ziņot par @{name}", "account.requested": "Gaida apstiprinājumu. Nospied, lai atceltu sekošanas pieparasījumu", "account.requested_follow": "{name} nosūtīja Tev sekošanas pieprasījumu", + "account.requests_to_follow_you": "Sekošanas pieprasījumi", "account.share": "Dalīties ar @{name} profilu", "account.show_reblogs": "Parādīt @{name} pastiprinātos ierakstus", "account.statuses_counter": "{count, plural, zero {{counter} ierakstu} one {{counter} ieraksts} other {{counter} ieraksti}}", @@ -67,7 +72,7 @@ "account.unendorse": "Neizcelt profilā", "account.unfollow": "Pārstāt sekot", "account.unmute": "Noņemt apklusinājumu @{name}", - "account.unmute_notifications_short": "Ieslēgt paziņojumu skaņu", + "account.unmute_notifications_short": "Atcelet paziņojumu apklusināšanu", "account.unmute_short": "Noņemt apklusinājumu", "account_note.placeholder": "Noklikšķini, lai pievienotu piezīmi", "admin.dashboard.daily_retention": "Lietotāju saglabāšanas rādītājs dienā pēc reģistrēšanās", @@ -91,12 +96,13 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Aprakstīt šo cilvēkiem ar redzes traucējumiem…", "alt_text_modal.done": "Gatavs", "announcement.announcement": "Paziņojums", + "annual_report.summary.archetype.lurker": "Glūņa", "annual_report.summary.archetype.oracle": "Orākuls", "annual_report.summary.archetype.replier": "Sabiedriskais tauriņš", "annual_report.summary.followers.followers": "sekotāji", "annual_report.summary.followers.total": "pavisam {count}", "annual_report.summary.here_it_is": "Šeit ir {year}. gada pārskats:", - "annual_report.summary.highlighted_post.by_favourites": "izlasēs visvairāk ievietotais ieraksts", + "annual_report.summary.highlighted_post.by_favourites": "izlasēm visvairāk pievienotais ieraksts", "annual_report.summary.highlighted_post.by_reblogs": "vispastiprinātākais ieraksts", "annual_report.summary.highlighted_post.by_replies": "ieraksts ar vislielāko atbilžu skaitu", "annual_report.summary.highlighted_post.possessive": "{name}", @@ -109,16 +115,17 @@ "annual_report.summary.thanks": "Paldies, ka esi daļa no Mastodon!", "attachments_list.unprocessed": "(neapstrādāti)", "audio.hide": "Slēpt audio", - "block_modal.remote_users_caveat": "Mēs vaicāsim serverim {domain} ņemt vērā Tavu lēmumu. Tomēr atbilstība nav nodrošināta, jo atsevišķi serveri var apstrādāt bloķēšanu citādi. Publiski ieraksti joprojām var būt redzami lietotājiem, kuri nav pieteikušies.", + "block_modal.remote_users_caveat": "Mēs vaicāsim serverim {domain} ņemt vērā Tavu lēmumu. Tomēr atbilstība nav nodrošināta, jo atsevišķi serveri liegšanu var apstrādāt citādi. Publiski ieraksti joprojām var būt redzami lietotājiem, kuri nav pieteikušies.", "block_modal.show_less": "Rādīt mazāk", "block_modal.show_more": "Parādīt mazāk", "block_modal.they_cant_mention": "Nevar Tevi pieminēt vai sekot Tev.", - "block_modal.they_cant_see_posts": "Nevar redzēt Tavus ierakstus, un Tu neredzēsi lietotāja.", + "block_modal.they_cant_see_posts": "Lietotajs nevarēs redzēt Tavus ierakstus, un Tu neredzēsi lietotāja.", "block_modal.title": "Bloķēt lietotāju?", + "block_modal.you_wont_see_mentions": "Tu neredzēsi ierakstus, kuros ir minēts šis lietotājs.", "boost_modal.combo": "Nospied {combo}, lai nākamreiz šo izlaistu", "boost_modal.reblog": "Pastiprināt ierakstu?", "boost_modal.undo_reblog": "Atcelt ieraksta pastiprināšanu?", - "bundle_column_error.copy_stacktrace": "Kopēt kļūdu ziņojumu", + "bundle_column_error.copy_stacktrace": "Ievietot kļūdu ziņojumu starpliktuvē", "bundle_column_error.error.body": "Pieprasīto lapu nevarēja atveidot. Tas varētu būt saistīts ar kļūdu mūsu kodā, vai tā ir pārlūkprogrammas saderības problēma.", "bundle_column_error.error.title": "Ak vai!", "bundle_column_error.network.body": "Mēģinot ielādēt šo lapu, radās kļūda. Tas varētu būt saistīts ar īslaicīgu interneta savienojuma vai šī servera problēmu.", @@ -167,9 +174,9 @@ "community.column_settings.remote_only": "Tikai attālinātie", "compose.language.change": "Mainīt valodu", "compose.language.search": "Meklēt valodas...", - "compose.published.body": "Ieraksts izveidots.", + "compose.published.body": "Ieraksts pievienots.", "compose.published.open": "Atvērt", - "compose.saved.body": "Ziņa saglabāta.", + "compose.saved.body": "Ieraksts saglabāts.", "compose_form.direct_message_warning_learn_more": "Uzzināt vairāk", "compose_form.encryption_warning": "Mastodon ieraksti nav pilnībā šifrēti. Nedalies ar jebkādu jūtīgu informāciju caur Mastodon!", "compose_form.hashtag_warning": "Šis ieraksts netiks uzrādīts nevienā tēmturī, jo tas nav redzams visiem. Tikai visiem redzamos ierakstus var meklēt pēc tēmtura.", @@ -193,7 +200,7 @@ "confirmation_modal.cancel": "Atcelt", "confirmations.block.confirm": "Bloķēt", "confirmations.delete.confirm": "Dzēst", - "confirmations.delete.message": "Vai tiešām vēlies dzēst šo ierakstu?", + "confirmations.delete.message": "Vai tiešām izdzēst šo ierakstu?", "confirmations.delete.title": "Izdzēst ierakstu?", "confirmations.delete_list.confirm": "Dzēst", "confirmations.delete_list.message": "Vai tiešām neatgriezeniski izdzēst šo sarakstu?", @@ -206,14 +213,15 @@ "confirmations.follow_to_list.confirm": "Sekot un pievienot sarakstam", "confirmations.follow_to_list.message": "Ir jāseko {name}, lai pievienotu sarakstam.", "confirmations.follow_to_list.title": "Sekot lietotājam?", - "confirmations.logout.confirm": "Iziet", - "confirmations.logout.message": "Vai tiešām vēlies izrakstīties?", + "confirmations.logout.confirm": "Atteikties", + "confirmations.logout.message": "Vai tiešām atteikties?", "confirmations.logout.title": "Atteikties?", + "confirmations.missing_alt_text.message": "Tavs ieraksts satur informācijas nesējus bez paskaidrojošā teksta. Aprakstu pievienošana palīdz padarīt saturu pieejamāku vairāk cilvēku.", "confirmations.missing_alt_text.secondary": "Vienalga iesūtīt", "confirmations.mute.confirm": "Apklusināt", "confirmations.redraft.confirm": "Dzēst un pārrakstīt", "confirmations.redraft.message": "Vai tiešām vēlies izdzēst šo ierakstu un veidot jaunu tā uzmetumu? Pievienošana izlasēs un pastiprinājumi tiks zaudēti, un sākotnējā ieraksta atbildes paliks bez saiknes ar to.", - "confirmations.redraft.title": "Dzēst un rakstīt vēlreiz?", + "confirmations.redraft.title": "Izdzēst un rakstīt ierakstu no jauna?", "confirmations.remove_from_followers.confirm": "Dzēst sekotāju", "confirmations.remove_from_followers.message": "{name} pārstās sekot jums. Vai tiešām vēlaties turpināt?", "confirmations.remove_from_followers.title": "Vai dzēst sekotāju?", @@ -241,14 +249,23 @@ "disabled_account_banner.text": "Tavs konts {disabledAccount} pašlaik ir atspējots.", "dismissable_banner.community_timeline": "Šie ir jaunākie publiskie ieraksti no cilvēkiem, kuru konti ir mitināti {domain}.", "dismissable_banner.dismiss": "Atcelt", + "dismissable_banner.explore_links": "Šie jaunumi šodien Fediversā tiek visvairāk kopīgoti. Jaunākas ziņas, kuras pievienoši vairāki dažādi cilvēki, tiek novietotas augstāk.", + "dismissable_banner.public_timeline": "Šie ir jaunākie Fediverse lietotāju publiskie ieraksti, kuriem {domain} seko cilvēki.", "domain_block_modal.block": "Bloķēt serveri", "domain_block_modal.block_account_instead": "Tā vietā liegt @{name}", "domain_block_modal.they_cant_follow": "Neviens šajā serverī nevar Tev sekot.", "domain_block_modal.they_wont_know": "Viņi nezinās, ka tikuši bloķēti.", "domain_block_modal.title": "Bloķēt domēnu?", + "domain_pill.activitypub_lets_connect": "Tas ļauj savienoties un mijiedarboties ar cilvēkiem ne tikai no Mastodon, bet arī starp dažādām sabiedriskajām lietotnēm.", + "domain_pill.activitypub_like_language": "ActivityPub ir kā valoda, kurā Mastodon sazināš ar citiem sabiedriskajiem tīkliem.", "domain_pill.server": "Serveris", + "domain_pill.their_handle": "Turis:", "domain_pill.username": "Lietotājvārds", - "embed.instructions": "Iestrādā šo ziņu savā mājaslapā, kopējot zemāk redzamo kodu.", + "domain_pill.whats_in_a_handle": "Kas ir turī?", + "domain_pill.who_they_are": "Tā kā turi norāda, kas kāds ir un kur viņi ir atrodami, Tu vari mijiedarboties ar cilvēkiem viscaur sabiedriskajā tīklā no .", + "domain_pill.who_you_are": "Tā kā Tavs turis norāda, kas Tu esi un kur atrodies, cilvēki var mijiedarboties ar Tevi viscaur sabiedriskajā tīklā no .", + "domain_pill.your_handle": "Tavs turis:", + "embed.instructions": "Iekļauj šo ierakstu savā tīmekļvietnē, ievietojot zemāk redzamo kodu starpliktuvē!", "embed.preview": "Tas izskatīsies šādi:", "emoji_button.activity": "Aktivitāte", "emoji_button.clear": "Notīrīt", @@ -267,20 +284,20 @@ "emoji_button.travel": "Ceļošana un vietas", "empty_column.account_hides_collections": "Šis lietotājs ir izvēlējies nedarīt šo informāciju pieejamu", "empty_column.account_suspended": "Konta darbība ir apturēta", - "empty_column.account_timeline": "Šeit ziņojumu nav!", + "empty_column.account_timeline": "Šeit nav ierakstu.", "empty_column.account_unavailable": "Profils nav pieejams", "empty_column.blocks": "Pašreiz tu neesi nevienu bloķējis.", "empty_column.bookmarked_statuses": "Pašlaik Tev nav neviena grāmatzīmēs pievienota ieraksta. Kad tādu pievienosi, tas parādīsies šeit.", - "empty_column.community": "Vietējā laika līnija ir tukša. Uzraksti kaut ko publiski, lai viss notiktu!", + "empty_column.community": "Vietējā laika līnija ir tukša. Uzraksti kaut ko publiski, lai iekustinātu visu!", "empty_column.direct": "Tev vēl nav privātu pieminēšanu. Kad Tu nosūtīsi vai saņemsi kādu, tā pārādīsies šeit.", "empty_column.domain_blocks": "Vēl nav neviena bloķēta domēna.", "empty_column.explore_statuses": "Pašlaik nav nekā aktuāla. Ieskaties šeit vēlāk!", - "empty_column.favourited_statuses": "Tev vēl nav iecienītāko ierakstu. Kad pievienosi kādu izlasei, tas tiks parādīts šeit.", - "empty_column.favourites": "Šo ziņu neviens vēl nav pievienojis izlasei. Kad kāds to izdarīs, tas parādīsies šeit.", + "empty_column.favourited_statuses": "Tev vēl nav izlasei pievienotu ierakstu. Kad pievienosi kādu, tas tiks parādīts šeit.", + "empty_column.favourites": "Šo ierakstu vēl neviens nav pievienojis izlasei. Kad kāds to izdarīs, šeit parādīsies ieraksti.", "empty_column.follow_requests": "Šobrīd Tev nav sekošanas pieprasījumu. Kad saņemsi kādu, tas parādīsies šeit.", "empty_column.followed_tags": "Tu vēl neseko nevienam tēmturim. Kad to izdarīsi, tie tiks parādīti šeit.", "empty_column.hashtag": "Ar šo tēmturi nekas nav atrodams.", - "empty_column.home": "Tava mājas laikjosla ir tukša. Seko vairāk cilvēkiem, lai to piepildītu!", + "empty_column.home": "Tava mājas laika līnija ir tukša. Seko vairāk cilvēkiem, lai to piepildītu!", "empty_column.list": "Pagaidām šajā sarakstā nekā nav. Kad šī saraksta dalībnieki ievietos jaunus ierakstus, tie parādīsies šeit.", "empty_column.mutes": "Neviens lietotājs vēl nav apklusināts.", "empty_column.notifications": "Tev vēl nav paziņojumu. Kad citi cilvēki ar Tevi mijiedarbosies, Tu to redzēsi šeit.", @@ -303,15 +320,15 @@ "filter_modal.added.review_and_configure": "Lai pārskatītu un tālāk konfigurētu šo filtru kategoriju, dodies uz {settings_link}.", "filter_modal.added.review_and_configure_title": "Filtra iestatījumi", "filter_modal.added.settings_link": "iestatījumu lapu", - "filter_modal.added.short_explanation": "Šī ziņa ir pievienota šai filtra kategorijai: {title}.", + "filter_modal.added.short_explanation": "Šis ieraksts tika pievienots šai atlasīšanas kategorijai: {title}.", "filter_modal.added.title": "Filtrs pievienots!", "filter_modal.select_filter.context_mismatch": "neattiecas uz šo kontekstu", "filter_modal.select_filter.expired": "beidzies", "filter_modal.select_filter.prompt_new": "Jauna kategorija: {name}", "filter_modal.select_filter.search": "Meklēt vai izveidot", "filter_modal.select_filter.subtitle": "Izmanto esošu kategoriju vai izveido jaunu", - "filter_modal.select_filter.title": "Filtrēt šo ziņu", - "filter_modal.title.status": "Filtrēt ziņu", + "filter_modal.select_filter.title": "Atlasīt šo ierakstu", + "filter_modal.title.status": "Atlasīt ziņu", "filtered_notifications_banner.title": "Filtrētie paziņojumi", "firehose.all": "Visi", "firehose.local": "Šis serveris", @@ -368,12 +385,21 @@ "home.pending_critical_update.title": "Ir pieejams būtisks drošības atjauninājums.", "home.show_announcements": "Rādīt paziņojumus", "ignore_notifications_modal.ignore": "Neņemt vērā paziņojumus", + "ignore_notifications_modal.not_following_title": "Neņemt vērā paziņojumus no cilvēkiem, kuriem neseko?", + "interaction_modal.action.favourite": "Lai turpinātu, nepieciešams pievienot sava konta izlasei.", + "interaction_modal.action.follow": "Lai turpinātu, nepieciešams sekot no sava konta.", + "interaction_modal.action.reblog": "Lai turpinātu, nepieciešams pastiprināt no sava konta.", + "interaction_modal.action.reply": "Lai turpinātu, nepieciešams atbildēt no sava konta.", + "interaction_modal.action.vote": "Lai turpinātu, nepieciešams balsot no sava konta.", + "interaction_modal.go": "Aiziet", + "interaction_modal.no_account_yet": "Vēl nav konta?", "interaction_modal.on_another_server": "Citā serverī", "interaction_modal.on_this_server": "Šajā serverī", - "interaction_modal.title.favourite": "Pievienot {name} ziņu izlasei", + "interaction_modal.title.favourite": "Pievienot {name} ierakstu izlasei", "interaction_modal.title.follow": "Sekot {name}", "interaction_modal.title.reblog": "Pastiprināt {name} ierakstu", - "interaction_modal.title.reply": "Atbildēt uz {name} ziņu", + "interaction_modal.title.reply": "Atbildēt uz {name} ierakstu", + "interaction_modal.username_prompt": "Piem., {example}", "intervals.full.days": "{number, plural, one {# diena} other {# dienas}}", "intervals.full.hours": "{number, plural, one {# stunda} other {# stundas}}", "intervals.full.minutes": "{number, plural, one {# minūte} other {# minūtes}}", @@ -385,8 +411,8 @@ "keyboard_shortcuts.description": "Apraksts", "keyboard_shortcuts.direct": "lai atvērtu privāto pieminējumu sleju", "keyboard_shortcuts.down": "Pārvietoties lejup sarakstā", - "keyboard_shortcuts.enter": "Atvērt ziņu", - "keyboard_shortcuts.favourite": "Pievienot izlasei", + "keyboard_shortcuts.enter": "Atvērt ierakstu", + "keyboard_shortcuts.favourite": "Pievienot ierakstu izlasei", "keyboard_shortcuts.favourites": "Atvērt izlašu sarakstu", "keyboard_shortcuts.federated": "Atvērt apvienoto laika līniju", "keyboard_shortcuts.heading": "Īsinājumtaustiņi", @@ -399,7 +425,7 @@ "keyboard_shortcuts.my_profile": "Atvērt savu profilu", "keyboard_shortcuts.notifications": "Atvērt paziņojumu kolonnu", "keyboard_shortcuts.open_media": "Atvērt multividi", - "keyboard_shortcuts.pinned": "Atvērt piesprausto ziņu sarakstu", + "keyboard_shortcuts.pinned": "Atvērt piesprausto ierakstu sarakstu", "keyboard_shortcuts.profile": "Atvērt autora profilu", "keyboard_shortcuts.reply": "Atbildēt", "keyboard_shortcuts.requests": "Atvērt sekošanas pieprasījumu sarakstu", @@ -408,7 +434,7 @@ "keyboard_shortcuts.start": "Atvērt kolonnu “Darba sākšana”", "keyboard_shortcuts.toggle_hidden": "Rādīt/slēpt tekstu aiz satura brīdinājuma", "keyboard_shortcuts.toggle_sensitivity": "Rādīt/slēpt multividi", - "keyboard_shortcuts.toot": "Sākt jaunu ziņu", + "keyboard_shortcuts.toot": "Uzsākt jaunu ierakstu", "keyboard_shortcuts.unfocus": "Atfokusēt veidojamā teksta/meklēšanas lauku", "keyboard_shortcuts.up": "Pārvietoties augšup sarakstā", "lightbox.close": "Aizvērt", @@ -444,7 +470,7 @@ "navigation_bar.blocks": "Bloķētie lietotāji", "navigation_bar.bookmarks": "Grāmatzīmes", "navigation_bar.community_timeline": "Vietējā laika līnija", - "navigation_bar.compose": "Veidot jaunu ziņu", + "navigation_bar.compose": "Izveidot jaunu ierakstu", "navigation_bar.direct": "Privātas pieminēšanas", "navigation_bar.discover": "Atklāt", "navigation_bar.domain_blocks": "Bloķētie domēni", @@ -460,15 +486,17 @@ "navigation_bar.mutes": "Apklusinātie lietotāji", "navigation_bar.opened_in_classic_interface": "Ieraksti, konti un citas noteiktas lapas pēc noklusējuma tiek atvērtas klasiskajā tīmekļa saskarnē.", "navigation_bar.personal": "Personīgie", - "navigation_bar.pins": "Piespraustās ziņas", + "navigation_bar.pins": "Piespraustie ieraksti", "navigation_bar.preferences": "Iestatījumi", "navigation_bar.public_timeline": "Apvienotā laika līnija", "navigation_bar.search": "Meklēt", "navigation_bar.security": "Drošība", "not_signed_in_indicator.not_signed_in": "Ir jāpiesakās, lai piekļūtu šim resursam.", "notification.admin.report": "{name} ziņoja par {target}", + "notification.admin.report_account": "{name} ziņoja par {count, plural, one {# ierakstu} other {# ierakstiem}} no {target} ar iemeslu: {category}", + "notification.admin.report_statuses": "{name} ziņoja par {target} ar iemeslu: {category}", "notification.admin.sign_up": "{name} pierakstījās", - "notification.favourite": "{name} pievienoja tavu ziņu izlasei", + "notification.favourite": "{name} pievienoja izlasei Tavu ierakstu", "notification.follow": "{name} uzsāka Tev sekot", "notification.follow_request": "{name} nosūtīja Tev sekošanas pieprasījumu", "notification.moderation-warning.learn_more": "Uzzināt vairāk", @@ -484,7 +512,7 @@ "notification.reblog": "{name} pastiprināja Tavu ierakstu", "notification.relationships_severance_event": "Zaudēti savienojumi ar {name}", "notification.relationships_severance_event.learn_more": "Uzzināt vairāk", - "notification.status": "{name} tikko publicēja", + "notification.status": "{name} tikko pievienoja ierakstu", "notification.update": "{name} laboja ierakstu", "notification_requests.accept": "Pieņemt", "notification_requests.dismiss": "Noraidīt", @@ -586,15 +614,15 @@ "reply_indicator.cancel": "Atcelt", "reply_indicator.poll": "Aptauja", "report.block": "Bloķēt", - "report.block_explanation": "Tu neredzēsi viņu ierakstus. Viņi nevarēs redzēt Tavus ierakstus vai sekot tev. Viņi varēs saprast, ka ir bloķēti.", + "report.block_explanation": "Tu neredzēsi viņu ierakstus. Viņi nevarēs redzēt Tavus ierakstus vai sekot tev. Viņi varēs saprast, ka ir liegti.", "report.categories.legal": "Tiesisks", "report.categories.other": "Citi", - "report.categories.spam": "Spams", + "report.categories.spam": "Mēstule", "report.categories.violation": "Saturs pārkāpj vienu vai vairākus servera noteikumus", "report.category.subtitle": "Izvēlieties labāko atbilstību", "report.category.title": "Pastāsti mums, kas notiek ar šo {type}", "report.category.title_account": "profilu", - "report.category.title_status": "ziņu", + "report.category.title_status": "ierakstu", "report.close": "Darīts", "report.comment.title": "Vai, tavuprāt, mums vēl būtu kas jāzina?", "report.forward": "Pārsūtīt {target}", @@ -609,7 +637,7 @@ "report.reasons.legal_description": "Tu uzskati, ka tas pārkāpj tavus vai servera valsts likumus", "report.reasons.other": "Tas ir kaut kas cits", "report.reasons.other_description": "Šī sūdzība neatbilst pārējām kategorijām", - "report.reasons.spam": "Tas ir spams", + "report.reasons.spam": "Tā ir mēstule", "report.reasons.spam_description": "Ļaunprātīgas saites, viltus iesaistīšana vai atkārtotas atbildes", "report.reasons.violation": "Tas pārkāpj servera noteikumus", "report.reasons.violation_description": "Tu zini, ka tas pārkāpj īpašus noteikumus", @@ -621,15 +649,19 @@ "report.target": "Ziņošana par: {target}", "report.thanks.take_action": "Šeit ir iespējas, lai pārvaldītu Mastodon redzamo saturu:", "report.thanks.take_action_actionable": "Kamēr mēs to izskatām, tu vari veikt darbības pret @{name}:", - "report.thanks.title": "Vai nevēlies to redzēt?", + "report.thanks.title": "Nevēlies to redzēt?", "report.thanks.title_actionable": "Paldies, ka ziņoji, mēs to izskatīsim.", "report.unfollow": "Pārtraukt sekot @{name}", "report.unfollow_explanation": "Tu seko šim kontam. Lai vairs neredzētu tā ierakstus savā mājas plūsmā, pārtrauc sekot tam!", - "report_notification.attached_statuses": "Pievienoti {count, plural,one {{count} sūtījums} other {{count} sūtījumi}}", + "report_notification.attached_statuses": "{count, plural, zero {Pievienoti {count} ierakstu} one {Pievienots {count} ieraksts} other {Pievienoti {count} ieraksti}}", "report_notification.categories.legal": "Tiesisks", + "report_notification.categories.legal_sentence": "nelikumīgs saturs", "report_notification.categories.other": "Cita", - "report_notification.categories.spam": "Spams", + "report_notification.categories.other_sentence": "cits", + "report_notification.categories.spam": "Mēstule", + "report_notification.categories.spam_sentence": "mēstule", "report_notification.categories.violation": "Noteikumu pārkāpums", + "report_notification.categories.violation_sentence": "noteikumu pārkāpums", "report_notification.open": "Atvērt ziņojumu", "search.no_recent_searches": "Nav nesen veiktu meklējumu", "search.placeholder": "Meklēšana", @@ -657,6 +689,7 @@ "server_banner.administered_by": "Pārvalda:", "server_banner.server_stats": "Servera statistika:", "sign_in_banner.create_account": "Izveidot kontu", + "sign_in_banner.follow_anyone": "Seko ikvienam Fediversā un redzi visu pievienošanas secībā! Nekādu algoritmu, reklāmu vai klikšķēsmu.", "sign_in_banner.sign_in": "Pieteikties", "sign_in_banner.sso_redirect": "Piesakies vai Reģistrējies", "status.admin_account": "Atvērt @{name} satura pārraudzības saskarni", @@ -665,7 +698,7 @@ "status.block": "Bloķēt @{name}", "status.bookmark": "Grāmatzīme", "status.cancel_reblog_private": "Nepastiprināt", - "status.cannot_reblog": "Šo ziņu nevar izcelt", + "status.cannot_reblog": "Šo ierakstu nevar pastiprināt", "status.continued_thread": "Turpināts pavediens", "status.copy": "Ievietot ieraksta saiti starpliktuvē", "status.delete": "Dzēst", @@ -676,8 +709,8 @@ "status.edited": "Pēdējoreiz labots {date}", "status.edited_x_times": "Labots {count, plural, zero {{count} reižu} one {{count} reizi} other {{count} reizes}}", "status.favourite": "Izlasē", - "status.favourites": "{count, plural, zero {izlasēs} one {izlasē} other {izlasēs}}", - "status.filter": "Filtrē šo ziņu", + "status.favourites": "{count, plural, one {izlasē} other {izlasēs}}", + "status.filter": "Atlasīt šo ierakstu", "status.history.created": "{name} izveidoja {date}", "status.history.edited": "{name} laboja {date}", "status.load_more": "Ielādēt vairāk", @@ -688,7 +721,7 @@ "status.more": "Vairāk", "status.mute": "Apklusināt @{name}", "status.mute_conversation": "Apklusināt sarunu", - "status.open": "Paplašināt šo ziņu", + "status.open": "Izvērst šo ierakstu", "status.pin": "Piespraust profilam", "status.pinned": "Piesprausts ieraksts", "status.read_more": "Lasīt vairāk", @@ -696,7 +729,7 @@ "status.reblog_private": "Pastiprināt ar sākotnējo redzamību", "status.reblogged_by": "{name} pastiprināja", "status.reblogs": "{count, plural, zero {pastiprinājumu} one {pastiprinājums} other {pastiprinājumi}}", - "status.reblogs.empty": "Neviens šo ierakstu vēl nav pastiprinājis. Kad būs, tie parādīsies šeit.", + "status.reblogs.empty": "Neviens vēl nav pastiprinājis šo ierakstu. Kad kāds to izdarīs, šeit tiks parādīti lietotāji.", "status.redraft": "Dzēst un pārrakstīt", "status.remove_bookmark": "Noņemt grāmatzīmi", "status.replied_to": "Atbildēja {name}", @@ -708,13 +741,13 @@ "status.show_less_all": "Rādīt mazāk visiem", "status.show_more_all": "Rādīt vairāk visiem", "status.show_original": "Rādīt pirmavotu", - "status.title.with_attachments": "{user} publicējis {attachmentCount, plural, one {pielikumu} other {{attachmentCount} pielikumus}}", + "status.title.with_attachments": "{user} pievienoja {attachmentCount, plural, zero {{attachmentCount} pielikumu} one {{attachmentCount} pielikumu} other {{attachmentCount} pielikumus}}", "status.translate": "Tulkot", "status.translated_from_with": "Tulkots no {lang} izmantojot {provider}", "status.uncached_media_warning": "Priekšskatījums nav pieejams", "status.unmute_conversation": "Noņemt sarunas apklusinājumu", "status.unpin": "Noņemt profila piespraudumu", - "subscribed_languages.lead": "Pēc izmaiņu veikšanas Tavā mājas un sarakstu laika līnijā tiks rādīti tikai tie ieraksti atlasītajās valodās. Neatlasīt nevienu, lai saņemtu ierakstus visās valodās.", + "subscribed_languages.lead": "Pēc izmaiņu veikšanas Tavā mājas un sarakstu laika līnijā tiks rādīti tikai ieraksti atlasītajās valodās. Neatlasīt nevienu, lai saņemtu ierakstus visās valodās.", "subscribed_languages.save": "Saglabāt izmaiņas", "subscribed_languages.target": "Mainīt abonētās valodas priekš {target}", "tabs_bar.home": "Sākums", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 8274755bb4..eaa3bcec64 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -98,8 +98,8 @@ "alt_text_modal.add_text_from_image": "Добавить текст из изображения", "alt_text_modal.cancel": "Отмена", "alt_text_modal.change_thumbnail": "Изменить обложку", - "alt_text_modal.describe_for_people_with_hearing_impairments": "Опишите то, что слышите, для людей с нарушениями слуха…", - "alt_text_modal.describe_for_people_with_visual_impairments": "Опишите то, что видите, для людей с нарушениями зрения…", + "alt_text_modal.describe_for_people_with_hearing_impairments": "Добавьте описание для людей с нарушениями слуха…", + "alt_text_modal.describe_for_people_with_visual_impairments": "Добавьте описание для людей с нарушениями зрения…", "alt_text_modal.done": "Готово", "announcement.announcement": "Объявление", "annual_report.summary.archetype.booster": "Репостер", @@ -456,36 +456,36 @@ "intervals.full.hours": "{number, plural, one {# час} few {# часа} other {# часов}}", "intervals.full.minutes": "{number, plural, one {# минута} few {# минуты} other {# минут}}", "keyboard_shortcuts.back": "перейти назад", - "keyboard_shortcuts.blocked": "чтобы открыть список заблокированных", + "keyboard_shortcuts.blocked": "открыть список заблокированных", "keyboard_shortcuts.boost": "продвинуть пост", "keyboard_shortcuts.column": "фокус на одном из столбцов", "keyboard_shortcuts.compose": "фокус на поле ввода", "keyboard_shortcuts.description": "Описание", - "keyboard_shortcuts.direct": "чтобы открыть столбец личных упоминаний", + "keyboard_shortcuts.direct": "перейти к личным упоминаниям", "keyboard_shortcuts.down": "вниз по списку", "keyboard_shortcuts.enter": "открыть пост", "keyboard_shortcuts.favourite": "добавить пост в избранное", - "keyboard_shortcuts.favourites": "открыть «Избранные»", + "keyboard_shortcuts.favourites": "перейти к избранным постам", "keyboard_shortcuts.federated": "перейти к глобальной ленте", "keyboard_shortcuts.heading": "Сочетания клавиш", "keyboard_shortcuts.home": "перейти к домашней ленте", - "keyboard_shortcuts.hotkey": "Гор. клавиша", - "keyboard_shortcuts.legend": "показать это окно", + "keyboard_shortcuts.hotkey": "Горячая клавиша", + "keyboard_shortcuts.legend": "показать эту справку", "keyboard_shortcuts.local": "перейти к локальной ленте", "keyboard_shortcuts.mention": "упомянуть автора поста", "keyboard_shortcuts.muted": "открыть список игнорируемых", "keyboard_shortcuts.my_profile": "перейти к своему профилю", "keyboard_shortcuts.notifications": "перейти к уведомлениям", - "keyboard_shortcuts.open_media": "открыть вложение", + "keyboard_shortcuts.open_media": "открыть медиа", "keyboard_shortcuts.pinned": "перейти к закреплённым постам", "keyboard_shortcuts.profile": "перейти к профилю автора", "keyboard_shortcuts.reply": "ответить", "keyboard_shortcuts.requests": "перейти к запросам на подписку", "keyboard_shortcuts.search": "перейти к поиску", "keyboard_shortcuts.spoilers": "показать/скрыть поле предупреждения о содержании", - "keyboard_shortcuts.start": "перейти к разделу \"добро пожаловать\"", + "keyboard_shortcuts.start": "перейти к разделу «Добро пожаловать»", "keyboard_shortcuts.toggle_hidden": "показать/скрыть текст за предупреждением", - "keyboard_shortcuts.toggle_sensitivity": "показать/скрыть медиафайлы", + "keyboard_shortcuts.toggle_sensitivity": "показать/скрыть медиа", "keyboard_shortcuts.toot": "начать писать новый пост", "keyboard_shortcuts.translate": "перевести пост", "keyboard_shortcuts.unfocus": "убрать фокус с поля ввода/поиска", diff --git a/app/lib/admin/system_check/elasticsearch_check.rb b/app/lib/admin/system_check/elasticsearch_check.rb index ea35807f30..3950756e6a 100644 --- a/app/lib/admin/system_check/elasticsearch_check.rb +++ b/app/lib/admin/system_check/elasticsearch_check.rb @@ -38,6 +38,11 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck :elasticsearch_index_mismatch, mismatched_indexes.join(' ') ) + elsif !specifications_match? + Admin::SystemCheck::Message.new( + :elasticsearch_analysis_mismatch, + mismatched_specifications_indexes.join(' ') + ) elsif cluster_health['status'] == 'red' Admin::SystemCheck::Message.new(:elasticsearch_health_red) elsif cluster_health['number_of_nodes'] < 2 && es_preset != 'single_node_cluster' @@ -111,10 +116,20 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck end end + def mismatched_specifications_indexes + @mismatched_specifications_indexes ||= INDEXES.filter_map do |klass| + klass.base_name if klass.specification.changed? + end + end + def indexes_match? mismatched_indexes.empty? end + def specifications_match? + mismatched_specifications_indexes.empty? + end + def es_preset ENV.fetch('ES_PRESET', 'single_node_cluster') end diff --git a/app/models/featured_tag.rb b/app/models/featured_tag.rb index dfc700649c..74fc72ba5c 100644 --- a/app/models/featured_tag.rb +++ b/app/models/featured_tag.rb @@ -18,17 +18,17 @@ class FeaturedTag < ApplicationRecord belongs_to :account, inverse_of: :featured_tags belongs_to :tag, inverse_of: :featured_tags, optional: true # Set after validation - validates :name, presence: true, format: { with: Tag::HASHTAG_NAME_RE }, on: :create + validates :name, presence: true, on: :create, if: -> { tag_id.nil? } + validates :name, format: { with: Tag::HASHTAG_NAME_RE }, on: :create, allow_blank: true + validates :tag_id, uniqueness: { scope: :account_id } - validate :validate_tag_uniqueness, on: :create validate :validate_featured_tags_limit, on: :create normalizes :name, with: ->(name) { name.strip.delete_prefix('#') } - before_create :set_tag - before_create :reset_data + before_validation :set_tag - scope :by_name, ->(name) { joins(:tag).where(tag: { name: HashtagNormalizer.new.normalize(name) }) } + before_create :reset_data LIMIT = 10 @@ -59,7 +59,11 @@ class FeaturedTag < ApplicationRecord private def set_tag - self.tag = Tag.find_or_create_by_names(name)&.first + if tag.nil? + self.tag = Tag.find_or_create_by_names(name)&.first + elsif tag&.new_record? + tag.save + end end def reset_data @@ -73,14 +77,6 @@ class FeaturedTag < ApplicationRecord errors.add(:base, I18n.t('featured_tags.errors.limit')) if account.featured_tags.count >= LIMIT end - def validate_tag_uniqueness - errors.add(:name, :taken) if tag_already_featured_for_account? - end - - def tag_already_featured_for_account? - FeaturedTag.by_name(name).exists?(account_id: account_id) - end - def visible_tagged_account_statuses account.statuses.distributable_visibility.tagged_with(tag) end diff --git a/app/presenters/tag_relationships_presenter.rb b/app/presenters/tag_relationships_presenter.rb index 52e24314be..922eb7a39b 100644 --- a/app/presenters/tag_relationships_presenter.rb +++ b/app/presenters/tag_relationships_presenter.rb @@ -1,13 +1,15 @@ # frozen_string_literal: true class TagRelationshipsPresenter - attr_reader :following_map + attr_reader :following_map, :featuring_map def initialize(tags, current_account_id = nil, **options) - @following_map = if current_account_id.nil? - {} - else - TagFollow.select(:tag_id).where(tag_id: tags.map(&:id), account_id: current_account_id).each_with_object({}) { |f, h| h[f.tag_id] = true }.merge(options[:following_map] || {}) - end + if current_account_id.nil? + @following_map = {} + @featuring_map = {} + else + @following_map = TagFollow.select(:tag_id).where(tag_id: tags.map(&:id), account_id: current_account_id).each_with_object({}) { |f, h| h[f.tag_id] = true }.merge(options[:following_map] || {}) + @featuring_map = FeaturedTag.select(:tag_id).where(tag_id: tags.map(&:id), account_id: current_account_id).each_with_object({}) { |f, h| h[f.tag_id] = true }.merge(options[:featuring_map] || {}) + end end end diff --git a/app/serializers/oembed_serializer.rb b/app/serializers/oembed_serializer.rb index c87f14f26b..077c47d027 100644 --- a/app/serializers/oembed_serializer.rb +++ b/app/serializers/oembed_serializer.rb @@ -75,7 +75,7 @@ class OEmbedSerializer < ActiveModel::Serializer <<~HTML.squish
- +
Post by @#{object.account.pretty_acct}@#{provider_name}
View on Mastodon
diff --git a/app/serializers/rest/tag_serializer.rb b/app/serializers/rest/tag_serializer.rb index a2bcb5fd1f..f41a1513db 100644 --- a/app/serializers/rest/tag_serializer.rb +++ b/app/serializers/rest/tag_serializer.rb @@ -6,6 +6,7 @@ class REST::TagSerializer < ActiveModel::Serializer attributes :id, :name, :url, :history attribute :following, if: :current_user? + attribute :featuring, if: :current_user? def id object.id.to_s @@ -27,6 +28,14 @@ class REST::TagSerializer < ActiveModel::Serializer end end + def featuring + if instance_options && instance_options[:relationships] + instance_options[:relationships].featuring_map[object.id] || false + else + FeaturedTag.exists?(tag_id: object.id, account_id: current_user.account_id) + end + end + def current_user? !current_user.nil? end diff --git a/app/services/account_search_service.rb b/app/services/account_search_service.rb index 8fa2bc14ea..d63ba621bc 100644 --- a/app/services/account_search_service.rb +++ b/app/services/account_search_service.rb @@ -142,11 +142,37 @@ class AccountSearchService < BaseService def core_query { - multi_match: { - query: @query, - type: 'best_fields', - fields: %w(username^2 display_name^2 text text.*), - operator: 'and', + dis_max: { + queries: [ + { + match: { + username: { + query: @query, + analyzer: 'word_join_analyzer', + }, + }, + }, + + { + match: { + display_name: { + query: @query, + analyzer: 'word_join_analyzer', + }, + }, + }, + + { + multi_match: { + query: @query, + type: 'best_fields', + fields: %w(text text.*), + operator: 'and', + }, + }, + ], + + tie_breaker: 0.5, }, } end diff --git a/app/services/create_featured_tag_service.rb b/app/services/create_featured_tag_service.rb index 3cc59156db..13d6ac0201 100644 --- a/app/services/create_featured_tag_service.rb +++ b/app/services/create_featured_tag_service.rb @@ -3,18 +3,24 @@ class CreateFeaturedTagService < BaseService include Payloadable - def call(account, name, force: true) + def call(account, name_or_tag, raise_error: true) + raise ArgumentError unless account.local? + @account = account - FeaturedTag.create!(account: account, name: name).tap do |featured_tag| - ActivityPub::AccountRawDistributionWorker.perform_async(build_json(featured_tag), account.id) if @account.local? - end - rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid => e - if force && e.is_a(ActiveRecord::RecordNotUnique) - FeaturedTag.by_name(name).find_by!(account: account) - else - account.featured_tags.new(name: name) + @featured_tag = begin + if name_or_tag.is_a?(Tag) + account.featured_tags.find_or_initialize_by(tag: name_or_tag) + else + account.featured_tags.find_or_initialize_by(name: name_or_tag) + end end + + create_method = raise_error ? :save! : :save + + ActivityPub::AccountRawDistributionWorker.perform_async(build_json(@featured_tag), @account.id) if @featured_tag.new_record? && @featured_tag.public_send(create_method) + + @featured_tag end private diff --git a/app/services/remove_featured_tag_service.rb b/app/services/remove_featured_tag_service.rb index 2aa70e8fc6..af8c5a64ee 100644 --- a/app/services/remove_featured_tag_service.rb +++ b/app/services/remove_featured_tag_service.rb @@ -3,11 +3,24 @@ class RemoveFeaturedTagService < BaseService include Payloadable - def call(account, featured_tag) + def call(account, featured_tag_or_tag) + raise ArgumentError unless account.local? + @account = account - featured_tag.destroy! - ActivityPub::AccountRawDistributionWorker.perform_async(build_json(featured_tag), account.id) if @account.local? + @featured_tag = begin + if featured_tag_or_tag.is_a?(FeaturedTag) + featured_tag_or_tag + elsif featured_tag_or_tag.is_a?(Tag) + FeaturedTag.find_by(account: account, tag: featured_tag_or_tag) + end + end + + return if @featured_tag.nil? + + @featured_tag.destroy! + + ActivityPub::AccountRawDistributionWorker.perform_async(build_json(@featured_tag), account.id) if @account.local? end private diff --git a/config/elasticsearch.default-ja-sudachi.yml b/config/elasticsearch.default-ja-sudachi.yml index ad3dc287c7..4387d553eb 100644 --- a/config/elasticsearch.default-ja-sudachi.yml +++ b/config/elasticsearch.default-ja-sudachi.yml @@ -1,7 +1,7 @@ # This is a configuration file for environments that use Japanese and Sudachi plug-ins. # To use this file, copy it to the Mastodon root directory and rename the file to ".elasticsearch.yml". -version: 1 +version: 2 accounts: filter: @@ -14,6 +14,10 @@ accounts: english_possessive_stemmer: type: stemmer language: possessive_english + word_joiner: + type: shingle + output_unigrams: true + token_separator: '' my_posfilter: type: sudachi_part_of_speech stoptags: @@ -45,6 +49,14 @@ accounts: - lowercase - asciifolding - cjk_width + word_join_analyzer: + type: custom + tokenizer: standard + filter: + - lowercase + - asciifolding + - cjk_width + - word_joiner edge_ngram: tokenizer: edge_ngram filter: diff --git a/config/elasticsearch.default.yml b/config/elasticsearch.default.yml index 149881ac50..641ec83132 100644 --- a/config/elasticsearch.default.yml +++ b/config/elasticsearch.default.yml @@ -1,7 +1,7 @@ # The standard ElasticSearch settings described in the original Mastodon code are stored. # This configuration file is overridden by creating a ".elasticsearch.yml" file in the Mastodon root directory. -version: 1 +version: 2 accounts: filter: @@ -14,6 +14,10 @@ accounts: english_possessive_stemmer: type: stemmer language: possessive_english + word_joiner: + type: shingle + output_unigrams: true + token_separator: '' analyzer: natural: @@ -32,6 +36,14 @@ accounts: - lowercase - asciifolding - cjk_width + word_join_analyzer: + type: custom + tokenizer: standard + filter: + - lowercase + - asciifolding + - cjk_width + - word_joiner edge_ngram: tokenizer: edge_ngram filter: diff --git a/config/locales/en.yml b/config/locales/en.yml index fa0a93793b..111c999f92 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1167,6 +1167,8 @@ en: system_checks: database_schema_check: message_html: There are pending database migrations. Please run them to ensure the application behaves as expected + elasticsearch_analysis_index_mismatch: + message_html: Elasticsearch index analyzer settings are outdated. Please run tootctl search deploy --only-mapping --only=%{value} elasticsearch_health_red: message_html: Elasticsearch cluster is unhealthy (red status), search features are unavailable elasticsearch_health_yellow: diff --git a/config/locales/ru.yml b/config/locales/ru.yml index dca4fff60c..d6ed3f917c 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -325,6 +325,7 @@ ru: create: Создать объявление title: Новое объявление preview: + disclaimer: Так как пользователи не могут отказаться от получения уведомлений по электронной почте, их следует использовать только для действительно важных объявлений, например, чтобы сообщить об утечке персональных данных или о закрытии сервера. explanation_html: 'Сообщение будет отравлено %{display_count} пользователям. В теле письма будет указан следующий текст:' title: Предпросмотр объявления по электронной почте publish: Опубликовать @@ -509,6 +510,7 @@ ru: save: Сохранить sign_in: status: Пост + title: FASP follow_recommendations: description_html: "Следуйте рекомендациям, чтобы помочь новым пользователям быстро находить интересный контент. Если пользователь не взаимодействовал с другими в достаточной степени, чтобы сформировать персонализированные рекомендации, вместо этого рекомендуется использовать эти учетные записи. Они пересчитываются на ежедневной основе на основе комбинации аккаунтов с наибольшим количеством недавних взаимодействий и наибольшим количеством местных подписчиков для данного языка." language: Для языка @@ -1620,13 +1622,6 @@ ru: action: Да, отписаться complete: Подписка отменена confirmation_html: Вы точно желаете отписаться от всех уведомления типа «%{type}», доставляемых из сервера Mastodon %{domain} на ваш адрес электронной почты %{email}? Вы всегда сможете подписаться снова в настройках e-mail уведомлений. - emails: - notification_emails: - favourite: любимые электронные письма с уведомлениями - follow: Следить за электронными сообщениями - follow_request: Письма с просьбой о помощи - mention: Упоминание электронных писем с уведомлениями - reblog: Уведомления по электронной почте resubscribe_html: Если вы отписались от рассылки по ошибке, вы можете повторно подписаться на рассылку в настройках настроек почтовых уведомлений. success_html: Вы больше не будете получать %{type} для Mastodon на %{domain} на вашу электронную почту %{email}. title: Отписаться @@ -1710,7 +1705,6 @@ ru: update: subject: "%{name} изменил(а) пост" notifications: - administration_emails: Уведомления администратора по электронной почте email_events: События для уведомлений по электронной почте email_events_hint: 'Выберите события, для которых вы хотели бы получать уведомления:' number: diff --git a/config/routes/api.rb b/config/routes/api.rb index c8233bb01d..3ffc0f4c3d 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -231,6 +231,8 @@ namespace :api, format: false do member do post :follow post :unfollow + post :feature + post :unfeature end end diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index acf7a4e79a..456066c87a 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -96,7 +96,7 @@ module Mastodon def api_versions { - mastodon: 5, + mastodon: 6, kmyblue: KMYBLUE_API_VERSION, } end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 2e7a59db05..cd4181a00d 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -23,7 +23,7 @@ RSpec.describe ApplicationController do end end - shared_examples 'respond_with_error' do |code| + shared_examples 'error response' do |code| it "returns http #{code} for http and renders template" do subject @@ -51,7 +51,7 @@ RSpec.describe ApplicationController do post 'success' end - include_examples 'respond_with_error', 422 + it_behaves_like 'error response', 422 end describe 'helper_method :current_account' do @@ -123,7 +123,7 @@ RSpec.describe ApplicationController do get 'routing_error' end - include_examples 'respond_with_error', 404 + it_behaves_like 'error response', 404 end context 'with ActiveRecord::RecordNotFound' do @@ -132,7 +132,7 @@ RSpec.describe ApplicationController do get 'record_not_found' end - include_examples 'respond_with_error', 404 + it_behaves_like 'error response', 404 end context 'with ActionController::InvalidAuthenticityToken' do @@ -141,7 +141,7 @@ RSpec.describe ApplicationController do get 'invalid_authenticity_token' end - include_examples 'respond_with_error', 422 + it_behaves_like 'error response', 422 end describe 'before_action :check_suspension' do @@ -186,7 +186,7 @@ RSpec.describe ApplicationController do get 'route_forbidden' end - include_examples 'respond_with_error', 403 + it_behaves_like 'error response', 403 end describe 'not_found' do @@ -201,7 +201,7 @@ RSpec.describe ApplicationController do get 'route_not_found' end - include_examples 'respond_with_error', 404 + it_behaves_like 'error response', 404 end describe 'gone' do @@ -216,7 +216,7 @@ RSpec.describe ApplicationController do get 'route_gone' end - include_examples 'respond_with_error', 410 + it_behaves_like 'error response', 410 end describe 'unprocessable_entity' do @@ -231,6 +231,6 @@ RSpec.describe ApplicationController do get 'route_unprocessable_entity' end - include_examples 'respond_with_error', 422 + it_behaves_like 'error response', 422 end end diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb index e7a8dd6d7f..c58bff659c 100644 --- a/spec/controllers/auth/registrations_controller_spec.rb +++ b/spec/controllers/auth/registrations_controller_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' RSpec.describe Auth::RegistrationsController do render_views - shared_examples 'checks for enabled registrations' do |path| + shared_examples 'registration mode based responses' do |path| context 'when in single user mode and open for registration' do before do Setting.registrations_mode = 'open' @@ -156,7 +156,7 @@ RSpec.describe Auth::RegistrationsController do end end - include_examples 'checks for enabled registrations', :new + it_behaves_like 'registration mode based responses', :new end describe 'POST #create' do @@ -542,7 +542,8 @@ RSpec.describe Auth::RegistrationsController do it_behaves_like 'registration with time', 'only secondary time range is set', 0, 0, 9, 12, true end - include_examples 'checks for enabled registrations', :create + it_behaves_like 'checks for enabled registrations', :create + it_behaves_like 'registration mode based responses', :create end describe 'DELETE #destroy' do diff --git a/spec/controllers/concerns/localized_spec.rb b/spec/controllers/concerns/localized_spec.rb index 4798e8270c..d4b8064d90 100644 --- a/spec/controllers/concerns/localized_spec.rb +++ b/spec/controllers/concerns/localized_spec.rb @@ -59,10 +59,10 @@ RSpec.describe Localized do sign_in(user) end - include_examples 'default locale' + it_behaves_like 'default locale' end context 'with a user who has not signed in' do - include_examples 'default locale' + it_behaves_like 'default locale' end end diff --git a/spec/controllers/relationships_controller_spec.rb b/spec/controllers/relationships_controller_spec.rb index 75b5e71f35..633d72fbba 100644 --- a/spec/controllers/relationships_controller_spec.rb +++ b/spec/controllers/relationships_controller_spec.rb @@ -35,7 +35,7 @@ RSpec.describe RelationshipsController do describe 'PATCH #update' do let(:alice) { Fabricate(:account, username: 'alice', domain: 'example.com') } - shared_examples 'redirects back to followers page' do + shared_examples 'general behavior for followed user' do it 'redirects back to followers page' do alice.follow!(user.account) @@ -49,7 +49,7 @@ RSpec.describe RelationshipsController do context 'when select parameter is not provided' do subject { patch :update } - include_examples 'redirects back to followers page' + it_behaves_like 'general behavior for followed user' end context 'when select parameter is provided' do @@ -83,7 +83,7 @@ RSpec.describe RelationshipsController do end end - include_examples 'redirects back to followers page' + it_behaves_like 'general behavior for followed user' end end end diff --git a/spec/controllers/settings/imports_controller_spec.rb b/spec/controllers/settings/imports_controller_spec.rb index 219b882e6d..c2c6c353f3 100644 --- a/spec/controllers/settings/imports_controller_spec.rb +++ b/spec/controllers/settings/imports_controller_spec.rb @@ -162,7 +162,7 @@ RSpec.describe Settings::ImportsController do ] end - include_examples 'export failed rows', "Account address,Show boosts,Notify on new posts,Languages\nfoo@bar,true,false,\nuser@bar,false,true,\"fr, de\"\n" + it_behaves_like 'export failed rows', "Account address,Show boosts,Notify on new posts,Languages\nfoo@bar,true,false,\nuser@bar,false,true,\"fr, de\"\n" end context 'with blocks' do @@ -175,7 +175,7 @@ RSpec.describe Settings::ImportsController do ] end - include_examples 'export failed rows', "foo@bar\nuser@bar\n" + it_behaves_like 'export failed rows', "foo@bar\nuser@bar\n" end context 'with mutes' do @@ -188,7 +188,7 @@ RSpec.describe Settings::ImportsController do ] end - include_examples 'export failed rows', "Account address,Hide notifications\nfoo@bar,true\nuser@bar,false\n" + it_behaves_like 'export failed rows', "Account address,Hide notifications\nfoo@bar,true\nuser@bar,false\n" end context 'with domain blocks' do @@ -201,7 +201,7 @@ RSpec.describe Settings::ImportsController do ] end - include_examples 'export failed rows', "bad.domain\nevil.domain\n" + it_behaves_like 'export failed rows', "bad.domain\nevil.domain\n" end context 'with bookmarks' do @@ -214,7 +214,7 @@ RSpec.describe Settings::ImportsController do ] end - include_examples 'export failed rows', "https://foo.com/1\nhttps://foo.com/2\n" + it_behaves_like 'export failed rows', "https://foo.com/1\nhttps://foo.com/2\n" end context 'with lists' do @@ -227,7 +227,7 @@ RSpec.describe Settings::ImportsController do ] end - include_examples 'export failed rows', "Amigos,user@example.com\nFrenemies,user@org.org\n" + it_behaves_like 'export failed rows', "Amigos,user@example.com\nFrenemies,user@org.org\n" end end diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb index 45c5e77323..0121c94330 100644 --- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb @@ -34,7 +34,7 @@ RSpec.describe Settings::TwoFactorAuthentication::ConfirmationsController do get :new, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } end - include_examples 'renders expected page' + it_behaves_like 'renders expected page' end it 'redirects if a new otp_secret has not been set in the session' do @@ -94,7 +94,7 @@ RSpec.describe Settings::TwoFactorAuthentication::ConfirmationsController do .to include(I18n.t('otp_authentication.wrong_code')) end - include_examples 'renders expected page' + it_behaves_like 'renders expected page' end private diff --git a/spec/lib/cache_buster_spec.rb b/spec/lib/cache_buster_spec.rb index f7cff9c1c3..65eb72ff3b 100644 --- a/spec/lib/cache_buster_spec.rb +++ b/spec/lib/cache_buster_spec.rb @@ -12,7 +12,7 @@ RSpec.describe CacheBuster do let(:purge_url) { 'https://example.com/test_purge' } describe '#bust' do - shared_examples 'makes_request' do + shared_examples 'cache busting request' do it 'makes an HTTP purging request' do method = http_method&.to_sym || :get stub_request(method, purge_url).to_return(status: 200) @@ -28,28 +28,28 @@ RSpec.describe CacheBuster do end context 'when using default options' do - include_examples 'makes_request' + it_behaves_like 'cache busting request' end context 'when specifying a secret header' do let(:secret_header) { 'X-Purge-Secret' } let(:secret) { SecureRandom.hex(20) } - include_examples 'makes_request' + it_behaves_like 'cache busting request' end context 'when specifying a PURGE method' do let(:http_method) { 'purge' } context 'when not using headers' do - include_examples 'makes_request' + it_behaves_like 'cache busting request' end context 'when specifying a secret header' do let(:secret_header) { 'X-Purge-Secret' } let(:secret) { SecureRandom.hex(20) } - include_examples 'makes_request' + it_behaves_like 'cache busting request' end end end diff --git a/spec/lib/fasp/request_spec.rb b/spec/lib/fasp/request_spec.rb index 5d81c09722..80d061dc61 100644 --- a/spec/lib/fasp/request_spec.rb +++ b/spec/lib/fasp/request_spec.rb @@ -44,14 +44,14 @@ RSpec.describe Fasp::Request do end describe '#get' do - include_examples 'a provider request', :get + it_behaves_like 'a provider request', :get end describe '#post' do - include_examples 'a provider request', :post + it_behaves_like 'a provider request', :post end describe '#delete' do - include_examples 'a provider request', :delete + it_behaves_like 'a provider request', :delete end end diff --git a/spec/lib/link_details_extractor_spec.rb b/spec/lib/link_details_extractor_spec.rb index cb072c4870..019a57cac5 100644 --- a/spec/lib/link_details_extractor_spec.rb +++ b/spec/lib/link_details_extractor_spec.rb @@ -118,7 +118,7 @@ RSpec.describe LinkDetailsExtractor do HTML - include_examples 'structured data' + it_behaves_like 'structured data' end context 'with the first tag is invalid JSON' do @@ -136,7 +136,7 @@ RSpec.describe LinkDetailsExtractor do HTML - include_examples 'structured data' + it_behaves_like 'structured data' end context 'with the first tag is null' do @@ -154,7 +154,7 @@ RSpec.describe LinkDetailsExtractor do HTML - include_examples 'structured data' + it_behaves_like 'structured data' end context 'with preceding block of unsupported LD+JSON' do @@ -194,7 +194,7 @@ RSpec.describe LinkDetailsExtractor do HTML - include_examples 'structured data' + it_behaves_like 'structured data' end context 'with unsupported in same block LD+JSON' do @@ -218,7 +218,7 @@ RSpec.describe LinkDetailsExtractor do HTML - include_examples 'structured data' + it_behaves_like 'structured data' end context 'with author names as array' do diff --git a/spec/lib/mastodon/cli/ip_blocks_spec.rb b/spec/lib/mastodon/cli/ip_blocks_spec.rb index 68d6b19859..d531b8b7a8 100644 --- a/spec/lib/mastodon/cli/ip_blocks_spec.rb +++ b/spec/lib/mastodon/cli/ip_blocks_spec.rb @@ -56,7 +56,7 @@ RSpec.describe Mastodon::CLI::IpBlocks do end context 'with valid IP addresses' do - include_examples 'ip address blocking' + it_behaves_like 'ip address blocking' end context 'when a specified IP address is already blocked' do @@ -84,7 +84,7 @@ RSpec.describe Mastodon::CLI::IpBlocks do .to('sign_up_requires_approval') end - include_examples 'ip address blocking' + it_behaves_like 'ip address blocking' end end @@ -101,25 +101,25 @@ RSpec.describe Mastodon::CLI::IpBlocks do context 'with --comment option' do let(:options) { { severity: 'no_access', comment: 'Spam' } } - include_examples 'ip address blocking' + it_behaves_like 'ip address blocking' end context 'with --duration option' do let(:options) { { severity: 'no_access', duration: 10.days } } - include_examples 'ip address blocking' + it_behaves_like 'ip address blocking' end context 'with "sign_up_requires_approval" severity' do let(:options) { { severity: 'sign_up_requires_approval' } } - include_examples 'ip address blocking' + it_behaves_like 'ip address blocking' end context 'with "sign_up_block" severity' do let(:options) { { severity: 'sign_up_block' } } - include_examples 'ip address blocking' + it_behaves_like 'ip address blocking' end context 'when a specified IP address fails to be blocked' do diff --git a/spec/lib/mastodon/redis_configuration_spec.rb b/spec/lib/mastodon/redis_configuration_spec.rb index e36dcfba0a..90dc20f6dd 100644 --- a/spec/lib/mastodon/redis_configuration_spec.rb +++ b/spec/lib/mastodon/redis_configuration_spec.rb @@ -207,18 +207,18 @@ RSpec.describe Mastodon::RedisConfiguration do end end - include_examples 'setting a different driver' - include_examples 'setting a namespace' - include_examples 'sentinel support' + it_behaves_like 'setting a different driver' + it_behaves_like 'setting a namespace' + it_behaves_like 'sentinel support' end describe '#sidekiq' do subject { redis_environment.sidekiq } - include_examples 'secondary configuration', 'SIDEKIQ' - include_examples 'setting a different driver' - include_examples 'setting a namespace' - include_examples 'sentinel support', 'SIDEKIQ' + it_behaves_like 'secondary configuration', 'SIDEKIQ' + it_behaves_like 'setting a different driver' + it_behaves_like 'setting a namespace' + it_behaves_like 'sentinel support', 'SIDEKIQ' end describe '#cache' do @@ -256,8 +256,8 @@ RSpec.describe Mastodon::RedisConfiguration do end end - include_examples 'secondary configuration', 'CACHE' - include_examples 'setting a different driver' - include_examples 'sentinel support', 'CACHE' + it_behaves_like 'secondary configuration', 'CACHE' + it_behaves_like 'setting a different driver' + it_behaves_like 'sentinel support', 'CACHE' end end diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index d97c01858d..25eb4ada26 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -35,7 +35,7 @@ RSpec.describe NotificationMailer do let(:notification) { Notification.create!(account: receiver.account, activity: mention) } let(:mail) { prepared_mailer_for(receiver.account).mention } - include_examples 'localized subject', 'notification_mailer.mention.subject', name: 'bob' + it_behaves_like 'localized subject', 'notification_mailer.mention.subject', name: 'bob' it 'renders the email' do expect(mail) @@ -47,8 +47,8 @@ RSpec.describe NotificationMailer do .and have_standard_headers('mention').for(receiver) end - include_examples 'delivery to non functional user' - include_examples 'delivery without status' + it_behaves_like 'delivery to non functional user' + it_behaves_like 'delivery without status' end describe 'follow' do @@ -56,7 +56,7 @@ RSpec.describe NotificationMailer do let(:notification) { Notification.create!(account: receiver.account, activity: follow) } let(:mail) { prepared_mailer_for(receiver.account).follow } - include_examples 'localized subject', 'notification_mailer.follow.subject', name: 'bob' + it_behaves_like 'localized subject', 'notification_mailer.follow.subject', name: 'bob' it 'renders the email' do expect(mail) @@ -66,7 +66,7 @@ RSpec.describe NotificationMailer do .and have_standard_headers('follow').for(receiver) end - include_examples 'delivery to non functional user' + it_behaves_like 'delivery to non functional user' end describe 'favourite' do @@ -74,7 +74,7 @@ RSpec.describe NotificationMailer do let(:notification) { Notification.create!(account: receiver.account, activity: favourite) } let(:mail) { prepared_mailer_for(own_status.account).favourite } - include_examples 'localized subject', 'notification_mailer.favourite.subject', name: 'bob' + it_behaves_like 'localized subject', 'notification_mailer.favourite.subject', name: 'bob' it 'renders the email' do expect(mail) @@ -86,8 +86,8 @@ RSpec.describe NotificationMailer do .and have_standard_headers('favourite').for(receiver) end - include_examples 'delivery to non functional user' - include_examples 'delivery without status' + it_behaves_like 'delivery to non functional user' + it_behaves_like 'delivery without status' end describe 'reblog' do @@ -95,7 +95,7 @@ RSpec.describe NotificationMailer do let(:notification) { Notification.create!(account: receiver.account, activity: reblog) } let(:mail) { prepared_mailer_for(own_status.account).reblog } - include_examples 'localized subject', 'notification_mailer.reblog.subject', name: 'bob' + it_behaves_like 'localized subject', 'notification_mailer.reblog.subject', name: 'bob' it 'renders the email' do expect(mail) @@ -107,8 +107,8 @@ RSpec.describe NotificationMailer do .and have_standard_headers('reblog').for(receiver) end - include_examples 'delivery to non functional user' - include_examples 'delivery without status' + it_behaves_like 'delivery to non functional user' + it_behaves_like 'delivery without status' end describe 'follow_request' do @@ -116,7 +116,7 @@ RSpec.describe NotificationMailer do let(:notification) { Notification.create!(account: receiver.account, activity: follow_request) } let(:mail) { prepared_mailer_for(receiver.account).follow_request } - include_examples 'localized subject', 'notification_mailer.follow_request.subject', name: 'bob' + it_behaves_like 'localized subject', 'notification_mailer.follow_request.subject', name: 'bob' it 'renders the email' do expect(mail) @@ -126,7 +126,7 @@ RSpec.describe NotificationMailer do .and have_standard_headers('follow_request').for(receiver) end - include_examples 'delivery to non functional user' + it_behaves_like 'delivery to non functional user' end private diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index 3f40e24c8b..6586d51a41 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -29,10 +29,10 @@ RSpec.describe UserMailer do .and(have_body_text(Rails.configuration.x.local_domain)) end - include_examples 'localized subject', - 'devise.mailer.confirmation_instructions.subject', - instance: Rails.configuration.x.local_domain - include_examples 'delivery to memorialized user' + it_behaves_like 'localized subject', + 'devise.mailer.confirmation_instructions.subject', + instance: Rails.configuration.x.local_domain + it_behaves_like 'delivery to memorialized user' end describe '#reconfirmation_instructions' do @@ -48,10 +48,10 @@ RSpec.describe UserMailer do .and(have_body_text(Rails.configuration.x.local_domain)) end - include_examples 'localized subject', - 'devise.mailer.confirmation_instructions.subject', - instance: Rails.configuration.x.local_domain - include_examples 'delivery to memorialized user' + it_behaves_like 'localized subject', + 'devise.mailer.confirmation_instructions.subject', + instance: Rails.configuration.x.local_domain + it_behaves_like 'delivery to memorialized user' end describe '#reset_password_instructions' do @@ -66,9 +66,9 @@ RSpec.describe UserMailer do .and(have_body_text('spec')) end - include_examples 'localized subject', - 'devise.mailer.reset_password_instructions.subject' - include_examples 'delivery to memorialized user' + it_behaves_like 'localized subject', + 'devise.mailer.reset_password_instructions.subject' + it_behaves_like 'delivery to memorialized user' end describe '#password_change' do @@ -82,9 +82,9 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('devise.mailer.password_change.title'))) end - include_examples 'localized subject', - 'devise.mailer.password_change.subject' - include_examples 'delivery to memorialized user' + it_behaves_like 'localized subject', + 'devise.mailer.password_change.subject' + it_behaves_like 'delivery to memorialized user' end describe '#email_changed' do @@ -98,9 +98,9 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('devise.mailer.email_changed.title'))) end - include_examples 'localized subject', - 'devise.mailer.email_changed.subject' - include_examples 'delivery to memorialized user' + it_behaves_like 'localized subject', + 'devise.mailer.email_changed.subject' + it_behaves_like 'delivery to memorialized user' end describe '#warning' do @@ -129,9 +129,9 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('devise.mailer.webauthn_credential.deleted.title'))) end - include_examples 'localized subject', - 'devise.mailer.webauthn_credential.deleted.subject' - include_examples 'delivery to memorialized user' + it_behaves_like 'localized subject', + 'devise.mailer.webauthn_credential.deleted.subject' + it_behaves_like 'delivery to memorialized user' end describe '#suspicious_sign_in' do @@ -148,8 +148,8 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('user_mailer.suspicious_sign_in.explanation'))) end - include_examples 'localized subject', - 'user_mailer.suspicious_sign_in.subject' + it_behaves_like 'localized subject', + 'user_mailer.suspicious_sign_in.subject' end describe '#failed_2fa' do @@ -166,8 +166,8 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('user_mailer.failed_2fa.explanation'))) end - include_examples 'localized subject', - 'user_mailer.failed_2fa.subject' + it_behaves_like 'localized subject', + 'user_mailer.failed_2fa.subject' end describe '#appeal_approved' do @@ -204,7 +204,7 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('devise.mailer.two_factor_enabled.explanation'))) end - include_examples 'delivery to memorialized user' + it_behaves_like 'delivery to memorialized user' end describe '#two_factor_disabled' do @@ -217,7 +217,7 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('devise.mailer.two_factor_disabled.explanation'))) end - include_examples 'delivery to memorialized user' + it_behaves_like 'delivery to memorialized user' end describe '#webauthn_enabled' do @@ -230,7 +230,7 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('devise.mailer.webauthn_enabled.explanation'))) end - include_examples 'delivery to memorialized user' + it_behaves_like 'delivery to memorialized user' end describe '#webauthn_disabled' do @@ -243,7 +243,7 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('devise.mailer.webauthn_disabled.explanation'))) end - include_examples 'delivery to memorialized user' + it_behaves_like 'delivery to memorialized user' end describe '#two_factor_recovery_codes_changed' do @@ -256,7 +256,7 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('devise.mailer.two_factor_recovery_codes_changed.explanation'))) end - include_examples 'delivery to memorialized user' + it_behaves_like 'delivery to memorialized user' end describe '#webauthn_credential_added' do @@ -270,7 +270,7 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('devise.mailer.webauthn_credential.added.explanation'))) end - include_examples 'delivery to memorialized user' + it_behaves_like 'delivery to memorialized user' end describe '#welcome' do @@ -289,7 +289,7 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('user_mailer.welcome.explanation'))) end - include_examples 'delivery to memorialized user' + it_behaves_like 'delivery to memorialized user' end describe '#backup_ready' do @@ -303,7 +303,7 @@ RSpec.describe UserMailer do .and(have_body_text(I18n.t('user_mailer.backup_ready.explanation'))) end - include_examples 'delivery to memorialized user' + it_behaves_like 'delivery to memorialized user' end describe '#terms_of_service_changed' do diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index defc17ab3c..c67484ea91 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -3,8 +3,8 @@ require 'rails_helper' RSpec.describe Account do - include_examples 'Account::Search' - include_examples 'Reviewable' + it_behaves_like 'Account::Search' + it_behaves_like 'Reviewable' context 'with an account record' do subject { Fabricate(:account) } @@ -992,8 +992,8 @@ RSpec.describe Account do end end - include_examples 'AccountAvatar', :account - include_examples 'AccountHeader', :account + it_behaves_like 'AccountAvatar', :account + it_behaves_like 'AccountHeader', :account describe '#increment_count!' do subject { Fabricate(:account) } diff --git a/spec/models/custom_filter_spec.rb b/spec/models/custom_filter_spec.rb index 168cbb7c91..03914fa6b4 100644 --- a/spec/models/custom_filter_spec.rb +++ b/spec/models/custom_filter_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe CustomFilter do - include_examples 'Expireable' + it_behaves_like 'Expireable' describe 'Validations' do it { is_expected.to validate_presence_of(:title) } diff --git a/spec/models/featured_tag_spec.rb b/spec/models/featured_tag_spec.rb index 20059cfba4..1197776b02 100644 --- a/spec/models/featured_tag_spec.rb +++ b/spec/models/featured_tag_spec.rb @@ -17,7 +17,7 @@ RSpec.describe FeaturedTag do let(:account) { Fabricate :account } - it { is_expected.to_not allow_value('Test').for(:name) } + it { is_expected.to_not allow_value('Test').for(:name).against(:tag_id) } context 'when account has hit limit' do before { stub_const 'FeaturedTag::LIMIT', 1 } diff --git a/spec/models/invite_spec.rb b/spec/models/invite_spec.rb index 6363f77a64..12ea6897f9 100644 --- a/spec/models/invite_spec.rb +++ b/spec/models/invite_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe Invite do - include_examples 'Expireable' + it_behaves_like 'Expireable' describe 'Associations' do it { is_expected.to belong_to(:user).inverse_of(:invites) } diff --git a/spec/models/ip_block_spec.rb b/spec/models/ip_block_spec.rb index 856d55be9d..18fb7ea136 100644 --- a/spec/models/ip_block_spec.rb +++ b/spec/models/ip_block_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe IpBlock do - include_examples 'Expireable' + it_behaves_like 'Expireable' describe 'Validations' do subject { Fabricate.build :ip_block } diff --git a/spec/models/login_activity_spec.rb b/spec/models/login_activity_spec.rb index 5b7935e8ba..bdee99c20f 100644 --- a/spec/models/login_activity_spec.rb +++ b/spec/models/login_activity_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe LoginActivity do - include_examples 'BrowserDetection' + it_behaves_like 'BrowserDetection' describe 'Associations' do it { is_expected.to belong_to(:user).required } diff --git a/spec/models/mute_spec.rb b/spec/models/mute_spec.rb index 33aa4f15dc..9cc4f74bea 100644 --- a/spec/models/mute_spec.rb +++ b/spec/models/mute_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe Mute do - include_examples 'Expireable' + it_behaves_like 'Expireable' describe 'Associations' do it { is_expected.to belong_to(:account).required } diff --git a/spec/models/poll_spec.rb b/spec/models/poll_spec.rb index 3288119546..04efb03a0b 100644 --- a/spec/models/poll_spec.rb +++ b/spec/models/poll_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe Poll do - include_examples 'Expireable' + it_behaves_like 'Expireable' describe '#reset_votes!' do let(:poll) { Fabricate :poll, cached_tallies: [2, 3], votes_count: 5, voters_count: 5 } diff --git a/spec/models/preview_card_provider_spec.rb b/spec/models/preview_card_provider_spec.rb index a3bd4f49ad..561c93d0b2 100644 --- a/spec/models/preview_card_provider_spec.rb +++ b/spec/models/preview_card_provider_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe PreviewCardProvider do - include_examples 'Reviewable' + it_behaves_like 'Reviewable' describe 'scopes' do let(:trendable_and_reviewed) { Fabricate(:preview_card_provider, trendable: true, reviewed_at: 5.days.ago) } diff --git a/spec/models/preview_card_trend_spec.rb b/spec/models/preview_card_trend_spec.rb index a5cb159af3..fb1f4643d5 100644 --- a/spec/models/preview_card_trend_spec.rb +++ b/spec/models/preview_card_trend_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe PreviewCardTrend do - include_examples 'RankedTrend' + it_behaves_like 'RankedTrend' describe 'Associations' do it { is_expected.to belong_to(:preview_card).required } diff --git a/spec/models/session_activation_spec.rb b/spec/models/session_activation_spec.rb index bb9b3c785f..63d22f0208 100644 --- a/spec/models/session_activation_spec.rb +++ b/spec/models/session_activation_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe SessionActivation do - include_examples 'BrowserDetection' + it_behaves_like 'BrowserDetection' describe '.active?' do subject { described_class.active?(id) } diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index 78d10632a8..7bbbf5f1a7 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Status do let(:bob) { Fabricate(:account, username: 'bob') } let(:other) { Fabricate(:status, account: bob, text: 'Skulls for the skull god! The enemy\'s gates are sideways!') } - include_examples 'Status::Visibility' + it_behaves_like 'Status::Visibility' describe '#local?' do it 'returns true when no remote URI is set' do diff --git a/spec/models/status_trend_spec.rb b/spec/models/status_trend_spec.rb index 50fb9b5f5c..28485ae4df 100644 --- a/spec/models/status_trend_spec.rb +++ b/spec/models/status_trend_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe StatusTrend do - include_examples 'RankedTrend' + it_behaves_like 'RankedTrend' describe 'Associations' do it { is_expected.to belong_to(:account).required } diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb index a1cc6a064f..0831ac34b8 100644 --- a/spec/models/tag_spec.rb +++ b/spec/models/tag_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe Tag do - include_examples 'Reviewable' + it_behaves_like 'Reviewable' describe 'Validations' do describe 'name' do diff --git a/spec/models/tag_trend_spec.rb b/spec/models/tag_trend_spec.rb index 37b50686db..2ddedd6cbc 100644 --- a/spec/models/tag_trend_spec.rb +++ b/spec/models/tag_trend_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe TagTrend do - include_examples 'RankedTrend' + it_behaves_like 'RankedTrend' describe 'Associations' do it { is_expected.to belong_to(:tag).required } diff --git a/spec/policies/admin/fasp/provider_policy_spec.rb b/spec/policies/admin/fasp/provider_policy_spec.rb index 802760f2e9..3bdb51405d 100644 --- a/spec/policies/admin/fasp/provider_policy_spec.rb +++ b/spec/policies/admin/fasp/provider_policy_spec.rb @@ -25,10 +25,10 @@ RSpec.describe Admin::Fasp::ProviderPolicy, type: :policy do end permissions :index?, :create? do - include_examples 'admin only', Fasp::Provider + it_behaves_like 'admin only', Fasp::Provider end permissions :show?, :create?, :update?, :destroy? do - include_examples 'admin only', :fasp_provider + it_behaves_like 'admin only', :fasp_provider end end diff --git a/spec/requests/api/v1/featured_tags_spec.rb b/spec/requests/api/v1/featured_tags_spec.rb index b9c78cc11b..7a5f92cdfd 100644 --- a/spec/requests/api/v1/featured_tags_spec.rb +++ b/spec/requests/api/v1/featured_tags_spec.rb @@ -127,10 +127,10 @@ RSpec.describe 'FeaturedTags' do FeaturedTag.create(name: params[:name], account: user.account) end - it 'returns http unprocessable entity' do + it 'returns http success' do post '/api/v1/featured_tags', headers: headers, params: params - expect(response).to have_http_status(422) + expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') end diff --git a/spec/requests/api/v1/tags_spec.rb b/spec/requests/api/v1/tags_spec.rb index f6ff7c614f..5beda68db0 100644 --- a/spec/requests/api/v1/tags_spec.rb +++ b/spec/requests/api/v1/tags_spec.rb @@ -161,4 +161,116 @@ RSpec.describe 'Tags' do end end end + + describe 'POST /api/v1/tags/:id/feature' do + subject do + post "/api/v1/tags/#{name}/feature", headers: headers + end + + let!(:tag) { Fabricate(:tag) } + let(:name) { tag.name } + let(:scopes) { 'write:accounts' } + + it_behaves_like 'forbidden for wrong scope', 'read read:follows' + + context 'when the tag exists' do + it 'creates featured tag', :aggregate_failures do + subject + + expect(response).to have_http_status(:success) + expect(response.content_type) + .to start_with('application/json') + expect(FeaturedTag.where(tag: tag, account: user.account)).to exist + end + end + + context 'when the tag does not exist' do + let(:name) { 'hoge' } + + it 'creates a new tag with the specified name', :aggregate_failures do + subject + + expect(response).to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(Tag.where(name: name)).to exist + expect(FeaturedTag.where(tag: Tag.find_by(name: name), account: user.account)).to exist + end + end + + context 'when the tag name is invalid' do + let(:name) { 'tag-name' } + + it 'returns http not found' do + subject + + expect(response).to have_http_status(404) + expect(response.content_type) + .to start_with('application/json') + end + end + + context 'when the Authorization header is missing' do + let(:headers) { {} } + let(:name) { 'unauthorized' } + + it 'returns http unauthorized' do + subject + + expect(response).to have_http_status(401) + expect(response.content_type) + .to start_with('application/json') + end + end + end + + describe 'POST #unfeature' do + subject do + post "/api/v1/tags/#{name}/unfeature", headers: headers + end + + let(:name) { tag.name } + let!(:tag) { Fabricate(:tag, name: 'foo') } + let(:scopes) { 'write:accounts' } + + before do + Fabricate(:featured_tag, account: user.account, tag: tag) + end + + it_behaves_like 'forbidden for wrong scope', 'read read:follows' + + it 'removes the featured tag', :aggregate_failures do + subject + + expect(response).to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(FeaturedTag.where(tag: tag, account: user.account)).to_not exist + end + + context 'when the tag name is invalid' do + let(:name) { 'tag-name' } + + it 'returns http not found' do + subject + + expect(response).to have_http_status(404) + expect(response.content_type) + .to start_with('application/json') + end + end + + context 'when the Authorization header is missing' do + let(:headers) { {} } + let(:name) { 'unauthorized' } + + it 'returns http unauthorized' do + subject + + expect(response).to have_http_status(401) + expect(response.content_type) + .to start_with('application/json') + end + end + end end diff --git a/spec/requests/oauth/token_spec.rb b/spec/requests/oauth/token_spec.rb index 74f301c577..7be65e7ab3 100644 --- a/spec/requests/oauth/token_spec.rb +++ b/spec/requests/oauth/token_spec.rb @@ -29,7 +29,7 @@ RSpec.describe 'Managing OAuth Tokens' do access_grant.plaintext_token end - shared_examples 'returns originally requested scopes' do + shared_examples 'original scope request preservation' do it 'returns all scopes requested for the given code' do subject @@ -41,26 +41,26 @@ RSpec.describe 'Managing OAuth Tokens' do context 'with no scopes specified' do let(:scope) { nil } - include_examples 'returns originally requested scopes' + it_behaves_like 'original scope request preservation' end context 'with scopes specified' do context 'when the scopes were requested for this code' do let(:scope) { 'write' } - include_examples 'returns originally requested scopes' + it_behaves_like 'original scope request preservation' end context 'when the scope was not requested for the code' do let(:scope) { 'follow' } - include_examples 'returns originally requested scopes' + it_behaves_like 'original scope request preservation' end context 'when the scope does not belong to the application' do let(:scope) { 'push' } - include_examples 'returns originally requested scopes' + it_behaves_like 'original scope request preservation' end end end diff --git a/spec/requests/omniauth_callbacks_spec.rb b/spec/requests/omniauth_callbacks_spec.rb index e13a49ec62..c71d025f9f 100644 --- a/spec/requests/omniauth_callbacks_spec.rb +++ b/spec/requests/omniauth_callbacks_spec.rb @@ -130,14 +130,14 @@ RSpec.describe 'OmniAuth callbacks' do end describe '#openid_connect', if: ENV['OIDC_ENABLED'] == 'true' && ENV['OIDC_SCOPE'].present? do - include_examples 'omniauth provider callbacks', :openid_connect + it_behaves_like 'omniauth provider callbacks', :openid_connect end describe '#cas', if: ENV['CAS_ENABLED'] == 'true' do - include_examples 'omniauth provider callbacks', :cas + it_behaves_like 'omniauth provider callbacks', :cas end describe '#saml', if: ENV['SAML_ENABLED'] == 'true' do - include_examples 'omniauth provider callbacks', :saml + it_behaves_like 'omniauth provider callbacks', :saml end end diff --git a/spec/services/activitypub/fetch_remote_account_service_spec.rb b/spec/services/activitypub/fetch_remote_account_service_spec.rb index 43d8148748..653e30be34 100644 --- a/spec/services/activitypub/fetch_remote_account_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_account_service_spec.rb @@ -70,7 +70,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do expect(account.domain).to eq 'example.com' end - include_examples 'sets profile data' + it_behaves_like 'sets profile data' end context 'when WebFinger presents different domain than URI' do @@ -94,7 +94,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do expect(account.domain).to eq 'iscool.af' end - include_examples 'sets profile data' + it_behaves_like 'sets profile data' end context 'when WebFinger returns a different URI' do diff --git a/spec/services/activitypub/fetch_remote_actor_service_spec.rb b/spec/services/activitypub/fetch_remote_actor_service_spec.rb index 9872c5cb4d..88c2e8331d 100644 --- a/spec/services/activitypub/fetch_remote_actor_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_actor_service_spec.rb @@ -70,7 +70,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService do expect(account.domain).to eq 'example.com' end - include_examples 'sets profile data' + it_behaves_like 'sets profile data' end context 'when WebFinger presents different domain than URI' do @@ -94,7 +94,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService do expect(account.domain).to eq 'iscool.af' end - include_examples 'sets profile data' + it_behaves_like 'sets profile data' end context 'when WebFinger returns a different URI' do diff --git a/spec/services/bulk_import_row_service_spec.rb b/spec/services/bulk_import_row_service_spec.rb index b9af795a5d..0601261bdb 100644 --- a/spec/services/bulk_import_row_service_spec.rb +++ b/spec/services/bulk_import_row_service_spec.rb @@ -115,7 +115,7 @@ RSpec.describe BulkImportRowService do account.follow!(target_account) end - include_examples 'row import success and list addition' + it_behaves_like 'row import success and list addition' end context 'when the user already requested to follow the target account' do @@ -123,17 +123,17 @@ RSpec.describe BulkImportRowService do account.request_follow!(target_account) end - include_examples 'row import success and list addition' + it_behaves_like 'row import success and list addition' end context 'when the target account is neither followed nor requested' do - include_examples 'row import success and list addition' + it_behaves_like 'row import success and list addition' end context 'when the target account is the user themself' do let(:target_account) { account } - include_examples 'row import success and list addition' + it_behaves_like 'row import success and list addition' end def add_target_account_to_list @@ -153,7 +153,7 @@ RSpec.describe BulkImportRowService do end context 'when the list does not exist yet' do - include_examples 'common behavior' + it_behaves_like 'common behavior' end context 'when the list exists' do @@ -161,7 +161,7 @@ RSpec.describe BulkImportRowService do Fabricate(:list, account: account, title: list_name) end - include_examples 'common behavior' + it_behaves_like 'common behavior' it 'does not create a new list' do account.follow!(target_account) diff --git a/spec/services/create_featured_tag_service_spec.rb b/spec/services/create_featured_tag_service_spec.rb index f057bc8538..ce8f8a4c38 100644 --- a/spec/services/create_featured_tag_service_spec.rb +++ b/spec/services/create_featured_tag_service_spec.rb @@ -20,11 +20,9 @@ RSpec.describe CreateFeaturedTagService do context 'with a remote account' do let(:account) { Fabricate(:account, domain: 'host.example') } - it 'creates a new featured tag and does not distributes' do + it 'raises argument error' do expect { subject.call(account, tag) } - .to change(FeaturedTag, :count).by(1) - expect(ActivityPub::AccountRawDistributionWorker) - .to_not have_enqueued_sidekiq_job(any_args) + .to raise_error ArgumentError end end end diff --git a/spec/services/delete_account_service_spec.rb b/spec/services/delete_account_service_spec.rb index 9055dc8819..3cb23650ee 100644 --- a/spec/services/delete_account_service_spec.rb +++ b/spec/services/delete_account_service_spec.rb @@ -128,7 +128,7 @@ RSpec.describe DeleteAccountService do let!(:remote_alice) { Fabricate(:account, inbox_url: 'https://alice.com/inbox', domain: 'alice.com', protocol: :activitypub) } let!(:remote_bob) { Fabricate(:account, inbox_url: 'https://bob.com/inbox', domain: 'bob.com', protocol: :activitypub) } - include_examples 'common behavior' do + it_behaves_like 'common behavior' do let(:account) { Fabricate(:account) } let(:local_follower) { Fabricate(:account) } @@ -145,7 +145,7 @@ RSpec.describe DeleteAccountService do stub_request(:post, account.inbox_url).to_return(status: 201) end - include_examples 'common behavior' do + it_behaves_like 'common behavior' do let(:account) { Fabricate(:account, inbox_url: 'https://bob.com/inbox', protocol: :activitypub, domain: 'bob.com') } let(:local_follower) { Fabricate(:account) } diff --git a/spec/services/remove_featured_tag_service_spec.rb b/spec/services/remove_featured_tag_service_spec.rb index 2f0694bc65..18aa1a9762 100644 --- a/spec/services/remove_featured_tag_service_spec.rb +++ b/spec/services/remove_featured_tag_service_spec.rb @@ -23,13 +23,9 @@ RSpec.describe RemoveFeaturedTagService do context 'when called by a non local account' do let(:account) { Fabricate(:account, domain: 'host.example') } - it 'destroys the featured tag and does not send a distribution' do - subject.call(account, featured_tag) - - expect { featured_tag.reload } - .to raise_error(ActiveRecord::RecordNotFound) - expect(ActivityPub::AccountRawDistributionWorker) - .to_not have_enqueued_sidekiq_job(any_args) + it 'raises argument error' do + expect { subject.call(account, featured_tag) } + .to raise_error(ArgumentError) end end end diff --git a/spec/services/suspend_account_service_spec.rb b/spec/services/suspend_account_service_spec.rb index c15c23ca30..2b1455e9a8 100644 --- a/spec/services/suspend_account_service_spec.rb +++ b/spec/services/suspend_account_service_spec.rb @@ -46,7 +46,7 @@ RSpec.describe SuspendAccountService do json['type'] == 'Update' && json['actor'] == actor_id && json['object']['id'] == actor_id && json['object']['suspended'] end - include_examples 'common behavior' do + it_behaves_like 'common behavior' do let!(:account) { Fabricate(:account) } let!(:remote_follower) { Fabricate(:account, uri: 'https://alice.com', inbox_url: 'https://alice.com/inbox', protocol: :activitypub, domain: 'alice.com') } let!(:remote_reporter) { Fabricate(:account, uri: 'https://bob.com', inbox_url: 'https://bob.com/inbox', protocol: :activitypub, domain: 'bob.com') } @@ -72,7 +72,7 @@ RSpec.describe SuspendAccountService do json['type'] == 'Reject' && json['actor'] == ActivityPub::TagManager.instance.uri_for(followee) && json['object']['actor'] == account.uri end - include_examples 'common behavior' do + it_behaves_like 'common behavior' do let!(:account) { Fabricate(:account, domain: 'bob.com', uri: 'https://bob.com', inbox_url: 'https://bob.com/inbox', protocol: :activitypub) } let!(:local_followee) { Fabricate(:account) } diff --git a/spec/services/unsuspend_account_service_spec.rb b/spec/services/unsuspend_account_service_spec.rb index 8d4882c37f..2410040062 100644 --- a/spec/services/unsuspend_account_service_spec.rb +++ b/spec/services/unsuspend_account_service_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe UnsuspendAccountService do - shared_context 'with common context' do + shared_context 'when account is unsuspended' do subject { described_class.new.call(account) } let!(:local_follower) { Fabricate(:user, current_sign_in_at: 1.hour.ago).account } @@ -31,12 +31,13 @@ RSpec.describe UnsuspendAccountService do stub_request(:post, 'https://bob.com/inbox').to_return(status: 201) end + let!(:account) { Fabricate(:account) } + it 'does not change the “suspended” flag' do expect { subject }.to_not change(account, :suspended?) end - include_examples 'with common context' do - let!(:account) { Fabricate(:account) } + include_context 'when account is unsuspended' do let!(:remote_follower) { Fabricate(:account, uri: 'https://alice.com', inbox_url: 'https://alice.com/inbox', protocol: :activitypub, domain: 'alice.com') } let!(:remote_reporter) { Fabricate(:account, uri: 'https://bob.com', inbox_url: 'https://bob.com/inbox', protocol: :activitypub, domain: 'bob.com') } @@ -65,8 +66,8 @@ RSpec.describe UnsuspendAccountService do end describe 'unsuspending a remote account' do - include_examples 'with common context' do - let!(:account) { Fabricate(:account, domain: 'bob.com', uri: 'https://bob.com', inbox_url: 'https://bob.com/inbox', protocol: :activitypub) } + include_context 'when account is unsuspended' do + let!(:account) { Fabricate(:account, domain: 'bob.com', uri: 'https://bob.com', inbox_url: 'https://bob.com/inbox', protocol: :activitypub) } let!(:resolve_account_service) { instance_double(ResolveAccountService) } before do diff --git a/spec/workers/import/row_worker_spec.rb b/spec/workers/import/row_worker_spec.rb index edb02cb391..f173d49706 100644 --- a/spec/workers/import/row_worker_spec.rb +++ b/spec/workers/import/row_worker_spec.rb @@ -8,95 +8,82 @@ RSpec.describe Import::RowWorker do let(:row) { Fabricate(:bulk_import_row, bulk_import: import) } describe '#perform' do - before do - allow(BulkImportRowService).to receive(:new).and_return(service_double) + before { allow(BulkImportRowService).to receive(:new).and_return(service_double) } + + shared_context 'when service succeeds' do + let(:service_double) { instance_double(BulkImportRowService, call: true) } + end + + shared_context 'when service fails' do + let(:service_double) { instance_double(BulkImportRowService, call: false) } + end + + shared_context 'when service errors' do + let(:service_double) { instance_double(BulkImportRowService) } + before { allow(service_double).to receive(:call).and_raise('dummy error') } end shared_examples 'clean failure' do - let(:service_double) { instance_double(BulkImportRowService, call: false) } - - it 'calls BulkImportRowService' do - subject.perform(row.id) - expect(service_double).to have_received(:call).with(row) - end - - it 'increases the number of processed items' do - expect { subject.perform(row.id) }.to(change { import.reload.processed_items }.by(+1)) - end - - it 'does not increase the number of imported items' do - expect { subject.perform(row.id) }.to_not(change { import.reload.imported_items }) - end - - it 'does not delete the row' do - subject.perform(row.id) - expect(BulkImportRow.exists?(row.id)).to be true + it 'calls service, increases processed items, preserves imported items, and keeps row' do + expect { subject.perform(row.id) } + .to change { import.reload.processed_items }.by(+1) + .and not_change { import.reload.imported_items } + .and(not_change { BulkImportRow.exists?(row.id) }.from(true)) + expect(service_double) + .to have_received(:call).with(row) end end shared_examples 'unclean failure' do - let(:service_double) { instance_double(BulkImportRowService) } - - before do - allow(service_double).to receive(:call) do - raise 'dummy error' - end - end - - it 'raises an error and does not change processed items count' do - expect { subject.perform(row.id) }.to raise_error(StandardError, 'dummy error').and(not_change { import.reload.processed_items }) - end - - it 'does not delete the row' do - expect { subject.perform(row.id) }.to raise_error(StandardError, 'dummy error').and(not_change { BulkImportRow.exists?(row.id) }) + it 'raises an error, preserves processed items, and keeps row' do + expect { subject.perform(row.id) } + .to raise_error(StandardError, 'dummy error') + .and(not_change { import.reload.processed_items }) + .and(not_change { BulkImportRow.exists?(row.id) }.from(true)) end end shared_examples 'clean success' do - let(:service_double) { instance_double(BulkImportRowService, call: true) } - - it 'calls BulkImportRowService' do - subject.perform(row.id) + it 'calls service, increases processed items, increases imported items, and deletes row' do + expect { subject.perform(row.id) } + .to change { import.reload.processed_items }.by(+1) + .and change { import.reload.imported_items }.by(+1) + .and(change { BulkImportRow.exists?(row.id) }.from(true).to(false)) expect(service_double).to have_received(:call).with(row) end - - it 'increases the number of processed items' do - expect { subject.perform(row.id) }.to(change { import.reload.processed_items }.by(+1)) - end - - it 'increases the number of imported items' do - expect { subject.perform(row.id) }.to(change { import.reload.imported_items }.by(+1)) - end - - it 'deletes the row' do - expect { subject.perform(row.id) }.to change { BulkImportRow.exists?(row.id) }.from(true).to(false) - end end context 'when there are multiple rows to process' do let(:import) { Fabricate(:bulk_import, total_items: 2, processed_items: 0, imported_items: 0, state: :in_progress) } context 'with a clean failure' do - include_examples 'clean failure' + include_context 'when service fails' + it_behaves_like 'clean failure' it 'does not mark the import as finished' do - expect { subject.perform(row.id) }.to_not(change { import.reload.state.to_sym }) + expect { subject.perform(row.id) } + .to_not(change { import.reload.state.to_sym }) end end context 'with an unclean failure' do - include_examples 'unclean failure' + include_context 'when service errors' + it_behaves_like 'unclean failure' it 'does not mark the import as finished' do - expect { subject.perform(row.id) }.to raise_error(StandardError).and(not_change { import.reload.state.to_sym }) + expect { subject.perform(row.id) } + .to raise_error(StandardError) + .and(not_change { import.reload.state.to_sym }) end end context 'with a clean success' do - include_examples 'clean success' + include_context 'when service succeeds' + it_behaves_like 'clean success' it 'does not mark the import as finished' do - expect { subject.perform(row.id) }.to_not(change { import.reload.state.to_sym }) + expect { subject.perform(row.id) } + .to_not(change { import.reload.state.to_sym }) end end end @@ -105,21 +92,28 @@ RSpec.describe Import::RowWorker do let(:import) { Fabricate(:bulk_import, total_items: 2, processed_items: 1, imported_items: 0, state: :in_progress) } context 'with a clean failure' do - include_examples 'clean failure' + include_context 'when service fails' + it_behaves_like 'clean failure' it 'marks the import as finished' do - expect { subject.perform(row.id) }.to change { import.reload.state.to_sym }.from(:in_progress).to(:finished) + expect { subject.perform(row.id) } + .to change { import.reload.state.to_sym }.from(:in_progress).to(:finished) end end - # NOTE: sidekiq retry logic may be a bit too difficult to test, so leaving this blind spot for now - it_behaves_like 'unclean failure' + context 'with an unclean failure' do + # NOTE: sidekiq retry logic may be a bit too difficult to test, so leaving this blind spot for now + include_context 'when service errors' + it_behaves_like 'unclean failure' + end context 'with a clean success' do - include_examples 'clean success' + include_context 'when service succeeds' + it_behaves_like 'clean success' it 'marks the import as finished' do - expect { subject.perform(row.id) }.to change { import.reload.state.to_sym }.from(:in_progress).to(:finished) + expect { subject.perform(row.id) } + .to change { import.reload.state.to_sym }.from(:in_progress).to(:finished) end end end diff --git a/spec/workers/move_worker_spec.rb b/spec/workers/move_worker_spec.rb index a24de57e27..d9cf4a1686 100644 --- a/spec/workers/move_worker_spec.rb +++ b/spec/workers/move_worker_spec.rb @@ -113,27 +113,27 @@ RSpec.describe MoveWorker do end shared_examples 'common tests' do - include_examples 'user note handling' - include_examples 'block and mute handling' - include_examples 'followers count handling' - include_examples 'lists handling' + it_behaves_like 'user note handling' + it_behaves_like 'block and mute handling' + it_behaves_like 'followers count handling' + it_behaves_like 'lists handling' context 'when a local user already follows both source and target' do before do local_follower.request_follow!(target_account) end - include_examples 'user note handling' - include_examples 'block and mute handling' - include_examples 'followers count handling' - include_examples 'lists handling' + it_behaves_like 'user note handling' + it_behaves_like 'block and mute handling' + it_behaves_like 'followers count handling' + it_behaves_like 'lists handling' context 'when the local user already has the target in a list' do before do list.accounts << target_account end - include_examples 'lists handling' + it_behaves_like 'lists handling' end end @@ -142,17 +142,17 @@ RSpec.describe MoveWorker do local_follower.follow!(target_account) end - include_examples 'user note handling' - include_examples 'block and mute handling' - include_examples 'followers count handling' - include_examples 'lists handling' + it_behaves_like 'user note handling' + it_behaves_like 'block and mute handling' + it_behaves_like 'followers count handling' + it_behaves_like 'lists handling' context 'when the local user already has the target in a list' do before do list.accounts << target_account end - include_examples 'lists handling' + it_behaves_like 'lists handling' end end end @@ -164,7 +164,7 @@ RSpec.describe MoveWorker do expect(UnfollowFollowWorker).to have_enqueued_sidekiq_job(local_follower.id, source_account.id, target_account.id, false) end - include_examples 'common tests' + it_behaves_like 'common tests' end context 'when target account is local' do @@ -175,7 +175,7 @@ RSpec.describe MoveWorker do expect(UnfollowFollowWorker).to have_enqueued_sidekiq_job(local_follower.id, source_account.id, target_account.id, true) end - include_examples 'common tests' + it_behaves_like 'common tests' end context 'when both target and source accounts are local' do @@ -187,7 +187,7 @@ RSpec.describe MoveWorker do expect(local_follower.following?(target_account)).to be true end - include_examples 'common tests' + it_behaves_like 'common tests' it 'does not allow the moved account to follow themselves' do source_account.follow!(target_account) diff --git a/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb b/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb index 28a4176193..55b66629e0 100644 --- a/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb +++ b/spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb @@ -108,7 +108,7 @@ RSpec.describe Scheduler::AccountsStatusesCleanupScheduler do context 'when the budget is lower than the number of toots to delete' do it 'deletes the appropriate statuses' do - expect(Status.count).to be > (subject.compute_budget) # Data check + expect(Status.count).to be > subject.compute_budget # Data check expect { subject.perform } .to change(Status, :count).by(-subject.compute_budget) # Cleanable statuses diff --git a/yarn.lock b/yarn.lock index 2e632ff9a0..71121a56f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13432,9 +13432,9 @@ __metadata: linkType: hard "pg-connection-string@npm:^2.6.0": - version: 2.8.1 - resolution: "pg-connection-string@npm:2.8.1" - checksum: 10c0/87cb519d97a5bdc756f71a6b051eea4d4887e2e102bc694ecda935fe636a037666a0444729b08c7a26c2e9e4b052b2b366af58492ccc49704bacd6876f946ce8 + version: 2.8.5 + resolution: "pg-connection-string@npm:2.8.5" + checksum: 10c0/5f65afc9dfc99ecf1583a1699c97511f3d505659c9c6a91db8cd0ffe862caa29060722712a034abd6da493356567261febf18b3a6ef223d0a219f0d50d959b97 languageName: node linkType: hard @@ -13469,9 +13469,9 @@ __metadata: linkType: hard "pg-protocol@npm:*": - version: 1.9.0 - resolution: "pg-protocol@npm:1.9.0" - checksum: 10c0/c37e61d7fafa97f22eabf12de69863f42fdabb3671df9cc2623bd0ffd6bdedc212e7e8460ad2c721c8a08d8477b4f128a923bf2381905d68a23a532ec7517c77 + version: 1.9.5 + resolution: "pg-protocol@npm:1.9.5" + checksum: 10c0/5cb3444cf973adadd22ee9ea26bb1674f0d980ef8f9c66d426bbe67fc9cb5f0ca4a204bf7e432b3ab2ab59ac8227f4b18ab3b2e64eaed537e037e916991c7319 languageName: node linkType: hard