diff --git a/.eslintrc.js b/.eslintrc.js index 176879034..e2d16a54a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -120,7 +120,6 @@ module.exports = defineConfig({ 'react/jsx-uses-react': 'off', // not needed with new JSX transform 'react/jsx-wrap-multilines': 'error', 'react/no-deprecated': 'off', - 'react/no-unknown-property': 'off', 'react/react-in-jsx-scope': 'off', // not needed with new JSX transform 'react/self-closing-comp': 'error', diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 895dbfbad..a7998ddfd 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -50,7 +50,6 @@ matchManagers: ['bundler'], matchPackageNames: [ 'rack', // Needs to be synced with Rails version - 'sprockets', // Requires manual upgrade https://github.com/rails/sprockets/blob/master/UPGRADING.md#guide-to-upgrading-from-sprockets-3x-to-4x 'strong_migrations', // Requires manual upgrade 'sidekiq', // Requires manual upgrade 'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1a5fef79..b68a9bde3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,6 +11,10 @@ You can contribute in the following ways: If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon). +## API Changes and Additions + +Please note that any changes or additions made to the API should have an accompanying pull request on [our documentation repository](https://github.com/mastodon/documentation). + ## Bug reports Bug reports and feature suggestions must use descriptive and concise titles and be submitted to [GitHub Issues](https://github.com/mastodon/mastodon/issues). Please use the search function to make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected. diff --git a/Gemfile b/Gemfile index e3fb39e16..cfcbcc0d3 100644 --- a/Gemfile +++ b/Gemfile @@ -5,7 +5,7 @@ ruby '>= 3.0.0' gem 'puma', '~> 6.3' gem 'rails', '~> 7.1.1' -gem 'sprockets', '~> 3.7.2' +gem 'propshaft' gem 'thor', '~> 1.2' gem 'rack', '~> 2.2.7' @@ -89,7 +89,6 @@ gem 'sidekiq-unique-jobs', '~> 7.1' gem 'sidekiq-bulk', '~> 0.2.0' gem 'simple-navigation', '~> 4.4' gem 'simple_form', '~> 5.2' -gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie' gem 'stoplight', '~> 3.0.1' gem 'strong_migrations', '1.6.4' gem 'tty-prompt', '~> 0.23', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 4c78e6b0a..4b39692d0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -118,7 +118,7 @@ GEM minitest (>= 5.1) mutex_m tzinfo (~> 2.0) - addressable (2.8.5) + addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) aes_key_wrap (1.1.0) android_key_attestation (0.3.0) @@ -175,7 +175,7 @@ GEM blurhash (0.1.7) bootsnap (1.17.0) msgpack (~> 1.2) - brakeman (6.0.1) + brakeman (6.1.0) browser (5.3.1) brpoplpush-redis_script (0.1.3) concurrent-ruby (~> 1.0, >= 1.0.5) @@ -197,7 +197,7 @@ GEM activesupport cbor (0.5.9.6) charlock_holmes (0.7.7) - chewy (7.3.4) + chewy (7.3.5) activesupport (>= 5.2) elasticsearch (>= 7.12.0, < 7.14.0) elasticsearch-dsl @@ -220,9 +220,9 @@ GEM database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) date (3.3.4) - debug (1.8.0) - irb (>= 1.5.0) - reline (>= 0.3.1) + debug (1.9.0) + irb (~> 1.10) + reline (>= 0.3.8) debug_inspector (1.1.0) devise (4.9.3) bcrypt (~> 3.0) @@ -377,20 +377,20 @@ GEM terminal-table (>= 1.5.1) idn-ruby (0.1.5) io-console (0.6.0) - irb (1.9.1) + irb (1.10.1) rdoc reline (>= 0.3.8) jmespath (1.6.2) - json (2.6.3) - json-canonicalization (0.3.2) + json (2.7.0) + json-canonicalization (1.0.0) json-jwt (1.15.3) activesupport (>= 4.2) aes_key_wrap bindata httpclient - json-ld (3.3.0) + json-ld (3.3.1) htmlentities (~> 4.3) - json-canonicalization (~> 0.3, >= 0.3.2) + json-canonicalization (~> 1.0) link_header (~> 0.0, >= 0.0.8) multi_json (~> 1.15) rack (>= 2.2, < 4) @@ -484,7 +484,8 @@ GEM nokogiri (1.15.5) mini_portile2 (~> 2.8.2) racc (~> 1.4) - oj (3.16.1) + oj (3.16.2) + bigdecimal (~> 3.1) omniauth (2.1.1) hashie (>= 3.4.6) rack (>= 2.2.3) @@ -534,6 +535,11 @@ GEM net-smtp premailer (~> 1.7, >= 1.7.9) private_address_check (0.5.0) + propshaft (0.8.0) + actionpack (>= 7.0.0) + activesupport (>= 7.0.0) + rack + railties (>= 7.0.0) psych (5.1.1.1) stringio public_suffix (5.0.4) @@ -608,7 +614,7 @@ GEM link_header (~> 0.0, >= 0.0.8) rdf-normalize (0.6.1) rdf (~> 3.2) - rdoc (6.6.0) + rdoc (6.6.1) psych (>= 4.0.0) redcarpet (3.6.0) redis (4.8.1) @@ -656,7 +662,7 @@ GEM rspec-mocks (~> 3.0) sidekiq (>= 5, < 8) rspec-support (3.12.1) - rubocop (1.57.2) + rubocop (1.58.0) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) @@ -664,7 +670,7 @@ GEM rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.28.1, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) rubocop-ast (1.30.0) @@ -702,7 +708,7 @@ GEM scenic (1.7.0) activerecord (>= 4.0.0) railties (>= 4.0.0) - selenium-webdriver (4.15.0) + selenium-webdriver (4.16.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) @@ -736,18 +742,11 @@ GEM simplecov-lcov (0.8.0) simplecov_json_formatter (0.1.4) smart_properties (1.17.0) - sprockets (3.7.2) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.4.2) - actionpack (>= 5.2) - activesupport (>= 5.2) - sprockets (>= 3.0.0) stackprof (0.2.25) statsd-ruby (1.5.0) stoplight (3.0.2) redlock (~> 1.0) - stringio (3.0.9) + stringio (3.1.0) strong_migrations (1.6.4) activerecord (>= 5.2) swd (1.3.0) @@ -911,6 +910,7 @@ DEPENDENCIES posix-spawn premailer-rails private_address_check (~> 0.5) + propshaft public_suffix (~> 5.0) puma (~> 6.3) pundit (~> 2.3) @@ -949,8 +949,6 @@ DEPENDENCIES simple_form (~> 5.2) simplecov (~> 0.22) simplecov-lcov (~> 0.8) - sprockets (~> 3.7.2) - sprockets-rails (~> 3.4) stackprof stoplight (~> 3.0.1) strong_migrations (= 1.6.4) diff --git a/README.md b/README.md index beab2c355..7b22d61b5 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ To set up **MacOS** for native development, complete the following steps: - Run `brew install postgresql@14` - Run `brew install redis` - Run `brew install imagemagick` +- Run `brew install libidn` - Install Foreman or a similar tool (such as [overmind](https://github.com/DarthSim/overmind)) to handle multiple process launching. - Navigate to Mastodon's root directory and run `brew install nvm` then `nvm use` to use the version from .nvmrc - Run `corepack enable && corepack prepare` diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 48d9119fb..135bbb0fd 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -114,7 +114,7 @@ module ApplicationHelper end def fa_icon(icon, attributes = {}) - class_names = attributes[:class]&.split(' ') || [] + class_names = attributes[:class]&.split || [] class_names << 'fa' class_names += icon.split.map { |cl| "fa-#{cl}" } diff --git a/app/javascript/mastodon/actions/notifications_typed.ts b/app/javascript/mastodon/actions/notifications_typed.ts index 7e51fa51e..176362f4b 100644 --- a/app/javascript/mastodon/actions/notifications_typed.ts +++ b/app/javascript/mastodon/actions/notifications_typed.ts @@ -18,6 +18,6 @@ export const notificationsUpdate = createAction( playSound: boolean; }) => ({ payload: args, - meta: { playSound: playSound ? { sound: 'boop' } : undefined }, + meta: { sound: playSound ? 'boop' : undefined }, }), ); diff --git a/app/javascript/mastodon/features/interaction_modal/index.jsx b/app/javascript/mastodon/features/interaction_modal/index.jsx index 4f145f9ed..216c63a7e 100644 --- a/app/javascript/mastodon/features/interaction_modal/index.jsx +++ b/app/javascript/mastodon/features/interaction_modal/index.jsx @@ -298,9 +298,9 @@ class LoginForm extends React.PureComponent { onFocus={this.handleFocus} onBlur={this.handleBlur} onKeyDown={this.handleKeyDown} - autocomplete='off' - autocapitalize='off' - spellcheck='false' + autoComplete='off' + autoCapitalize='off' + spellCheck='false' /> diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx index 5fb9af90a..e4593fd72 100644 --- a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx +++ b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx @@ -84,7 +84,7 @@ class NavigationPanel extends Component { {banner && -
rel="me"
neleidžia apsimesti interneto svetainėse, kuriose yra naudotojų sukurto turinio. Vietoj to gali naudoti net nuorodą
puslapio antraštėje esančią žymę a
, tačiau HTML turi būti pasiekiamas nevykdant JavaScript.
hint_html: "Savo tapatybės patvirtinimas Mastodon skirtas visiems. Remiantis atviraisiais žiniatinklio standartais, dabar ir visam laikui nemokamas. Viskas, ko tau reikia, yra asmeninė svetainė, pagal kurią žmonės tave atpažįsta. Kai iš savo profilio pateiksi nuorodą į šią svetainę, patikrinsime, ar svetainėje yra nuoroda į tavo profilį, ir parodysime vizualinį indikatorių."
+ instructions_html: Nukopijuok ir įklijuok toliau pateiktą kodą į savo svetainės HTML. Tada į vieną iš papildomų profilio laukų skirtuke „Redaguoti profilį“ įrašyk savo svetainės adresą ir išsaugok pakeitimus.
verification: Patvirtinimas
verified_links: Tavo patikrintos nuorodos
webauthn_credentials:
create:
error: Kilo problema pridedant saugumo raktą. Bandyk dar kartą.
+ success: Tavo saugumo raktas buvo sėkmingai pridėtas.
+ delete_confirmation: Ar tikrai nori ištrinti šį saugumo raktą?
+ description_html: Jei įjungsi saugumo rakto tapatybės nustatymą, prisijungiant reikės naudoti vieną iš savo saugumo raktų.
+ destroy:
+ error: Kilo problema ištrinant saugumo raktą. Bandyk dar kartą.
+ success: Tavo saugumo raktas buvo sėkmingai ištrintas.
nickname_hint: Įvesk naujojo saugumo rakto slapyvardį
not_enabled: Dar neįjungei WebAuthn
diff --git a/config/locales/my.yml b/config/locales/my.yml
index 03ed771a4..4ba4fcfad 100644
--- a/config/locales/my.yml
+++ b/config/locales/my.yml
@@ -1324,6 +1324,7 @@ my:
'86400': ၁ ရက်
expires_in_prompt: ဘယ်တော့မှ
generate: ဖိတ်ကြားချက်လင့်ခ် ဖန်တီးပါ
+ invalid: ဤဖိတ်ကြားချက်မှာ မမှန်ကန်ပါ
invited_by: သင့်ကို ဖိတ်ခေါ်ထားသည် -
max_uses:
other: "%{count} အသုံးပြုမှုများ"
diff --git a/config/locales/ne.yml b/config/locales/ne.yml
new file mode 100644
index 000000000..db03c5186
--- /dev/null
+++ b/config/locales/ne.yml
@@ -0,0 +1 @@
+ne:
diff --git a/config/locales/ry.yml b/config/locales/ry.yml
new file mode 100644
index 000000000..6fe57b65c
--- /dev/null
+++ b/config/locales/ry.yml
@@ -0,0 +1 @@
+ry:
diff --git a/config/locales/sc.yml b/config/locales/sc.yml
index fa7603f2b..d92b64783 100644
--- a/config/locales/sc.yml
+++ b/config/locales/sc.yml
@@ -5,6 +5,7 @@ sc:
contact_missing: No cunfiguradu
contact_unavailable: No a disponimentu
hosted_on: Mastodon allogiadu in %{domain}
+ title: Informatziones
accounts:
follow: Sighi
followers:
@@ -45,6 +46,7 @@ sc:
confirm: Cunfirma
confirmed: Cunfirmadu
confirming: Cunfirmende
+ custom: Personalizadu
delete: Cantzella datos
deleted: Cantzelladu
demote: Degrada
@@ -81,7 +83,9 @@ sc:
moderation:
active: Ativu
all: Totus
+ disabled: Disativadu
pending: De imbiare
+ silenced: Limitadu
suspended: Suspèndidu
title: Moderatzione
moderation_notes: Notas de moderatzione
@@ -112,6 +116,7 @@ sc:
search: Chirca
search_same_email_domain: Àteras persones cun su pròpiu domìniu de posta
search_same_ip: Àteras persones cun sa pròpiu IP
+ security: Seguresa
sensitive: Sensìbile
sensitized: marcadu comente a sensìbile
shared_inbox_url: URL de intrada cumpartzida
@@ -122,6 +127,7 @@ sc:
silenced: Limitadas
statuses: Tuts
subscribe: Sutascrie·ti
+ suspend: Suspensione
suspended: Suspèndidu
suspension_irreversible: Is datos de custu contu sunt istados cantzellados in manera irreversìbile. Podes bogare sa suspensione a su contu pro chi si potzat impreare, ma no at a recuperare datu perunu de is chi teniat in antis.
suspension_reversible_hint_html: Su contu est istadu suspèndidu, e is datos ant a èssere cantzelladu de su totu su %{date}. Finas a tando, su contu si podet ripristinare sena efetu malu perunu. Si boles cantzellare totu is datos de su contu immediatamente ddu podes fàghere inoghe in bassu.
@@ -274,6 +280,7 @@ sc:
updated_msg: Emoji atualizadu
upload: Càrriga
dashboard:
+ media_storage: Immagasinamentu
software: Programmas
space: Impreu de ispàtziu
title: Pannellu
@@ -281,21 +288,28 @@ sc:
add_new: Permite sa federatzione cun domìniu
created_msg: Sa federatzione cun su domìniu est istada permìtida
destroyed_msg: Sa federatzione cun su domìniu no est istada permìtida
+ import: Importatzione
undo: Non permitas sa federatzione cun su domìniu
domain_blocks:
add_new: Agiunghe blocu de domìniu nou
+ confirm_suspension:
+ cancel: Annulla
+ confirm: Suspensione
created_msg: Protzessende su blocu de domìniu
destroyed_msg: Su blocu de domìniu est istadu iscontzadu
domain: Domìniu
edit: Modìfica su blocu de su domìniu
existing_domain_block_html: As giai impostu lìmites prus astrintos a %{name}, ddu dias dèpere isblocare prima.
+ import: Importatzione
new:
create: Crea unu blocu
hint: Su blocu de domìniu no at a impedire sa creatzione de contos noos in sa base de datos, ma ant a èssere aplicados in manera retroativa mètodos de moderatzione ispetzìficos subra custos contos.
severity:
noop: Perunu
+ silence: A sa muda
suspend: Suspensione
title: Blocu de domìniu nou
+ not_permitted: Non tenes su permissu de fàghere custa atzione
obfuscate: Cua su nòmine de domìniu
obfuscate_hint: Cua una parte de su nòmine de domìniu in sa lista si sa visualizatzione de sa lista de domìnios limitados est ativa
private_comment: Cummentu privadu
@@ -326,9 +340,24 @@ sc:
title: Cussìgios de sighidura
unsuppress: Recùpera su cussìgiu de sighidura
instances:
+ back_to_all: Totus
+ back_to_limited: Limitadu
+ back_to_warning: Atentzione
by_domain: Domìniu
+ content_policies:
+ policies:
+ reject_reports: Refuda informes
+ silence: A sa muda
+ suspend: Suspensione
+ dashboard:
+ instance_reports_measure: informes a subra de àtere
+ delivery:
+ all: Totus
delivery_available: Sa cunsigna est a disponimentu
empty: Perunu domìniu agatadu.
+ known_accounts:
+ one: "%{count} contu connòschidu"
+ other: "%{count} contos connòschidos"
moderation:
all: Totus
limited: Limitadas
@@ -390,18 +419,23 @@ sc:
notes:
one: "%{count} nota"
other: "%{count} notas"
+ action_log: Registru de controllu
action_taken_by: Mesuras adotadas dae
are_you_sure: Seguru?
assign_to_self: Assigna a mie
assigned: Moderatzione assignada
by_target_domain: Domìniu de su contu signaladu
+ cancel: Annulla
comment:
none: Perunu
+ confirm: Cunfirma
created_at: Sinnaladu
forwarded: Torradu a imbiare
forwarded_to: Torradu a imbiare a %{domain}
mark_as_resolved: Marca comente a isòrvidu
+ mark_as_sensitive: Signala comente a sensìbile
mark_as_unresolved: Marcare comente a non isòrvidu
+ no_one_assigned: Nemos
notes:
create: Agiunghe una nota
create_and_resolve: Isorve cun una nota
@@ -419,6 +453,15 @@ sc:
unassign: Boga s'assignatzione
unresolved: No isòrvidu
updated_at: Atualizadu
+ view_profile: Visualiza profilu
+ roles:
+ categories:
+ administration: Amministratzione
+ invites: Invitos
+ moderation: Moderatzione
+ delete: Cantzella
+ privileges:
+ administrator: Amministratzione
rules:
add_new: Agiunghe règula
delete: Cantzella
@@ -427,10 +470,26 @@ sc:
empty: Peruna règula de serbidore definida ancora.
title: Règulas de su serbidore
settings:
+ about:
+ manage_rules: Gesti is règulas de su serbidore
+ title: Informatziones
+ appearance:
+ title: Aspetu
+ default_noindex:
+ desc_html: Ìmplicat a totu is utentes chi no apant modificadu custa cunfiguratzione
+ title: Esclude in manera predefinida is utentes dae s'inditzamentu de is motores de chirca
+ discovery:
+ follow_recommendations: Cussìgios de sighidura
+ profile_directory: Diretòriu de profilos
+ public_timelines: Lìnias de tempos pùblicas
+ title: Iscoberta
+ trends: Tendèntzias
domain_blocks:
all: Pro totus
disabled: Pro nemos
users: Pro utentes locales in lìnia
+ registrations:
+ title: Registros
registrations_mode:
modes:
approved: Aprovatzione rechesta pro si registrare
@@ -439,7 +498,10 @@ sc:
site_uploads:
delete: Cantzella s'archìviu carrigadu
destroyed_msg: Càrriga de su situ cantzellada.
+ software_updates:
+ documentation_link: Àteras informatziones
statuses:
+ application: Aplicatzione
back_to_account: Torra a sa pàgina de su contu
deleted: Cantzelladu
media:
@@ -447,6 +509,10 @@ sc:
no_status_selected: Perunu istadu est istadu mudadu dae chi non nd'as seletzionadu
title: Istados de su contu
with_media: Cun elementos multimediales
+ strikes:
+ actions:
+ none: "%{name} at imbiadu un'avisu a %{target}"
+ suspend: "%{name} at suspèndidu su contu de %{target}"
system_checks:
database_schema_check:
message_html: Ddoe at tràmudas de base de datos in suspesu. Pone·ddas in esecutzione pro ti assegurare chi s'aplicatzione funtzionet comente si tocat
@@ -459,12 +525,24 @@ sc:
review: Revisiona s'istadu
updated_msg: Cunfiguratzione de etichetas atualizada
title: Amministratzione
+ trends:
+ pending_review: De revisionare
+ tags:
+ title: Etichetas de tendèntzia
+ title: Tendèntzias
warning_presets:
add_new: Agiunghe noa
delete: Cantzella
edit_preset: Modìfica s'avisu predefinidu
empty: No as cunfiguradu ancora perunu avisu predefinidu.
title: Gesti is cunfiguratziones predefinidas de is avisos
+ webhooks:
+ delete: Cantzella
+ disable: Disativa
+ disabled: Disativadu
+ enable: Ativa
+ enabled: Ativu
+ status: Istadu
admin_mailer:
new_pending_account:
body: Is detàllios de su contu nou sunt a suta. Podes aprovare o refudare custa rechesta.
@@ -473,6 +551,9 @@ sc:
body: "%{reporter} at sinnaladu %{target}"
body_remote: Una persone de su domìniu %{domain} at sinnaladu %{target}
subject: Informe nou pro %{instance} (#%{id})
+ new_trends:
+ new_trending_tags:
+ title: Etichetas de tendèntzia
aliases:
add_new: Crea unu nomìngiu
created_msg: Nomìngiu creadu. Immoe podes cumintzare a tramudare dae su contu betzu.
@@ -495,17 +576,21 @@ sc:
notification_preferences: Muda is preferèntzias de posta
salutation: "%{name},"
settings: 'Muda is preferèntzias de posta: %{link}'
+ unsubscribe: Annulla sa sutiscritzione
view: 'Visualizatzione:'
view_profile: Visualiza profilu
view_status: Ammustra s'istadu
applications:
created: Aplicatzione creada
destroyed: Aplicatzione cantzellada
+ logout: Essi
regenerate_token: Torra a generare s'identificadore de atzessu
token_regenerated: Identificadore de atzessu generadu
warning: Dae cara a custos datos. Non ddos cumpartzas mai cun nemos!
your_token: S'identificadore tuo de atzessu
auth:
+ confirmations:
+ login_link: intra
delete_account: Cantzella su contu
delete_account_html: Si boles cantzellare su contu, ddu podes fàghere inoghe. T'amus a dimandare una cunfirmatzione.
description:
@@ -528,11 +613,14 @@ sc:
register: Registru
registration_closed: "%{instance} no atzetat àteras persones"
reset_password: Reseta sa crae
+ rules:
+ back: A coa
security: Seguresa
set_new_password: Cunfigura una crae noa
status:
account_status: Istadu de su contu
confirming: Isetende chi sa posta eletrònica siat cumpletada.
+ functional: Su contu tuo est operativu.
pending: Sa dimanda tua est in protzessu de revisione dae su personale nostru. Podet serbire unu pagu de tempus. As a retzire unu messàgiu eletrònicu si sa dimanda est aprovada.
redirecting_to: Su contu tuo est inativu pro ite in die de oe est torrende a indiritzare a %{acct}.
too_fast: Formulàriu imbiadu tropu a lestru, torra a proare.
@@ -581,8 +669,14 @@ sc:
more_details_html: Pro àteros detàllios, bide sa normativa de riservadesa.
username_available: Su nòmine de utente tuo at a torrare a èssere a disponimentu
username_unavailable: Su nòmine de utente tuo no at a abarrare a disponimentu
+ disputes:
+ strikes:
+ title_actions:
+ none: Atentzione
domain_validator:
invalid_domain: no est unu nòmine de domìniu vàlidu
+ edit_profile:
+ other: Àteru
errors:
'400': Sa dimanda chi as imbiadu non fiat vàlida o non fiat curreta.
'403': Non tenes permissu pro bìdere custa pàgina.
@@ -638,11 +732,15 @@ sc:
title: Agiunghe unu filtru nou
generic:
all: Totus
+ cancel: Annulla
changes_saved_msg: Modìficas sarvadas.
+ confirm: Cunfirma
copy: Còpia
delete: Cantzella
+ none: Perunu
order_by: Òrdina pro
save_changes: Sarva is modìficas
+ today: oe
validation_errors:
one: Calicuna cosa ancora no est andende. Bide sa faddina in bàsciu
other: Calicuna cosa ancora no est andende. Bide is %{count} faddinas in bàsciu
@@ -655,12 +753,15 @@ sc:
overwrite: Subrascrie
overwrite_long: Sostitui is registros atuales cun cussos noos
preface: Podes importare datos chi as esportadu dae unu àteru serbidore, che a sa lista de sa gente chi ses sighende o blochende.
+ status: Istadu
success: Datos carrigados; ant a èssere protzessados luego
+ type: Casta de importatzione
types:
blocking: Lista de blocos
bookmarks: Sinnalibros
domain_blocking: Lista domìnios blocados
following: Lista de sighiduras
+ lists: Listas
muting: Lista gente a sa muda
upload: Càrriga
invites:
@@ -685,6 +786,13 @@ sc:
expires_at: Iscadit
uses: Impreos
title: Invita gente
+ login_activities:
+ authentication_methods:
+ password: crae
+ webauthn: craes de seguresa
+ mail_subscriptions:
+ unsubscribe:
+ title: Annulla sa sutiscritzione
media_attachments:
validations:
images_and_video: Non si podet allegare unu vìdeu in una publicatzione chi cuntenet giai immàgines
@@ -797,6 +905,8 @@ sc:
other: Àteru
posting_defaults: Valores predefinidos de publicatzione
public_timelines: Lìnias de tempos pùblicas
+ privacy:
+ search: Chirca
reactions:
errors:
limit_reached: Lìmite de reatziones diferentes cròmpidu
@@ -850,6 +960,7 @@ sc:
platforms:
adobe_air: Adobe Air
android: Android
+ chrome_os: ChromeOS
firefox_os: Firefox OS
ios: iOS
linux: Linux
@@ -934,6 +1045,7 @@ sc:
'2629746': 1 mese
'31556952': 1 annu
'5259492': 2 meses
+ '604800': 1 chida
'63113904': 2 annos
'7889238': 3 meses
stream_entries:
@@ -969,6 +1081,7 @@ sc:
subject: S'archìviu tuo est prontu pro èssere iscarrigadu
title: Collida dae s'archìviu
warning:
+ reason: 'Resone:'
subject:
disable: Su contu tuo %{acct} est istadu cungeladu
none: Avisu pro %{acct}
diff --git a/config/locales/simple_form.fil.yml b/config/locales/simple_form.fil.yml
new file mode 100644
index 000000000..4084bf2f9
--- /dev/null
+++ b/config/locales/simple_form.fil.yml
@@ -0,0 +1 @@
+fil:
diff --git a/config/locales/simple_form.hu.yml b/config/locales/simple_form.hu.yml
index 70c225e8f..6e11f7fb9 100644
--- a/config/locales/simple_form.hu.yml
+++ b/config/locales/simple_form.hu.yml
@@ -81,8 +81,8 @@ hu:
bootstrap_timeline_accounts: Ezek a fiókok ki lesznek tűzve az új felhasználók követési javaslatainak élére.
closed_registrations_message: Akkor jelenik meg, amikor a regisztráció le van zárva
content_cache_retention_period: A más kiszolgálókról származó bejegyzések megadott számú nap után törölve lesznek, ha pozitív értékre van állítva. Ez lehet, hogy nem fordítható vissza.
- custom_css: A Mastodon webes verziójában használhatsz egyedi stílusokat.
- mascot: Felülvágja a haladó webes felületen található illusztrációt.
+ custom_css: A Mastodon webes verziójában használhatsz egyéni stílusokat.
+ mascot: Felülbírálja a speciális webes felületen található illusztrációt.
media_cache_retention_period: A letöltött médiafájlok megadott számú nap után törölve lesznek, ha pozitív értékre van állítva, és igény szerint újból le lesznek töltve.
peers_api_enabled: Azon domainek listája, melyekkel ez a kiszolgáló találkozott a fediverzumban. Nem csatolunk adatot arról, hogy föderált kapcsolatban vagy-e az adott kiszolgálóval, csak arról, hogy a kiszolgálód tud a másikról. Ezt olyan szolgáltatások használják, melyek általában a föderációról készítenek statisztikákat.
profile_directory: A profilok jegyzéke minden olyan felhasználót felsorol, akik engedélyezték a felfedezhetőségüket.
@@ -103,7 +103,7 @@ hu:
form_challenge:
current_password: Beléptél egy biztonsági térben
imports:
- data: Egy másik Mastodon kiszolgálóról exportált CSV-fájl
+ data: Egy másik Mastodon-kiszolgálóról exportált CSV-fájl
invite_request:
text: Ez segít nekünk átnézni a jelentkezésedet
ip_block:
@@ -199,7 +199,7 @@ hu:
otp_attempt: Kétlépcsős azonosító kód
password: Jelszó
phrase: Kulcsszó vagy kifejezés
- setting_advanced_layout: Haladó webes felület engedélyezése
+ setting_advanced_layout: Speciális webes felület engedélyezése
setting_aggregate_reblogs: Megtolások csoportosítása az idővonalakon
setting_always_send_emails: E-mail értesítések küldése mindig
setting_auto_play_gif: GIF-ek automatikus lejátszása
diff --git a/config/locales/simple_form.hy.yml b/config/locales/simple_form.hy.yml
index 56aa1d66b..9dbcd1301 100644
--- a/config/locales/simple_form.hy.yml
+++ b/config/locales/simple_form.hy.yml
@@ -43,7 +43,7 @@ hy:
setting_display_media_hide_all: Երբեք մեդիա ցոյց չտալ
setting_display_media_show_all: Մեդիա միշտ ցոյց տալ
setting_use_blurhash: Կտորները հիմնուում են թաքցուած վիզուալի վրայ՝ խամրեցնելով դետալները
- setting_use_pending_items: Թաքցնել հոսքի թարմացումները կտտոի ետեւում՝ աւտօմատ թարմացուող հոսքի փոխարէն
+ setting_use_pending_items: Թաքցնել հոսքի թարմացումները կոճակի ետեւում՝ աւտօմատ թարմացուող հոսքի փոխարէն
username: Միայն լատինատառեր, թուեր եւ տակի գծիկ
whole_word: Եթէ բանալի բառը կամ արտայայտութիւնը պարունակում է միայն այբբենական նիշեր եւ թուեր, ապա այն կիրառուելու է ամբողջ բառի հետ համընկնելու դէպքում միայն
domain_allow:
diff --git a/config/locales/simple_form.lt.yml b/config/locales/simple_form.lt.yml
index 39caaf6ba..6eb90340d 100644
--- a/config/locales/simple_form.lt.yml
+++ b/config/locales/simple_form.lt.yml
@@ -27,14 +27,33 @@ lt:
none: Naudok šią parinktį norėdamas (-a) išsiųsti įspėjimą naudotojui, nesukeldamas (-a) jokio kito veiksmo.
sensitive: Priversk visus šio naudotojo medijos priedus pažymėti kaip jautrius.
silence: Neleisk naudotojui skelbti viešai matomų įrašų, paslėpk jų įrašus ir pranešimus nuo žmonių, kurie neseka jo. Uždaro visus su šia paskyra susijusius ataskaitas.
+ suspend: Neleisk jokios sąveikos iš šios paskyros arba į ją ir ištrink jos turinį. Sugrąžinama per 30 dienų. Uždaro visas su šia paskyra susijusias ataskaitas.
+ warning_preset_id: Pasirinktinai. Gali pridėti pasirinktinį tekstą iš anksto nustatyto rinkinio pabaigoje
+ announcement:
+ all_day: Jei pažymėta, bus rodomos tik laikotarpio datos
+ ends_at: Pasirinktinai. Skelbimas šiuo laiku bus automatiškai panaikintas
+ scheduled_at: Palik tuščią, kad skelbimas būtų paskelbtas iš karto
+ starts_at: Pasirinktinai. Jei skelbimas susietas su tam tikru laiko tarpu
+ text: Gali naudoti įrašo sintaksę. Būk dėmesingas (-a), kiek vietos naudotojo ekrane užims skelbimas
+ appeal:
+ text: Gali pateikti apeliaciją dėl streiko tik vieną kartą
defaults:
+ autofollow: Žmonės, kurie užsiregistruos per kvietimą, automatiškai seks tave
avatar: PNG, GIF arba JPG. Ne daugiau kaip %{size}. Bus sumažintas iki %{dimensions} tšk.
- header: PNG, GIF arba JPG. Ne daugiau kaip %{size}. Bus sumažintas iki %{dimensions}tšk.
+ bot: Signalizuoti kitiems, kad paskyroje daugiausia atliekami automatiniai veiksmai ir kad ji gali būti nestebima
+ context: Vienas arba keli kontekstai, kuriems turėtų būti taikomas filtras
+ current_password: Saugumo sumetimais įvesk dabartinės paskyros slaptažodį
+ current_username: Kad patvirtintum, įvesk dabartinės paskyros naudotojo vardą
+ digest: Siunčiama tik po ilgo neaktyvumo laikotarpio ir tik tuo atveju, jei negavai jokių asmeninių žinučių
+ email: Tau bus išsiųstas patvirtinimo el. laiškas
+ header: PNG, GIF arba JPG. Ne daugiau kaip %{size}. Bus sumažintas iki %{dimensions} tšk.
inbox_url: Nukopijuok URL adresą iš pradinio puslapio perdavėjo, kurį nori naudoti
irreversible: Filtruoti įrašai išnyks negrįžtamai, net jei vėliau filtras bus pašalintas
locale: Naudotojo sąsajos kalba, el. laiškai ir stumiamieji pranešimai
password: Naudok bent 8 simbolius
- phrase: Bus suderinta, neatsižvelgiant į teksto korpusą arba įrašo turinio įspėjimą
+ phrase: Bus suderinta, neatsižvelgiant į teksto lygį arba įrašo turinio įspėjimą
+ scopes: Prie kurių API programai bus leidžiama pasiekti. Pasirinkus aukščiausio lygio sritį, atskirų sričių pasirinkti nereikia.
+ setting_aggregate_reblogs: Nerodyti naujų pakėlimų įrašams, kurie neseniai buvo pakelti (taikoma tik naujai gautiems pakėlimams)
setting_always_send_emails: Paprastai pranešimai el. paštu nebus siunčiami, kai aktyviai naudoji Mastodon
setting_default_sensitive: Jautrioji medija pagal numatytuosius nustatymus yra paslėpta ir gali būti atskleista paspaudus
setting_display_media_default: Slėpti mediją, pažymėtą kaip jautrią
@@ -42,21 +61,116 @@ lt:
setting_display_media_show_all: Visada rodyti mediją
setting_use_blurhash: Gradientai pagrįsti paslėptų vaizdų spalvomis, tačiau užgožia bet kokias detales
setting_use_pending_items: Slėpti laiko skalės naujienas po paspaudimo, vietoj automatinio kanalo slinkimo
+ username: Gali naudoti raides, skaičius ir pabraukimus
+ whole_word: Kai raktažodis ar frazė yra tik raidinis ir skaitmeninis, jis bus taikomas tik tada, jei atitiks visą žodį
+ email_domain_block:
+ with_dns_records: Bus bandoma išspręsti nurodyto domeno DNS įrašus, o rezultatai taip pat bus blokuojami
featured_tag:
name: 'Štai keletas pastaruoju metu dažniausiai saitažodžių, kurių tu naudojai:'
+ filters:
+ action: Pasirink, kokį veiksmą atlikti, kai įrašas atitinka filtrą
+ actions:
+ hide: Visiškai paslėpti filtruotą turinį ir elgtis taip, tarsi jo neegzistuotų
+ warn: Slėpti filtruojamą turinį po įspėjimu, paminint filtro pavadinimą
form_admin_settings:
+ activity_api_enabled: Vietinių paskelbtų įrašų, aktyvių naudotojų ir naujų registracijų skaičiai kas savaitę
+ backups_retention_period: Laikyti sukurtus naudotojų archyvus nurodytą dienų skaičių.
peers_api_enabled: Domenų pavadinimų sąrašas, su kuriais šis serveris susidūrė fediverse. Čia nėra duomenų apie tai, ar tu bendrauji su tam tikru serveriu, tik apie tai, kad tavo serveris apie jį žino. Tai naudojama tarnybose, kurios renka federacijos statistiką bendrąja prasme.
site_contact_email: Kaip žmonės gali su tavimi susisiekti teisiniais ar pagalbos užklausimais.
site_contact_username: Kaip žmonės gali tave pasiekti Mastodon.
site_extended_description: Bet kokia papildoma informacija, kuri gali būti naudinga lankytojams ir naudotojams. Gali būti struktūrizuota naudojant Markdown sintaksę.
+ thumbnail: Maždaug 2:1 dydžio vaizdas, rodomas šalia tavo serverio informacijos.
+ timeline_preview: Atsijungę lankytojai galės naršyti naujausius viešus įrašus, esančius serveryje.
trends: Trendai rodo, kurios įrašai, saitažodžiai ir naujienų istorijos tavo serveryje sulaukia didžiausio susidomėjimo.
sessions:
- webauthn: Jei tai USB raktas, būtinai jį įkišk ir, jei reikia, paliesk.
+ otp: 'Įvesk telefono programėlėje sugeneruotą dviejų tapatybės kodą arba naudok vieną iš atkūrimo kodų:'
+ webauthn: Jei tai USB raktas, būtinai jį įkišk ir, jei reikia, paspausk.
settings:
indexable: Tavo profilio puslapis gali būti rodomas paieškos rezultatuose Google, Bing ir kituose.
+ user:
+ chosen_languages: Kai pažymėta, viešose laiko skalėse bus rodomi tik įrašai pasirinktomis kalbomis
+ role: Vaidmuo valdo, kokius leidimus naudotojas (-a) turi
labels:
+ account:
+ indexable: Įtraukti viešus įrašus į paieškos rezultatus
+ show_collections: Rodyti sekimus ir sekėjus profilyje
+ unlocked: Automatiškai priimti naujus sekėjus
+ account_warning_preset:
+ title: Pavadinimas
+ admin_account_action:
+ include_statuses: Įtraukti praneštus įrašus į el. laišką
+ defaults:
+ avatar: Profilio nuotrauka
+ bot: Tai automatinė paskyra
+ chosen_languages: Filtruoti kalbas
+ display_name: Rodomas vardas
+ email: El. pašto adresas
+ expires_in: Nustoja galioti po
+ fields: Papildomi laukai
+ irreversible: Mesti vietoj slėpti
+ locale: Sąsajos kalba
+ max_uses: Maksimalus naudojimo skaičius
+ new_password: Naujas slaptažodis
+ note: Biografija
+ password: Slaptažodis
+ phrase: Raktažodis arba frazė
+ setting_auto_play_gif: Automatiškai leisti animuotų GIF
+ setting_boost_modal: Rodyti patvirtinimo dialogą prieš pakėliant įrašą
+ setting_default_language: Skelbimo kalba
+ setting_default_privacy: Skelbimo privatumas
+ setting_default_sensitive: Visada žymėti mediją kaip jautrią
+ setting_delete_modal: Rodyti patvirtinimo dialogą prieš ištrinant įrašą
+ setting_display_media: Medijos rodymas
+ setting_display_media_hide_all: Slėpti viską
+ setting_display_media_show_all: Rodyti viską
+ setting_expand_spoilers: Visada išplėsti įrašus, pažymėtus turinio įspėjimais
+ setting_hide_network: Slėpti savo socialinę diagramą
+ setting_system_font_ui: Naudoti numatytąjį sistemos šriftą
+ setting_theme: Svetainės tema
+ setting_use_pending_items: Lėtas režimas
+ title: Pavadinimas
+ type: Importo tipas
+ username: Naudotojo vardas
+ username_or_email: Naudotojo vardas arba el. paštas
+ whole_word: Visas žodis
+ email_domain_block:
+ with_dns_records: Įtraukti MX įrašus ir domeno IP adresus
featured_tag:
name: Saitažodis
+ filters:
+ actions:
+ hide: Slėpti visiškai
+ warn: Slėpti su įspėjimu
+ form_admin_settings:
+ activity_api_enabled: Skelbti suvestinį statistiką apie naudotojų veiklą per API
+ bootstrap_timeline_accounts: Visada rekomenduoti šias paskyras naujiems naudotojams
+ content_cache_retention_period: Turinio talpyklos išlaikymo laikotarpis
+ custom_css: Pasirinktinis CSS
+ mascot: Pasirinktinis talismanas (pasenęs)
+ registrations_mode: Kas gali užsiregistruoti
+ show_domain_blocks_rationale: Rodyti, kodėl domenai buvo užblokuoti
+ site_extended_description: Išplėstas aprašymas
+ site_short_description: Serverio aprašymas
+ site_terms: Privatumo politika
+ site_title: Serverio pavadinimas
+ theme: Numatytoji tema
+ thumbnail: Serverio miniatūra
+ invite_request:
+ text: Kodėl nori prisijungti?
+ notification_emails:
+ favourite: Kažkas pamėgo tavo įrašą
+ follow: Kažkas seka tave
+ follow_request: Kažkas paprašė sekti tave
+ mention: Kažkas paminėjo tave
+ pending_account: Reikia peržiūros naujam paskyrui
+ reblog: Kažkas pakėlė tavo įrašą
+ software_updates:
+ label: Yra nauja Mastodon versija
+ patch: Pranešti apie klaidų ištaisymo atnaujinimus
+ rule:
+ text: Taisyklė
+ settings:
+ show_application: Rodyti, iš kurios programėles išsiuntei įrašą
tag:
listable: Leisti šį saitažodį rodyti paieškose ir pasiūlymuose
name: Saitažodis
@@ -64,11 +178,15 @@ lt:
usable: Leisti įrašams naudoti šį saitažodį
user:
role: Vaidmuo
+ time_zone: Laiko juosta
user_role:
+ color: Ženklelio spalva
+ highlighted: Rodyti vaidmenį kaip ženklelį naudotojo profiliuose
+ name: Pavadinimas
permissions_as_keys: Leidimai
position: Prioritetas
webhook:
- events: Įgalinti įvykiai
+ events: Įjungti įvykiai
template: Naudingosios apkrovos šablonas
url: Galutinio taško URL
'no': Ne
diff --git a/config/locales/simple_form.ne.yml b/config/locales/simple_form.ne.yml
new file mode 100644
index 000000000..db03c5186
--- /dev/null
+++ b/config/locales/simple_form.ne.yml
@@ -0,0 +1 @@
+ne:
diff --git a/config/locales/simple_form.ry.yml b/config/locales/simple_form.ry.yml
new file mode 100644
index 000000000..6fe57b65c
--- /dev/null
+++ b/config/locales/simple_form.ry.yml
@@ -0,0 +1 @@
+ry:
diff --git a/config/locales/simple_form.sc.yml b/config/locales/simple_form.sc.yml
index 2c4725996..5f5d63307 100644
--- a/config/locales/simple_form.sc.yml
+++ b/config/locales/simple_form.sc.yml
@@ -53,6 +53,8 @@ sc:
domain: Custu domìniu at a pòdere recuperare datos dae custu serbidore e is datos in intrada dae cue ant a èssere protzessados e archiviados
email_domain_block:
with_dns_records: S'at a fàghere unu tentativu de risòlvere is registros DNS de su domìniu e fintzas is risultados ant a èssere blocados
+ form_admin_settings:
+ activity_api_enabled: Nùmeru de tuts publicados in locale, utentes ativos e registros noos in perìodos chidajolos
form_challenge:
current_password: Ses intrende in un'àrea segura
imports:
@@ -155,6 +157,7 @@ sc:
setting_use_pending_items: Modalidade lenta
severity: Severidade
sign_in_token_attempt: Còdighe de seguresa
+ title: Tìtulu
type: Casta de importatzione
username: Nòmine utente
username_or_email: Nòmine utente o indiritzu de posta eletrònica
@@ -163,6 +166,16 @@ sc:
with_dns_records: Include registros MX e indiritzos IP de su domìniu
featured_tag:
name: Eticheta
+ form_admin_settings:
+ activity_api_enabled: Pùblica istatìsticas agregadas subra s'atividade de s'utente
+ custom_css: CSS personalizadu
+ peers_api_enabled: Pùblica sa lista de serbidores iscobertos in s'API
+ profile_directory: Ativa diretòriu de profilos
+ show_domain_blocks: Ammustra blocos de domìniu
+ site_contact_username: Nòmine de utente de su cuntatu
+ site_short_description: Descritzione de su serbidore
+ site_title: Nòmine de su serbidore
+ thumbnail: Miniadura de su serbidore
interactions:
must_be_follower: Bloca is notìficas dae chie non ti sighit
must_be_following: Bloca is notìficas dae gente chi non sighis
@@ -186,6 +199,7 @@ sc:
mention: Una persone t'at mentovadu
pending_account: Unu contu nou tenet bisòngiu de una revisione
reblog: Una persone at cumpartzidu s'istadu tuo
+ report: Imbiu de un'informe nou
rule:
text: Règula
tag:
@@ -193,6 +207,9 @@ sc:
name: Eticheta
trendable: Permite a custa eticheta de apàrrere in is tendèntzias
usable: Permite a is tuts de impreare custa eticheta
+ user_role:
+ name: Nòmine
+ permissions_as_keys: Permissos
'no': Nono
recommended: Cussigiadu
required:
diff --git a/config/locales/simple_form.tlh.yml b/config/locales/simple_form.tlh.yml
new file mode 100644
index 000000000..884714fb7
--- /dev/null
+++ b/config/locales/simple_form.tlh.yml
@@ -0,0 +1 @@
+tlh:
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index 63779e5bd..caf253c69 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -656,6 +656,10 @@ sk:
rules_check:
action: Spravuj serverové pravidlá
message_html: Neurčil/a si žiadne serverové pravidlá.
+ software_version_critical_check:
+ action: Pozri dostupné aktualizácie
+ software_version_patch_check:
+ action: Pozri dostupné aktualizácie
upload_check_privacy_error:
action: Pozri tu pre viac informácií
upload_check_privacy_error_object_storage:
diff --git a/config/locales/tlh.yml b/config/locales/tlh.yml
new file mode 100644
index 000000000..884714fb7
--- /dev/null
+++ b/config/locales/tlh.yml
@@ -0,0 +1 @@
+tlh:
diff --git a/lib/mastodon/cli/accounts.rb b/lib/mastodon/cli/accounts.rb
index 33520df25..414675303 100644
--- a/lib/mastodon/cli/accounts.rb
+++ b/lib/mastodon/cli/accounts.rb
@@ -472,15 +472,13 @@ module Mastodon::CLI
end
total = 0
- total += Account.where(id: ::Follow.where(account: account).select(:target_account_id)).count if options[:follows]
- total += Account.where(id: ::Follow.where(target_account: account).select(:account_id)).count if options[:followers]
+ total += account.following.reorder(nil).count if options[:follows]
+ total += account.followers.reorder(nil).count if options[:followers]
progress = create_progress_bar(total)
processed = 0
if options[:follows]
- scope = Account.where(id: ::Follow.where(account: account).select(:target_account_id))
-
- scope.find_each do |target_account|
+ account.following.reorder(nil).find_each do |target_account|
UnfollowService.new.call(account, target_account)
rescue => e
progress.log pastel.red("Error processing #{target_account.id}: #{e}")
@@ -493,9 +491,7 @@ module Mastodon::CLI
end
if options[:followers]
- scope = Account.where(id: ::Follow.where(target_account: account).select(:account_id))
-
- scope.find_each do |target_account|
+ account.followers.reorder(nil).find_each do |target_account|
UnfollowService.new.call(target_account, account)
rescue => e
progress.log pastel.red("Error processing #{target_account.id}: #{e}")
diff --git a/lib/mastodon/cli/domains.rb b/lib/mastodon/cli/domains.rb
index 329f17167..e092497dc 100644
--- a/lib/mastodon/cli/domains.rb
+++ b/lib/mastodon/cli/domains.rb
@@ -97,6 +97,8 @@ module Mastodon::CLI
say("Removed #{custom_emojis_count} custom emojis#{dry_run_mode_suffix}", :green)
end
+ CRAWL_SLEEP_TIME = 20
+
option :concurrency, type: :numeric, default: 50, aliases: [:c]
option :format, type: :string, default: 'summary', aliases: [:f]
option :exclude_suspended, type: :boolean, default: false, aliases: [:x]
@@ -168,8 +170,8 @@ module Mastodon::CLI
pool.post(domain, &work_unit)
end
- sleep 20
- sleep 20 until pool.queue_length.zero?
+ sleep CRAWL_SLEEP_TIME
+ sleep CRAWL_SLEEP_TIME until pool.queue_length.zero?
pool.shutdown
pool.wait_for_termination(20)
diff --git a/lib/mastodon/cli/email_domain_blocks.rb b/lib/mastodon/cli/email_domain_blocks.rb
index 88a84ecb4..022b1dcbb 100644
--- a/lib/mastodon/cli/email_domain_blocks.rb
+++ b/lib/mastodon/cli/email_domain_blocks.rb
@@ -7,10 +7,10 @@ module Mastodon::CLI
class EmailDomainBlocks < Base
desc 'list', 'List blocked e-mail domains'
def list
- EmailDomainBlock.where(parent_id: nil).order(id: 'DESC').find_each do |entry|
+ EmailDomainBlock.where(parent_id: nil).find_each do |entry|
say(entry.domain.to_s, :white)
- EmailDomainBlock.where(parent_id: entry.id).order(id: 'DESC').find_each do |child|
+ EmailDomainBlock.where(parent_id: entry.id).find_each do |child|
say(" #{child.domain}", :cyan)
end
end
diff --git a/lib/mastodon/cli/maintenance.rb b/lib/mastodon/cli/maintenance.rb
index c53d74254..553ca056d 100644
--- a/lib/mastodon/cli/maintenance.rb
+++ b/lib/mastodon/cli/maintenance.rb
@@ -346,7 +346,7 @@ module Mastodon::CLI
remove_index_if_exists!(:announcement_reactions, 'index_announcement_reactions_on_account_id_and_announcement_id')
- say 'Removing duplicate account identity proofs…'
+ say 'Removing duplicate announcement reactions…'
ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM announcement_reactions GROUP BY account_id, announcement_id, name HAVING count(*) > 1").each do |row|
AnnouncementReaction.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy)
end
@@ -431,7 +431,7 @@ module Mastodon::CLI
def deduplicate_domain_blocks!
remove_index_if_exists!(:domain_blocks, 'index_domain_blocks_on_domain')
- say 'Deduplicating domain_allows…'
+ say 'Deduplicating domain_blocks…'
ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM domain_blocks GROUP BY domain HAVING count(*) > 1").each do |row|
domain_blocks = DomainBlock.where(id: row['ids'].split(',')).by_severity.reverse.to_a
@@ -462,7 +462,7 @@ module Mastodon::CLI
UnavailableDomain.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy)
end
- say 'Restoring domain_allows indexes…'
+ say 'Restoring unavailable_domains indexes…'
ActiveRecord::Base.connection.add_index :unavailable_domains, ['domain'], name: 'index_unavailable_domains_on_domain', unique: true
end
@@ -712,7 +712,7 @@ module Mastodon::CLI
end
def remove_index_if_exists!(table, name)
- ActiveRecord::Base.connection.remove_index(table, name: name)
+ ActiveRecord::Base.connection.remove_index(table, name: name) if ActiveRecord::Base.connection.index_name_exists?(table, name)
rescue ArgumentError, ActiveRecord::StatementInvalid
nil
end
diff --git a/lib/mastodon/cli/statuses.rb b/lib/mastodon/cli/statuses.rb
index 0d6018a2b..7acf3f9b7 100644
--- a/lib/mastodon/cli/statuses.rb
+++ b/lib/mastodon/cli/statuses.rb
@@ -120,7 +120,7 @@ module Mastodon::CLI
say('Beginning removal of now-orphaned media attachments to free up disk space...')
- scope = MediaAttachment.reorder(nil).unattached.where('created_at < ?', options[:days].pred.days.ago)
+ scope = MediaAttachment.unattached.where('created_at < ?', options[:days].pred.days.ago)
processed = 0
removed = 0
progress = create_progress_bar(scope.count)
diff --git a/package.json b/package.json
index 543af8a4b..500d6d2cd 100644
--- a/package.json
+++ b/package.json
@@ -193,7 +193,7 @@
"eslint-plugin-jsx-a11y": "~6.8.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-promise": "~6.1.1",
- "eslint-plugin-react": "~7.33.0",
+ "eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.3",
"jest": "^29.5.0",
diff --git a/spec/controllers/admin/accounts_controller_spec.rb b/spec/controllers/admin/accounts_controller_spec.rb
index 307e81950..1882ea838 100644
--- a/spec/controllers/admin/accounts_controller_spec.rb
+++ b/spec/controllers/admin/accounts_controller_spec.rb
@@ -161,12 +161,13 @@ RSpec.describe Admin::AccountsController do
it 'logs action' do
expect(subject).to have_http_status 302
- log_item = Admin::ActionLog.last
-
- expect(log_item).to_not be_nil
- expect(log_item.action).to eq :approve
- expect(log_item.account_id).to eq current_user.account_id
- expect(log_item.target_id).to eq account.user.id
+ expect(latest_admin_action_log)
+ .to be_present
+ .and have_attributes(
+ action: eq(:approve),
+ account_id: eq(current_user.account_id),
+ target_id: eq(account.user.id)
+ )
end
end
@@ -201,12 +202,13 @@ RSpec.describe Admin::AccountsController do
it 'logs action' do
expect(subject).to have_http_status 302
- log_item = Admin::ActionLog.last
-
- expect(log_item).to_not be_nil
- expect(log_item.action).to eq :reject
- expect(log_item.account_id).to eq current_user.account_id
- expect(log_item.target_id).to eq account.user.id
+ expect(latest_admin_action_log)
+ .to be_present
+ .and have_attributes(
+ action: eq(:reject),
+ account_id: eq(current_user.account_id),
+ target_id: eq(account.user.id)
+ )
end
end
@@ -427,4 +429,10 @@ RSpec.describe Admin::AccountsController do
end
end
end
+
+ private
+
+ def latest_admin_action_log
+ Admin::ActionLog.last
+ end
end
diff --git a/spec/controllers/admin/action_logs_controller_spec.rb b/spec/controllers/admin/action_logs_controller_spec.rb
index b7854469d..be4222df0 100644
--- a/spec/controllers/admin/action_logs_controller_spec.rb
+++ b/spec/controllers/admin/action_logs_controller_spec.rb
@@ -9,11 +9,9 @@ describe Admin::ActionLogsController do
let!(:account) { Fabricate(:account) }
before do
- _orphaned_logs = %w(
- Account User UserRole Report DomainBlock DomainAllow
- EmailDomainBlock UnavailableDomain Status AccountWarning
- Announcement IpBlock Instance CustomEmoji CanonicalEmailBlock Appeal
- ).map { |type| Admin::ActionLog.new(account: account, action: 'destroy', target_type: type, target_id: 1312).save! }
+ orphaned_log_types.map do |type|
+ Fabricate(:action_log, account: account, action: 'destroy', target_type: type, target_id: 1312)
+ end
end
describe 'GET #index' do
@@ -24,4 +22,27 @@ describe Admin::ActionLogsController do
expect(response).to have_http_status(200)
end
end
+
+ private
+
+ def orphaned_log_types
+ %w(
+ Account
+ AccountWarning
+ Announcement
+ Appeal
+ CanonicalEmailBlock
+ CustomEmoji
+ DomainAllow
+ DomainBlock
+ EmailDomainBlock
+ Instance
+ IpBlock
+ Report
+ Status
+ UnavailableDomain
+ User
+ UserRole
+ )
+ end
end
diff --git a/spec/controllers/admin/domain_blocks_controller_spec.rb b/spec/controllers/admin/domain_blocks_controller_spec.rb
index 13826be36..22960f531 100644
--- a/spec/controllers/admin/domain_blocks_controller_spec.rb
+++ b/spec/controllers/admin/domain_blocks_controller_spec.rb
@@ -192,16 +192,11 @@ RSpec.describe Admin::DomainBlocksController do
let(:original_severity) { 'suspend' }
let(:new_severity) { 'silence' }
- it 'changes the block severity' do
- expect { subject }.to change { domain_block.reload.severity }.from('suspend').to('silence')
- end
-
- it 'undoes individual suspensions' do
- expect { subject }.to change { remote_account.reload.suspended? }.from(true).to(false)
- end
-
- it 'performs individual silences' do
- expect { subject }.to change { remote_account.reload.silenced? }.from(false).to(true)
+ it 'changes the block severity, suspensions, and silences' do
+ expect { subject }
+ .to change_severity('suspend', 'silence')
+ .and change_suspended(true, false)
+ .and change_silenced(false, true)
end
end
@@ -209,17 +204,26 @@ RSpec.describe Admin::DomainBlocksController do
let(:original_severity) { 'silence' }
let(:new_severity) { 'suspend' }
- it 'changes the block severity' do
- expect { subject }.to change { domain_block.reload.severity }.from('silence').to('suspend')
+ it 'changes the block severity, silences, and suspensions' do
+ expect { subject }
+ .to change_severity('silence', 'suspend')
+ .and change_silenced(true, false)
+ .and change_suspended(false, true)
end
+ end
- it 'undoes individual silences' do
- expect { subject }.to change { remote_account.reload.silenced? }.from(true).to(false)
- end
+ private
- it 'performs individual suspends' do
- expect { subject }.to change { remote_account.reload.suspended? }.from(false).to(true)
- end
+ def change_severity(from, to)
+ change { domain_block.reload.severity }.from(from).to(to)
+ end
+
+ def change_silenced(from, to)
+ change { remote_account.reload.silenced? }.from(from).to(to)
+ end
+
+ def change_suspended(from, to)
+ change { remote_account.reload.suspended? }.from(from).to(to)
end
end
diff --git a/spec/controllers/admin/export_domain_allows_controller_spec.rb b/spec/controllers/admin/export_domain_allows_controller_spec.rb
index e1e5ecc1f..0a2e34262 100644
--- a/spec/controllers/admin/export_domain_allows_controller_spec.rb
+++ b/spec/controllers/admin/export_domain_allows_controller_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Admin::ExportDomainAllowsController do
get :export, params: { format: :csv }
expect(response).to have_http_status(200)
- expect(response.body).to eq(File.read(File.join(file_fixture_path, 'domain_allows.csv')))
+ expect(response.body).to eq(domain_allows_csv_file)
end
end
@@ -40,7 +40,7 @@ RSpec.describe Admin::ExportDomainAllowsController do
# Domains should now be added
get :export, params: { format: :csv }
expect(response).to have_http_status(200)
- expect(response.body).to eq(File.read(File.join(file_fixture_path, 'domain_allows.csv')))
+ expect(response.body).to eq(domain_allows_csv_file)
end
it 'displays error on no file selected' do
@@ -49,4 +49,10 @@ RSpec.describe Admin::ExportDomainAllowsController do
expect(flash[:error]).to eq(I18n.t('admin.export_domain_allows.no_file'))
end
end
+
+ private
+
+ def domain_allows_csv_file
+ File.read(File.join(file_fixture_path, 'domain_allows.csv'))
+ end
end
diff --git a/spec/controllers/admin/export_domain_blocks_controller_spec.rb b/spec/controllers/admin/export_domain_blocks_controller_spec.rb
index 5a282c957..bfcccfa06 100644
--- a/spec/controllers/admin/export_domain_blocks_controller_spec.rb
+++ b/spec/controllers/admin/export_domain_blocks_controller_spec.rb
@@ -26,7 +26,13 @@ RSpec.describe Admin::ExportDomainBlocksController do
get :export, params: { format: :csv }
expect(response).to have_http_status(200)
- expect(response.body).to eq(File.read(File.join(file_fixture_path, 'domain_blocks.csv')))
+ expect(response.body).to eq(domain_blocks_csv_file)
+ end
+
+ private
+
+ def domain_blocks_csv_file
+ File.read(File.join(file_fixture_path, 'domain_blocks.csv'))
end
end
diff --git a/spec/controllers/api/v1/accounts/identity_proofs_controller_spec.rb b/spec/controllers/api/v1/accounts/identity_proofs_controller_spec.rb
deleted file mode 100644
index 6351de761..000000000
--- a/spec/controllers/api/v1/accounts/identity_proofs_controller_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Accounts::IdentityProofsController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
- let(:account) { Fabricate(:account) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index, params: { account_id: account.id, limit: 2 }
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/lists_controller_spec.rb b/spec/controllers/api/v1/accounts/lists_controller_spec.rb
deleted file mode 100644
index 418839cfa..000000000
--- a/spec/controllers/api/v1/accounts/lists_controller_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Accounts::ListsController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:lists') }
- let(:account) { Fabricate(:account) }
- let(:list) { Fabricate(:list, account: user.account) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- user.account.follow!(account)
- list.accounts << account
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index, params: { account_id: account.id }
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/lookup_controller_spec.rb b/spec/controllers/api/v1/accounts/lookup_controller_spec.rb
deleted file mode 100644
index 37407766f..000000000
--- a/spec/controllers/api/v1/accounts/lookup_controller_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Accounts::LookupController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
- let(:account) { Fabricate(:account) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show, params: { account_id: account.id, acct: account.acct }
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/pins_controller_spec.rb b/spec/controllers/api/v1/accounts/pins_controller_spec.rb
deleted file mode 100644
index 36f525e75..000000000
--- a/spec/controllers/api/v1/accounts/pins_controller_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::Accounts::PinsController do
- let(:john) { Fabricate(:user) }
- let(:kevin) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: john.id, scopes: 'write:accounts') }
-
- before do
- kevin.account.followers << john.account
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
- subject { post :create, params: { account_id: kevin.account.id } }
-
- it 'creates account_pin', :aggregate_failures do
- expect do
- subject
- end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(1)
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'DELETE #destroy' do
- subject { delete :destroy, params: { account_id: kevin.account.id } }
-
- before do
- Fabricate(:account_pin, account: john.account, target_account: kevin.account)
- end
-
- it 'destroys account_pin', :aggregate_failures do
- expect do
- subject
- end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(-1)
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/search_controller_spec.rb b/spec/controllers/api/v1/accounts/search_controller_spec.rb
deleted file mode 100644
index aa9455a4a..000000000
--- a/spec/controllers/api/v1/accounts/search_controller_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::Accounts::SearchController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show, params: { q: 'query' }
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/featured_tags/suggestions_controller_spec.rb b/spec/controllers/api/v1/featured_tags/suggestions_controller_spec.rb
deleted file mode 100644
index 54c63dcc6..000000000
--- a/spec/controllers/api/v1/featured_tags/suggestions_controller_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::FeaturedTags::SuggestionsController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
- let(:account) { Fabricate(:account) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index, params: { account_id: account.id, limit: 2 }
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v2/suggestions_controller_spec.rb b/spec/controllers/api/v2/suggestions_controller_spec.rb
deleted file mode 100644
index 5e6508bfd..000000000
--- a/spec/controllers/api/v2/suggestions_controller_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V2::SuggestionsController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/fixtures/files/elite-assets.tar.gz b/spec/fixtures/files/elite-assets.tar.gz
new file mode 100644
index 000000000..7b4f44257
Binary files /dev/null and b/spec/fixtures/files/elite-assets.tar.gz differ
diff --git a/spec/generators/post_deployment_migration_generator_spec.rb b/spec/generators/post_deployment_migration_generator_spec.rb
index d770a78e9..55e70a791 100644
--- a/spec/generators/post_deployment_migration_generator_spec.rb
+++ b/spec/generators/post_deployment_migration_generator_spec.rb
@@ -12,7 +12,7 @@ describe PostDeploymentMigrationGenerator, type: :generator do
include FileUtils
tests described_class
- destination File.expand_path('../../tmp', __dir__)
+ destination Rails.root.join('tmp', 'generator-test')
before { prepare_destination }
after { rm_rf(destination_root) }
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 3cc88014c..0a55770ba 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -29,15 +29,25 @@ describe ApplicationHelper do
describe 'body_classes' do
context 'with a body class string from a controller' do
- before do
- without_partial_double_verification do
- allow(helper).to receive_messages(body_class_string: 'modal-layout compose-standalone', current_theme: 'default', current_account: Fabricate(:account))
- end
- end
+ before { helper.extend controller_helpers }
it 'uses the controller body classes in the result' do
expect(helper.body_classes).to match(/modal-layout compose-standalone/)
end
+
+ private
+
+ def controller_helpers
+ Module.new do
+ def body_class_string = 'modal-layout compose-standalone'
+
+ def current_account
+ @current_account ||= Fabricate(:account)
+ end
+
+ def current_theme = 'default'
+ end
+ end
end
end
@@ -122,9 +132,7 @@ describe ApplicationHelper do
describe 'available_sign_up_path' do
context 'when registrations are closed' do
before do
- without_partial_double_verification do
- allow(Setting).to receive(:registrations_mode).and_return('none')
- end
+ allow(Setting).to receive(:[]).with('registrations_mode').and_return 'none'
end
it 'redirects to joinmastodon site' do
diff --git a/spec/helpers/home_helper_spec.rb b/spec/helpers/home_helper_spec.rb
index c6baec5a1..befc8a5c8 100644
--- a/spec/helpers/home_helper_spec.rb
+++ b/spec/helpers/home_helper_spec.rb
@@ -23,12 +23,19 @@ RSpec.describe HomeHelper do
context 'with a valid account' do
let(:account) { Fabricate(:account) }
- it 'returns a link to the account' do
- without_partial_double_verification do
- allow(helper).to receive_messages(current_account: account, prefers_autoplay?: false)
- result = helper.account_link_to(account)
+ before { helper.extend controller_helpers }
- expect(result).to match "@#{account.acct}"
+ it 'returns a link to the account' do
+ result = helper.account_link_to(account)
+
+ expect(result).to match "@#{account.acct}"
+ end
+
+ private
+
+ def controller_helpers
+ Module.new do
+ def current_account = Account.last
end
end
end
diff --git a/spec/helpers/media_component_helper_spec.rb b/spec/helpers/media_component_helper_spec.rb
index 149f6a83a..af5d92769 100644
--- a/spec/helpers/media_component_helper_spec.rb
+++ b/spec/helpers/media_component_helper_spec.rb
@@ -3,16 +3,12 @@
require 'rails_helper'
describe MediaComponentHelper do
+ before { helper.extend controller_helpers }
+
describe 'render_video_component' do
let(:media) { Fabricate(:media_attachment, type: :video, status: Fabricate(:status)) }
let(:result) { helper.render_video_component(media.status) }
- before do
- without_partial_double_verification do
- allow(helper).to receive(:current_account).and_return(media.account)
- end
- end
-
it 'renders a react component for the video' do
expect(parsed_html.div['data-component']).to eq('Video')
end
@@ -22,12 +18,6 @@ describe MediaComponentHelper do
let(:media) { Fabricate(:media_attachment, type: :audio, status: Fabricate(:status)) }
let(:result) { helper.render_audio_component(media.status) }
- before do
- without_partial_double_verification do
- allow(helper).to receive(:current_account).and_return(media.account)
- end
- end
-
it 'renders a react component for the audio' do
expect(parsed_html.div['data-component']).to eq('Audio')
end
@@ -37,12 +27,6 @@ describe MediaComponentHelper do
let(:media) { Fabricate(:media_attachment, type: :audio, status: Fabricate(:status)) }
let(:result) { helper.render_media_gallery_component(media.status) }
- before do
- without_partial_double_verification do
- allow(helper).to receive(:current_account).and_return(media.account)
- end
- end
-
it 'renders a react component for the media gallery' do
expect(parsed_html.div['data-component']).to eq('MediaGallery')
end
@@ -54,10 +38,6 @@ describe MediaComponentHelper do
before do
PreviewCardsStatus.create(status: status, preview_card: Fabricate(:preview_card))
-
- without_partial_double_verification do
- allow(helper).to receive(:current_account).and_return(status.account)
- end
end
it 'returns the correct react component markup' do
@@ -69,12 +49,6 @@ describe MediaComponentHelper do
let(:status) { Fabricate(:status, poll: Fabricate(:poll)) }
let(:result) { helper.render_poll_component(status) }
- before do
- without_partial_double_verification do
- allow(helper).to receive(:current_account).and_return(status.account)
- end
- end
-
it 'returns the correct react component markup' do
expect(parsed_html.div['data-component']).to eq('Poll')
end
@@ -85,4 +59,10 @@ describe MediaComponentHelper do
def parsed_html
Nokogiri::Slop(result)
end
+
+ def controller_helpers
+ Module.new do
+ def current_account = Account.last
+ end
+ end
end
diff --git a/spec/lib/mastodon/cli/accounts_spec.rb b/spec/lib/mastodon/cli/accounts_spec.rb
index 3216d0d1b..563f6e877 100644
--- a/spec/lib/mastodon/cli/accounts_spec.rb
+++ b/spec/lib/mastodon/cli/accounts_spec.rb
@@ -4,7 +4,11 @@ require 'rails_helper'
require 'mastodon/cli/accounts'
describe Mastodon::CLI::Accounts do
+ subject { cli.invoke(action, arguments, options) }
+
let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
it_behaves_like 'CLI Command'
@@ -27,25 +31,24 @@ describe Mastodon::CLI::Accounts do
end
describe '#create' do
+ let(:action) { :create }
+
shared_examples 'a new user with given email address and username' do
- it 'creates a new user with the specified email address' do
- cli.invoke(:create, arguments, options)
-
- expect(User.find_by(email: options[:email])).to be_present
- end
-
- it 'creates a new local account with the specified username' do
- cli.invoke(:create, arguments, options)
-
- expect(Account.find_local('tootctl_username')).to be_present
- end
-
- it 'returns "OK" and newly generated password' do
+ it 'creates user and accounts from options and displays success message' do
allow(SecureRandom).to receive(:hex).and_return('test_password')
- expect { cli.invoke(:create, arguments, options) }.to output(
- a_string_including("OK\nNew password: test_password")
- ).to_stdout
+ expect { subject }
+ .to output_results('OK', 'New password: test_password')
+ expect(user_from_options).to be_present
+ expect(account_from_options).to be_present
+ end
+
+ def user_from_options
+ User.find_by(email: options[:email])
+ end
+
+ def account_from_options
+ Account.find_local('tootctl_username')
end
end
@@ -61,9 +64,8 @@ describe Mastodon::CLI::Accounts do
let(:options) { { email: 'invalid' } }
it 'exits with an error message' do
- expect { cli.invoke(:create, arguments, options) }.to output(
- a_string_including('Failure/Error: email')
- ).to_stdout
+ expect { subject }
+ .to output_results('Failure/Error: email')
.and raise_error(SystemExit)
end
end
@@ -75,7 +77,7 @@ describe Mastodon::CLI::Accounts do
it_behaves_like 'a new user with given email address and username'
it 'creates a new user with confirmed status' do
- cli.invoke(:create, arguments, options)
+ subject
user = User.find_by(email: options[:email])
@@ -93,7 +95,7 @@ describe Mastodon::CLI::Accounts do
it_behaves_like 'a new user with given email address and username'
it 'creates a new user with approved status' do
- cli.invoke(:create, arguments, options)
+ subject
user = User.find_by(email: options[:email])
@@ -109,7 +111,7 @@ describe Mastodon::CLI::Accounts do
it_behaves_like 'a new user with given email address and username'
it 'creates a new user and assigns the specified role' do
- cli.invoke(:create, arguments, options)
+ subject
role = User.find_by(email: options[:email])&.role
@@ -121,9 +123,8 @@ describe Mastodon::CLI::Accounts do
let(:options) { { email: 'tootctl@example.com', role: '404' } }
it 'exits with an error message indicating the role name was not found' do
- expect { cli.invoke(:create, arguments, options) }.to output(
- a_string_including('Cannot find user role with that name')
- ).to_stdout
+ expect { subject }
+ .to output_results('Cannot find user role with that name')
.and raise_error(SystemExit)
end
end
@@ -139,16 +140,15 @@ describe Mastodon::CLI::Accounts do
end
it 'returns an error message indicating the username is already taken' do
- expect { cli.invoke(:create, arguments, options) }.to output(
- a_string_including("The chosen username is currently in use\nUse --force to reattach it anyway and delete the other user")
- ).to_stdout
+ expect { subject }
+ .to output_results("The chosen username is currently in use\nUse --force to reattach it anyway and delete the other user")
end
context 'with --force option' do
let(:options) { { email: 'tootctl_new@example.com', reattach: true, force: true } }
it 'reattaches the account to the new user and deletes the previous user' do
- cli.invoke(:create, arguments, options)
+ subject
user = Account.find_local('tootctl_username')&.user
@@ -173,20 +173,21 @@ describe Mastodon::CLI::Accounts do
let(:arguments) { ['tootctl_username'] }
it 'raises a required argument missing error (Thor::RequiredArgumentMissingError)' do
- expect { cli.invoke(:create, arguments) }
+ expect { subject }
.to raise_error(Thor::RequiredArgumentMissingError)
end
end
end
describe '#modify' do
+ let(:action) { :modify }
+
context 'when the given username is not found' do
let(:arguments) { ['non_existent_username'] }
it 'exits with an error message indicating the user was not found' do
- expect { cli.invoke(:modify, arguments) }.to output(
- a_string_including('No user with such username')
- ).to_stdout
+ expect { subject }
+ .to output_results('No user with such username')
.and raise_error(SystemExit)
end
end
@@ -196,15 +197,9 @@ describe Mastodon::CLI::Accounts do
let(:arguments) { [user.account.username] }
context 'when no option is provided' do
- it 'returns a successful message' do
- expect { cli.invoke(:modify, arguments) }.to output(
- a_string_including('OK')
- ).to_stdout
- end
-
- it 'does not modify the user' do
- cli.invoke(:modify, arguments)
-
+ it 'returns a successful message and preserves user' do
+ expect { subject }
+ .to output_results('OK')
expect(user).to eq(user.reload)
end
end
@@ -214,9 +209,8 @@ describe Mastodon::CLI::Accounts do
let(:options) { { role: '404' } }
it 'exits with an error message indicating the role was not found' do
- expect { cli.invoke(:modify, arguments, options) }.to output(
- a_string_including('Cannot find user role with that name')
- ).to_stdout
+ expect { subject }
+ .to output_results('Cannot find user role with that name')
.and raise_error(SystemExit)
end
end
@@ -226,7 +220,7 @@ describe Mastodon::CLI::Accounts do
let(:options) { { role: default_role.name } }
it "updates the user's role to the specified role" do
- cli.invoke(:modify, arguments, options)
+ subject
role = user.reload.role
@@ -241,7 +235,7 @@ describe Mastodon::CLI::Accounts do
let(:user) { Fabricate(:user, role: role) }
it "removes the user's role successfully" do
- cli.invoke(:modify, arguments, options)
+ subject
role = user.reload.role
@@ -254,13 +248,13 @@ describe Mastodon::CLI::Accounts do
let(:options) { { email: 'new_email@email.com' } }
it "sets the user's unconfirmed email to the provided email address" do
- cli.invoke(:modify, arguments, options)
+ subject
expect(user.reload.unconfirmed_email).to eq(options[:email])
end
it "does not update the user's original email address" do
- cli.invoke(:modify, arguments, options)
+ subject
expect(user.reload.email).to eq('old_email@email.com')
end
@@ -270,13 +264,13 @@ describe Mastodon::CLI::Accounts do
let(:options) { { email: 'new_email@email.com', confirm: true } }
it "updates the user's email address to the provided email" do
- cli.invoke(:modify, arguments, options)
+ subject
expect(user.reload.email).to eq(options[:email])
end
it "sets the user's email address as confirmed" do
- cli.invoke(:modify, arguments, options)
+ subject
expect(user.reload.confirmed?).to be(true)
end
@@ -288,7 +282,7 @@ describe Mastodon::CLI::Accounts do
let(:options) { { confirm: true } }
it "confirms the user's email address" do
- cli.invoke(:modify, arguments, options)
+ subject
expect(user.reload.confirmed?).to be(true)
end
@@ -303,7 +297,7 @@ describe Mastodon::CLI::Accounts do
end
it 'approves the user' do
- expect { cli.invoke(:modify, arguments, options) }.to change { user.reload.approved }.from(false).to(true)
+ expect { subject }.to change { user.reload.approved }.from(false).to(true)
end
end
@@ -312,7 +306,7 @@ describe Mastodon::CLI::Accounts do
let(:options) { { disable: true } }
it 'disables the user' do
- expect { cli.invoke(:modify, arguments, options) }.to change { user.reload.disabled }.from(false).to(true)
+ expect { subject }.to change { user.reload.disabled }.from(false).to(true)
end
end
@@ -321,7 +315,7 @@ describe Mastodon::CLI::Accounts do
let(:options) { { enable: true } }
it 'enables the user' do
- expect { cli.invoke(:modify, arguments, options) }.to change { user.reload.disabled }.from(true).to(false)
+ expect { subject }.to change { user.reload.disabled }.from(true).to(false)
end
end
@@ -331,9 +325,8 @@ describe Mastodon::CLI::Accounts do
it 'returns a new password for the user' do
allow(SecureRandom).to receive(:hex).and_return('new_password')
- expect { cli.invoke(:modify, arguments, options) }.to output(
- a_string_including('new_password')
- ).to_stdout
+ expect { subject }
+ .to output_results('new_password')
end
end
@@ -342,7 +335,7 @@ describe Mastodon::CLI::Accounts do
let(:options) { { disable_2fa: true } }
it 'disables the two-factor authentication for the user' do
- expect { cli.invoke(:modify, arguments, options) }.to change { user.reload.otp_required_for_login }.from(true).to(false)
+ expect { subject }.to change { user.reload.otp_required_for_login }.from(true).to(false)
end
end
@@ -351,9 +344,8 @@ describe Mastodon::CLI::Accounts do
let(:options) { { email: 'invalid' } }
it 'exits with an error message' do
- expect { cli.invoke(:modify, arguments, options) }.to output(
- a_string_including('Failure/Error: email')
- ).to_stdout
+ expect { subject }
+ .to output_results('Failure/Error: email')
.and raise_error(SystemExit)
end
end
@@ -361,9 +353,8 @@ describe Mastodon::CLI::Accounts do
end
describe '#delete' do
+ let(:action) { :delete }
let(:account) { Fabricate(:account) }
- let(:arguments) { [account.username] }
- let(:options) { { email: account.user.email } }
let(:delete_account_service) { instance_double(DeleteAccountService) }
before do
@@ -372,26 +363,29 @@ describe Mastodon::CLI::Accounts do
end
context 'when both username and --email are provided' do
+ let(:arguments) { [account.username] }
+ let(:options) { { email: account.user.email } }
+
it 'exits with an error message indicating that only one should be used' do
- expect { cli.invoke(:delete, arguments, options) }.to output(
- a_string_including('Use username or --email, not both')
- ).to_stdout
+ expect { subject }
+ .to output_results('Use username or --email, not both')
.and raise_error(SystemExit)
end
end
context 'when neither username nor --email are provided' do
it 'exits with an error message indicating that no username was provided' do
- expect { cli.invoke(:delete) }.to output(
- a_string_including('No username provided')
- ).to_stdout
+ expect { subject }
+ .to output_results('No username provided')
.and raise_error(SystemExit)
end
end
context 'when username is provided' do
+ let(:arguments) { [account.username] }
+
it 'deletes the specified user successfully' do
- cli.invoke(:delete, arguments)
+ subject
expect(delete_account_service).to have_received(:call).with(account, reserve_email: false).once
end
@@ -399,34 +393,29 @@ describe Mastodon::CLI::Accounts do
context 'with --dry-run option' do
let(:options) { { dry_run: true } }
- it 'does not delete the specified user' do
- cli.invoke(:delete, arguments, options)
-
+ it 'outputs a successful message in dry run mode and does not delete the user' do
+ expect { subject }
+ .to output_results('OK (DRY RUN)')
expect(delete_account_service).to_not have_received(:call).with(account, reserve_email: false)
end
-
- it 'outputs a successful message in dry run mode' do
- expect { cli.invoke(:delete, arguments, options) }.to output(
- a_string_including('OK (DRY RUN)')
- ).to_stdout
- end
end
context 'when the given username is not found' do
let(:arguments) { ['non_existent_username'] }
it 'exits with an error message indicating that no user was found' do
- expect { cli.invoke(:delete, arguments) }.to output(
- a_string_including('No user with such username')
- ).to_stdout
+ expect { subject }
+ .to output_results('No user with such username')
.and raise_error(SystemExit)
end
end
end
context 'when --email is provided' do
+ let(:options) { { email: account.user.email } }
+
it 'deletes the specified user successfully' do
- cli.invoke(:delete, nil, options)
+ subject
expect(delete_account_service).to have_received(:call).with(account, reserve_email: false).once
end
@@ -434,16 +423,12 @@ describe Mastodon::CLI::Accounts do
context 'with --dry-run option' do
let(:options) { { email: account.user.email, dry_run: true } }
- it 'does not delete the user' do
- cli.invoke(:delete, nil, options)
-
- expect(delete_account_service).to_not have_received(:call).with(account, reserve_email: false)
- end
-
- it 'outputs a successful message in dry run mode' do
- expect { cli.invoke(:delete, nil, options) }.to output(
- a_string_including('OK (DRY RUN)')
- ).to_stdout
+ it 'outputs a successful message in dry run mode and does not delete the user' do
+ expect { subject }
+ .to output_results('OK (DRY RUN)')
+ expect(delete_account_service)
+ .to_not have_received(:call)
+ .with(account, reserve_email: false)
end
end
@@ -451,9 +436,8 @@ describe Mastodon::CLI::Accounts do
let(:options) { { email: '404@example.com' } }
it 'exits with an error message indicating that no user was found' do
- expect { cli.invoke(:delete, nil, options) }.to output(
- a_string_including('No user with such email')
- ).to_stdout
+ expect { subject }
+ .to output_results('No user with such email')
.and raise_error(SystemExit)
end
end
@@ -461,6 +445,7 @@ describe Mastodon::CLI::Accounts do
end
describe '#approve' do
+ let(:action) { :approve }
let(:total_users) { 4 }
before do
@@ -469,8 +454,10 @@ describe Mastodon::CLI::Accounts do
end
context 'with --all option' do
+ let(:options) { { all: true } }
+
it 'approves all pending registrations' do
- cli.invoke(:approve, nil, all: true)
+ subject
expect(User.pluck(:approved).all?(true)).to be(true)
end
@@ -480,28 +467,28 @@ describe Mastodon::CLI::Accounts do
context 'when the number is positive' do
let(:options) { { number: 2 } }
- it 'approves the earliest n pending registrations' do
- cli.invoke(:approve, nil, options)
-
- n_earliest_pending_registrations = User.order(created_at: :asc).first(options[:number])
+ it 'approves the earliest n pending registrations but not the remaining ones' do
+ subject
expect(n_earliest_pending_registrations.all?(&:approved?)).to be(true)
+ expect(pending_registrations.all?(&:approved?)).to be(false)
end
- it 'does not approve the remaining pending registrations' do
- cli.invoke(:approve, nil, options)
+ def n_earliest_pending_registrations
+ User.order(created_at: :asc).first(options[:number])
+ end
- pending_registrations = User.order(created_at: :asc).last(total_users - options[:number])
-
- expect(pending_registrations.all?(&:approved?)).to be(false)
+ def pending_registrations
+ User.order(created_at: :asc).last(total_users - options[:number])
end
end
context 'when the number is negative' do
+ let(:options) { { number: -1 } }
+
it 'exits with an error message indicating that the number must be positive' do
- expect { cli.invoke(:approve, nil, number: -1) }.to output(
- a_string_including('Number must be positive')
- ).to_stdout
+ expect { subject }
+ .to output_results('Number must be positive')
.and raise_error(SystemExit)
end
end
@@ -509,15 +496,10 @@ describe Mastodon::CLI::Accounts do
context 'when the given number is greater than the number of users' do
let(:options) { { number: total_users * 2 } }
- it 'approves all users' do
- cli.invoke(:approve, nil, options)
-
- expect(User.pluck(:approved).all?(true)).to be(true)
- end
-
- it 'does not raise any error' do
- expect { cli.invoke(:approve, nil, options) }
+ it 'approves all users and does not raise any error' do
+ expect { subject }
.to_not raise_error
+ expect(User.pluck(:approved).all?(true)).to be(true)
end
end
end
@@ -528,7 +510,7 @@ describe Mastodon::CLI::Accounts do
let(:arguments) { [user.account.username] }
it 'approves the specified user successfully' do
- cli.invoke(:approve, arguments)
+ subject
expect(user.reload.approved?).to be(true)
end
@@ -538,9 +520,8 @@ describe Mastodon::CLI::Accounts do
let(:arguments) { ['non_existent_username'] }
it 'exits with an error message indicating that no such account was found' do
- expect { cli.invoke(:approve, arguments) }.to output(
- a_string_including('No such account')
- ).to_stdout
+ expect { subject }
+ .to output_results('No such account')
.and raise_error(SystemExit)
end
end
@@ -548,13 +529,14 @@ describe Mastodon::CLI::Accounts do
end
describe '#follow' do
+ let(:action) { :follow }
+
context 'when the given username is not found' do
let(:arguments) { ['non_existent_username'] }
it 'exits with an error message indicating that no account with the given username was found' do
- expect { cli.invoke(:follow, arguments) }.to output(
- a_string_including('No such account')
- ).to_stdout
+ expect { subject }
+ .to output_results('No such account')
.and raise_error(SystemExit)
end
end
@@ -565,36 +547,32 @@ describe Mastodon::CLI::Accounts do
let!(:follower_rony) { Fabricate(:account, username: 'rony') }
let!(:follower_charles) { Fabricate(:account, username: 'charles') }
let(:follow_service) { instance_double(FollowService, call: nil) }
+ let(:arguments) { [target_account.username] }
before do
allow(FollowService).to receive(:new).and_return(follow_service)
stub_parallelize_with_progress!
end
- it 'makes all local accounts follow the target account' do
- cli.follow(target_account.username)
-
+ it 'displays a successful message and makes all local accounts follow the target account' do
+ expect { subject }
+ .to output_results("OK, followed target from #{Account.local.count} accounts")
expect(follow_service).to have_received(:call).with(follower_bob, target_account, any_args).once
expect(follow_service).to have_received(:call).with(follower_rony, target_account, any_args).once
expect(follow_service).to have_received(:call).with(follower_charles, target_account, any_args).once
end
-
- it 'displays a successful message' do
- expect { cli.follow(target_account.username) }.to output(
- a_string_including("OK, followed target from #{Account.local.count} accounts")
- ).to_stdout
- end
end
end
describe '#unfollow' do
+ let(:action) { :unfollow }
+
context 'when the given username is not found' do
let(:arguments) { ['non_existent_username'] }
it 'exits with an error message indicating that no account with the given username was found' do
- expect { cli.invoke(:unfollow, arguments) }.to output(
- a_string_including('No such account')
- ).to_stdout
+ expect { subject }
+ .to output_results('No such account')
.and raise_error(SystemExit)
end
end
@@ -605,6 +583,7 @@ describe Mastodon::CLI::Accounts do
let!(:follower_rambo) { Fabricate(:account, username: 'rambo', domain: nil) }
let!(:follower_ana) { Fabricate(:account, username: 'ana', domain: nil) }
let(:unfollow_service) { instance_double(UnfollowService, call: nil) }
+ let(:arguments) { [target_account.username] }
before do
accounts = [follower_chris, follower_rambo, follower_ana]
@@ -613,30 +592,25 @@ describe Mastodon::CLI::Accounts do
stub_parallelize_with_progress!
end
- it 'makes all local accounts unfollow the target account' do
- cli.unfollow(target_account.username)
-
+ it 'displays a successful message and makes all local accounts unfollow the target account' do
+ expect { subject }
+ .to output_results('OK, unfollowed target from 3 accounts')
expect(unfollow_service).to have_received(:call).with(follower_chris, target_account).once
expect(unfollow_service).to have_received(:call).with(follower_rambo, target_account).once
expect(unfollow_service).to have_received(:call).with(follower_ana, target_account).once
end
-
- it 'displays a successful message' do
- expect { cli.unfollow(target_account.username) }.to output(
- a_string_including('OK, unfollowed target from 3 accounts')
- ).to_stdout
- end
end
end
describe '#backup' do
+ let(:action) { :backup }
+
context 'when the given username is not found' do
let(:arguments) { ['non_existent_username'] }
it 'exits with an error message indicating that there is no such account' do
- expect { cli.invoke(:backup, arguments) }.to output(
- a_string_including('No user with such username')
- ).to_stdout
+ expect { subject }
+ .to output_results('No user with such username')
.and raise_error(SystemExit)
end
end
@@ -646,23 +620,17 @@ describe Mastodon::CLI::Accounts do
let(:user) { account.user }
let(:arguments) { [account.username] }
- it 'creates a new backup for the specified user' do
- expect { cli.invoke(:backup, arguments) }.to change { user.backups.count }.by(1)
- end
-
- it 'creates a backup job' do
- allow(BackupWorker).to receive(:perform_async)
-
- cli.invoke(:backup, arguments)
- latest_backup = user.backups.last
+ before { allow(BackupWorker).to receive(:perform_async) }
+ it 'creates a new backup and backup job for the specified user and outputs success message' do
+ expect { subject }
+ .to change { user.backups.count }.by(1)
+ .and output_results('OK')
expect(BackupWorker).to have_received(:perform_async).with(latest_backup.id).once
end
- it 'displays a successful message' do
- expect { cli.invoke(:backup, arguments) }.to output(
- a_string_including('OK')
- ).to_stdout
+ def latest_backup
+ user.backups.last
end
end
end
@@ -724,9 +692,8 @@ describe Mastodon::CLI::Accounts do
end
it 'displays a successful message' do
- expect { cli.refresh }.to output(
- a_string_including('Refreshed 2 accounts')
- ).to_stdout
+ expect { cli.refresh }
+ .to output_results('Refreshed 2 accounts')
end
context 'with --dry-run option' do
@@ -761,9 +728,8 @@ describe Mastodon::CLI::Accounts do
end
it 'displays a successful message with (DRY RUN)' do
- expect { cli.refresh }.to output(
- a_string_including('Refreshed 2 accounts (DRY RUN)')
- ).to_stdout
+ expect { cli.refresh }
+ .to output_results('Refreshed 2 accounts (DRY RUN)')
end
end
end
@@ -823,9 +789,7 @@ describe Mastodon::CLI::Accounts do
allow(account_example_com_a).to receive(:reset_avatar!).and_raise(Mastodon::UnexpectedResponseError)
expect { cli.refresh(*arguments) }
- .to output(
- a_string_including("Account failed: #{account_example_com_a.username}@#{account_example_com_a.domain}")
- ).to_stdout
+ .to output_results("Account failed: #{account_example_com_a.username}@#{account_example_com_a.domain}")
end
end
@@ -833,9 +797,8 @@ describe Mastodon::CLI::Accounts do
it 'exits with an error message' do
allow(Account).to receive(:find_remote).with(account_example_com_b.username, account_example_com_b.domain).and_return(nil)
- expect { cli.refresh(*arguments) }.to output(
- a_string_including('No such account')
- ).to_stdout
+ expect { cli.refresh(*arguments) }
+ .to output_results('No such account')
.and raise_error(SystemExit)
end
end
@@ -878,7 +841,6 @@ describe Mastodon::CLI::Accounts do
allow(cli).to receive(:parallelize_with_progress).and_yield(account_example_com_a)
.and_yield(account_example_com_b)
.and_return([2, nil])
-
cli.options = { domain: domain }
end
@@ -925,32 +887,33 @@ describe Mastodon::CLI::Accounts do
context 'when neither a list of accts nor options are provided' do
it 'exits with an error message' do
- expect { cli.refresh }.to output(
- a_string_including('No account(s) given')
- ).to_stdout
+ expect { cli.refresh }
+ .to output_results('No account(s) given')
.and raise_error(SystemExit)
end
end
end
describe '#rotate' do
+ let(:action) { :rotate }
+
context 'when neither username nor --all option are given' do
it 'exits with an error message' do
- expect { cli.rotate }.to output(
- a_string_including('No account(s) given')
- ).to_stdout
+ expect { subject }
+ .to output_results('No account(s) given')
.and raise_error(SystemExit)
end
end
context 'when a username is given' do
let(:account) { Fabricate(:account) }
+ let(:arguments) { [account.username] }
it 'correctly rotates keys for the specified account' do
old_private_key = account.private_key
old_public_key = account.public_key
- cli.rotate(account.username)
+ subject
account.reload
expect(account.private_key).to_not eq(old_private_key)
@@ -960,34 +923,31 @@ describe Mastodon::CLI::Accounts do
it 'broadcasts the new keys for the specified account' do
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_in)
- cli.rotate(account.username)
+ subject
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_in).with(anything, account.id, anything).once
end
+ end
- context 'when the given username is not found' do
- it 'exits with an error message when the specified username is not found' do
- expect { cli.rotate('non_existent_username') }.to output(
- a_string_including('No such account')
- ).to_stdout
- .and raise_error(SystemExit)
- end
+ context 'when the given username is not found' do
+ let(:arguments) { ['non_existent_username'] }
+
+ it 'exits with an error message when the specified username is not found' do
+ expect { subject }
+ .to output_results('No such account')
+ .and raise_error(SystemExit)
end
end
context 'when --all option is provided' do
let!(:accounts) { Fabricate.times(2, :account) }
- let(:options) { { all: true } }
-
- before do
- cli.options = { all: true }
- end
+ let(:options) { { all: true } }
it 'correctly rotates keys for all local accounts' do
old_private_keys = accounts.map(&:private_key)
old_public_keys = accounts.map(&:public_key)
- cli.rotate
+ subject
accounts.each(&:reload)
expect(accounts.map(&:private_key)).to_not eq(old_private_keys)
@@ -997,7 +957,7 @@ describe Mastodon::CLI::Accounts do
it 'broadcasts the new keys for each account' do
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_in)
- cli.rotate
+ subject
accounts.each do |account|
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_in).with(anything, account.id, anything).once
@@ -1007,11 +967,12 @@ describe Mastodon::CLI::Accounts do
end
describe '#merge' do
+ let(:action) { :merge }
+
shared_examples 'an account not found' do |acct|
it 'exits with an error message indicating that there is no such account' do
- expect { cli.invoke(:merge, arguments) }.to output(
- a_string_including("No such account (#{acct})")
- ).to_stdout
+ expect { subject }
+ .to output_results("No such account (#{acct})")
.and raise_error(SystemExit)
end
end
@@ -1061,9 +1022,8 @@ describe Mastodon::CLI::Accounts do
end
it 'exits with an error message indicating that the accounts do not have the same pub key' do
- expect { cli.invoke(:merge, arguments) }.to output(
- a_string_including("Accounts don't have the same public key, might not be duplicates!\nOverride with --force")
- ).to_stdout
+ expect { subject }
+ .to output_results("Accounts don't have the same public key, might not be duplicates!\nOverride with --force")
.and raise_error(SystemExit)
end
@@ -1075,15 +1035,10 @@ describe Mastodon::CLI::Accounts do
allow(from_account).to receive(:destroy)
end
- it 'merges "from_account" into "to_account"' do
- cli.invoke(:merge, arguments, options)
+ it 'merges `from_account` into `to_account` and deletes `from_account`' do
+ subject
expect(to_account).to have_received(:merge_with!).with(from_account).once
- end
-
- it 'deletes "from_account"' do
- cli.invoke(:merge, arguments, options)
-
expect(from_account).to have_received(:destroy).once
end
end
@@ -1103,21 +1058,17 @@ describe Mastodon::CLI::Accounts do
allow(from_account).to receive(:destroy)
end
- it 'merges "from_account" into "to_account"' do
- cli.invoke(:merge, arguments)
+ it 'merges "from_account" into "to_account" and deletes from_account' do
+ subject
expect(to_account).to have_received(:merge_with!).with(from_account).once
- end
-
- it 'deletes "from_account"' do
- cli.invoke(:merge, arguments)
-
expect(from_account).to have_received(:destroy)
end
end
end
describe '#cull' do
+ let(:action) { :cull }
let(:delete_account_service) { instance_double(DeleteAccountService, call: nil) }
let!(:tom) { Fabricate(:account, updated_at: 30.days.ago, username: 'tom', uri: 'https://example.com/users/tom', domain: 'example.com', protocol: :activitypub) }
let!(:bob) { Fabricate(:account, updated_at: 30.days.ago, last_webfingered_at: nil, username: 'bob', uri: 'https://example.org/users/bob', domain: 'example.org', protocol: :activitypub) }
@@ -1137,34 +1088,28 @@ describe Mastodon::CLI::Accounts do
stub_request(:head, 'https://example.net/users/tales').to_return(status: 200)
end
- it 'deletes all inactive remote accounts that longer exist in the origin server' do
- cli.cull
-
+ def expect_delete_inactive_remote_accounts
expect(delete_account_service).to have_received(:call).with(bob, reserve_username: false).once
expect(delete_account_service).to have_received(:call).with(gon, reserve_username: false).once
end
- it 'does not delete any active remote account that still exists in the origin server' do
- cli.cull
-
+ def expect_not_delete_active_accounts
expect(delete_account_service).to_not have_received(:call).with(tom, reserve_username: false)
expect(delete_account_service).to_not have_received(:call).with(ana, reserve_username: false)
expect(delete_account_service).to_not have_received(:call).with(tales, reserve_username: false)
end
- it 'touches inactive remote accounts that have not been deleted' do
- expect { cli.cull }.to(change { tales.reload.updated_at })
- end
-
- it 'displays the summary correctly' do
- expect { cli.cull }.to output(
- a_string_including('Visited 5 accounts, removed 2')
- ).to_stdout
+ it 'touches inactive remote accounts that have not been deleted and summarizes activity' do
+ expect { subject }
+ .to change { tales.reload.updated_at }
+ .and output_results('Visited 5 accounts, removed 2')
+ expect_delete_inactive_remote_accounts
+ expect_not_delete_active_accounts
end
end
context 'when a domain is specified' do
- let(:domain) { 'example.net' }
+ let(:arguments) { ['example.net'] }
before do
stub_parallelize_with_progress!
@@ -1172,17 +1117,15 @@ describe Mastodon::CLI::Accounts do
stub_request(:head, 'https://example.net/users/tales').to_return(status: 404)
end
- it 'deletes inactive remote accounts that longer exist in the specified domain' do
- cli.cull(domain)
-
+ def expect_delete_inactive_remote_accounts
expect(delete_account_service).to have_received(:call).with(gon, reserve_username: false).once
expect(delete_account_service).to have_received(:call).with(tales, reserve_username: false).once
end
- it 'displays the summary correctly' do
- expect { cli.cull(domain) }.to output(
- a_string_including('Visited 2 accounts, removed 2')
- ).to_stdout
+ it 'displays the summary correctly and deletes inactive remote accounts' do
+ expect { subject }
+ .to output_results('Visited 2 accounts, removed 2')
+ expect_delete_inactive_remote_accounts
end
end
@@ -1194,16 +1137,14 @@ describe Mastodon::CLI::Accounts do
stub_request(:head, 'https://example.net/users/gon').to_return(status: 200)
end
- it 'skips accounts from the unavailable domain' do
- cli.cull
-
+ def expect_skip_accounts_from_unavailable_domain
expect(delete_account_service).to_not have_received(:call).with(tales, reserve_username: false)
end
- it 'displays the summary correctly' do
- expect { cli.cull }.to output(
- a_string_including("Visited 5 accounts, removed 0\nThe following domains were not available during the check:\n example.net")
- ).to_stdout
+ it 'displays the summary correctly and skip accounts from unavailable domains' do
+ expect { subject }
+ .to output_results("Visited 5 accounts, removed 0\nThe following domains were not available during the check:\n example.net")
+ expect_skip_accounts_from_unavailable_domain
end
end
@@ -1242,25 +1183,25 @@ describe Mastodon::CLI::Accounts do
end
describe '#reset_relationships' do
+ let(:action) { :reset_relationships }
let(:target_account) { Fabricate(:account) }
let(:arguments) { [target_account.username] }
context 'when no option is given' do
it 'exits with an error message indicating that at least one option is required' do
- expect { cli.invoke(:reset_relationships, arguments) }.to output(
- a_string_including('Please specify either --follows or --followers, or both')
- ).to_stdout
+ expect { subject }
+ .to output_results('Please specify either --follows or --followers, or both')
.and raise_error(SystemExit)
end
end
context 'when the given username is not found' do
let(:arguments) { ['non_existent_username'] }
+ let(:options) { { follows: true } }
it 'exits with an error message indicating that there is no such account' do
- expect { cli.invoke(:reset_relationships, arguments, follows: true) }.to output(
- a_string_including('No such account')
- ).to_stdout
+ expect { subject }
+ .to output_results('No such account')
.and raise_error(SystemExit)
end
end
@@ -1274,26 +1215,14 @@ describe Mastodon::CLI::Accounts do
before do
accounts.each { |account| target_account.follow!(account) }
- end
-
- it 'resets all "following" relationships from the target account' do
- cli.invoke(:reset_relationships, arguments, options)
-
- expect(target_account.reload.following).to be_empty
- end
-
- it 'calls BootstrapTimelineWorker once to rebuild the timeline' do
allow(BootstrapTimelineWorker).to receive(:perform_async)
-
- cli.invoke(:reset_relationships, arguments, options)
-
- expect(BootstrapTimelineWorker).to have_received(:perform_async).with(target_account.id).once
end
- it 'displays a successful message' do
- expect { cli.invoke(:reset_relationships, arguments, options) }.to output(
- a_string_including("Processed #{total_relationships} relationships")
- ).to_stdout
+ it 'resets following relationships and displays a successful message and rebuilds timeline' do
+ expect { subject }
+ .to output_results("Processed #{total_relationships} relationships")
+ expect(target_account.reload.following).to be_empty
+ expect(BootstrapTimelineWorker).to have_received(:perform_async).with(target_account.id).once
end
end
@@ -1304,17 +1233,11 @@ describe Mastodon::CLI::Accounts do
accounts.each { |account| account.follow!(target_account) }
end
- it 'resets all "followers" relationships from the target account' do
- cli.invoke(:reset_relationships, arguments, options)
-
+ it 'resets followers relationships and displays a successful message' do
+ expect { subject }
+ .to output_results("Processed #{total_relationships} relationships")
expect(target_account.reload.followers).to be_empty
end
-
- it 'displays a successful message' do
- expect { cli.invoke(:reset_relationships, arguments, options) }.to output(
- a_string_including("Processed #{total_relationships} relationships")
- ).to_stdout
- end
end
context 'with --follows and --followers options' do
@@ -1323,38 +1246,22 @@ describe Mastodon::CLI::Accounts do
before do
accounts.first(2).each { |account| account.follow!(target_account) }
accounts.last(1).each { |account| target_account.follow!(account) }
- end
-
- it 'resets all "followers" relationships from the target account' do
- cli.invoke(:reset_relationships, arguments, options)
-
- expect(target_account.reload.followers).to be_empty
- end
-
- it 'resets all "following" relationships from the target account' do
- cli.invoke(:reset_relationships, arguments, options)
-
- expect(target_account.reload.following).to be_empty
- end
-
- it 'calls BootstrapTimelineWorker once to rebuild the timeline' do
allow(BootstrapTimelineWorker).to receive(:perform_async)
-
- cli.invoke(:reset_relationships, arguments, options)
-
- expect(BootstrapTimelineWorker).to have_received(:perform_async).with(target_account.id).once
end
- it 'displays a successful message' do
- expect { cli.invoke(:reset_relationships, arguments, options) }.to output(
- a_string_including("Processed #{total_relationships} relationships")
- ).to_stdout
+ it 'resets followers and following and displays a successful message and rebuilds timeline' do
+ expect { subject }
+ .to output_results("Processed #{total_relationships} relationships")
+ expect(target_account.reload.followers).to be_empty
+ expect(target_account.reload.following).to be_empty
+ expect(BootstrapTimelineWorker).to have_received(:perform_async).with(target_account.id).once
end
end
end
end
describe '#prune' do
+ let(:action) { :prune }
let!(:local_account) { Fabricate(:account) }
let!(:bot_account) { Fabricate(:account, bot: true, domain: 'example.com') }
let!(:group_account) { Fabricate(:account, actor_type: 'Group', domain: 'example.com') }
@@ -1368,66 +1275,57 @@ describe Mastodon::CLI::Accounts do
stub_parallelize_with_progress!
end
- it 'prunes all remote accounts with no interactions with local users' do
- cli.prune
-
+ def expect_prune_remote_accounts_without_interaction
prunable_account_ids = prunable_accounts.pluck(:id)
expect(Account.where(id: prunable_account_ids).count).to eq(0)
end
- it 'displays a successful message' do
- expect { cli.prune }.to output(
- a_string_including("OK, pruned #{prunable_accounts.size} accounts")
- ).to_stdout
+ it 'displays a successful message and handles accounts correctly' do
+ expect { subject }
+ .to output_results("OK, pruned #{prunable_accounts.size} accounts")
+ expect_prune_remote_accounts_without_interaction
+ expect_not_prune_local_accounts
+ expect_not_prune_bot_accounts
+ expect_not_prune_group_accounts
+ expect_not_prune_mentioned_accounts
end
- it 'does not prune local accounts' do
- cli.prune
-
+ def expect_not_prune_local_accounts
expect(Account.exists?(id: local_account.id)).to be(true)
end
- it 'does not prune bot accounts' do
- cli.prune
-
+ def expect_not_prune_bot_accounts
expect(Account.exists?(id: bot_account.id)).to be(true)
end
- it 'does not prune group accounts' do
- cli.prune
-
+ def expect_not_prune_group_accounts
expect(Account.exists?(id: group_account.id)).to be(true)
end
- it 'does not prune accounts that have been mentioned' do
- cli.prune
-
+ def expect_not_prune_mentioned_accounts
expect(Account.exists?(id: mentioned_account.id)).to be true
end
context 'with --dry-run option' do
- before do
- cli.options = { dry_run: true }
- end
-
- it 'does not prune any account' do
- cli.prune
+ let(:options) { { dry_run: true } }
+ def expect_no_account_prunes
prunable_account_ids = prunable_accounts.pluck(:id)
expect(Account.where(id: prunable_account_ids).count).to eq(prunable_accounts.size)
end
- it 'displays a successful message with (DRY RUN)' do
- expect { cli.prune }.to output(
- a_string_including("OK, pruned #{prunable_accounts.size} accounts (DRY RUN)")
- ).to_stdout
+ it 'displays a successful message with (DRY RUN) and doesnt prune anything' do
+ expect { subject }
+ .to output_results("OK, pruned #{prunable_accounts.size} accounts (DRY RUN)")
+ expect_no_account_prunes
end
end
end
describe '#migrate' do
+ let(:action) { :migrate }
let!(:source_account) { Fabricate(:account) }
let!(:target_account) { Fabricate(:account, domain: 'example.com') }
let(:arguments) { [source_account.username] }
@@ -1441,7 +1339,7 @@ describe Mastodon::CLI::Accounts do
shared_examples 'a successful migration' do
it 'calls the MoveService for the last migration' do
- cli.invoke(:migrate, arguments, options)
+ subject
last_migration = source_account.migrations.last
@@ -1449,9 +1347,8 @@ describe Mastodon::CLI::Accounts do
end
it 'displays a successful message' do
- expect { cli.invoke(:migrate, arguments, options) }.to output(
- a_string_including("OK, migrated #{source_account.acct} to #{target_account.acct}")
- ).to_stdout
+ expect { subject }
+ .to output_results("OK, migrated #{source_account.acct} to #{target_account.acct}")
end
end
@@ -1459,29 +1356,27 @@ describe Mastodon::CLI::Accounts do
let(:options) { { replay: true, target: "#{target_account.username}@example.com" } }
it 'exits with an error message indicating that using both options is not possible' do
- expect { cli.invoke(:migrate, arguments, options) }.to output(
- a_string_including('Use --replay or --target, not both')
- ).to_stdout
+ expect { subject }
+ .to output_results('Use --replay or --target, not both')
.and raise_error(SystemExit)
end
end
context 'when no option is given' do
it 'exits with an error message indicating that at least one option must be used' do
- expect { cli.invoke(:migrate, arguments, {}) }.to output(
- a_string_including('Use either --replay or --target')
- ).to_stdout
+ expect { subject }
+ .to output_results('Use either --replay or --target')
.and raise_error(SystemExit)
end
end
context 'when the given username is not found' do
let(:arguments) { ['non_existent_username'] }
+ let(:options) { { replay: true } }
it 'exits with an error message indicating that there is no such account' do
- expect { cli.invoke(:migrate, arguments, replay: true) }.to output(
- a_string_including("No such account: #{arguments.first}")
- ).to_stdout
+ expect { subject }
+ .to output_results("No such account: #{arguments.first}")
.and raise_error(SystemExit)
end
end
@@ -1491,9 +1386,8 @@ describe Mastodon::CLI::Accounts do
context 'when the specified account has no previous migrations' do
it 'exits with an error message indicating that the given account has no previous migrations' do
- expect { cli.invoke(:migrate, arguments, options) }.to output(
- a_string_including('The specified account has not performed any migration')
- ).to_stdout
+ expect { subject }
+ .to output_results('The specified account has not performed any migration')
.and raise_error(SystemExit)
end
end
@@ -1515,9 +1409,8 @@ describe Mastodon::CLI::Accounts do
end
it 'exits with an error message' do
- expect { cli.invoke(:migrate, arguments, options) }.to output(
- a_string_including('The specified account is not redirecting to its last migration target. Use --force if you want to replay the migration anyway')
- ).to_stdout
+ expect { subject }
+ .to output_results('The specified account is not redirecting to its last migration target. Use --force if you want to replay the migration anyway')
.and raise_error(SystemExit)
end
end
@@ -1544,9 +1437,8 @@ describe Mastodon::CLI::Accounts do
end
it 'exits with an error message indicating that there is no such account' do
- expect { cli.invoke(:migrate, arguments, options) }.to output(
- a_string_including("The specified target account could not be found: #{options[:target]}")
- ).to_stdout
+ expect { subject }
+ .to output_results("The specified target account could not be found: #{options[:target]}")
.and raise_error(SystemExit)
end
end
@@ -1557,7 +1449,7 @@ describe Mastodon::CLI::Accounts do
end
it 'creates a migration for the specified account with the target account' do
- cli.invoke(:migrate, arguments, options)
+ subject
last_migration = source_account.migrations.last
@@ -1569,9 +1461,8 @@ describe Mastodon::CLI::Accounts do
context 'when the migration record is invalid' do
it 'exits with an error indicating that the validation failed' do
- expect { cli.invoke(:migrate, arguments, options) }.to output(
- a_string_including('Error: Validation failed')
- ).to_stdout
+ expect { subject }
+ .to output_results('Error: Validation failed')
.and raise_error(SystemExit)
end
end
@@ -1582,9 +1473,8 @@ describe Mastodon::CLI::Accounts do
end
it 'exits with an error message' do
- expect { cli.invoke(:migrate, arguments, options) }.to output(
- a_string_including('The specified account is redirecting to a different target account. Use --force if you want to change the migration target')
- ).to_stdout
+ expect { subject }
+ .to output_results('The specified account is redirecting to a different target account. Use --force if you want to change the migration target')
.and raise_error(SystemExit)
end
end
diff --git a/spec/lib/mastodon/cli/cache_spec.rb b/spec/lib/mastodon/cli/cache_spec.rb
index c1ce04710..b1515801e 100644
--- a/spec/lib/mastodon/cli/cache_spec.rb
+++ b/spec/lib/mastodon/cli/cache_spec.rb
@@ -4,22 +4,29 @@ require 'rails_helper'
require 'mastodon/cli/cache'
describe Mastodon::CLI::Cache do
+ subject { cli.invoke(action, arguments, options) }
+
let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#clear' do
+ let(:action) { :clear }
+
before { allow(Rails.cache).to receive(:clear) }
it 'clears the Rails cache' do
- expect { cli.invoke(:clear) }.to output(
- a_string_including('OK')
- ).to_stdout
+ expect { subject }
+ .to output_results('OK')
expect(Rails.cache).to have_received(:clear)
end
end
describe '#recount' do
+ let(:action) { :recount }
+
context 'with the `accounts` argument' do
let(:arguments) { ['accounts'] }
let(:account_stat) { Fabricate(:account_stat) }
@@ -29,9 +36,8 @@ describe Mastodon::CLI::Cache do
end
it 're-calculates account records in the cache' do
- expect { cli.invoke(:recount, arguments) }.to output(
- a_string_including('OK')
- ).to_stdout
+ expect { subject }
+ .to output_results('OK')
expect(account_stat.reload.statuses_count).to be_zero
end
@@ -46,9 +52,8 @@ describe Mastodon::CLI::Cache do
end
it 're-calculates account records in the cache' do
- expect { cli.invoke(:recount, arguments) }.to output(
- a_string_including('OK')
- ).to_stdout
+ expect { subject }
+ .to output_results('OK')
expect(status_stat.reload.replies_count).to be_zero
end
@@ -58,9 +63,9 @@ describe Mastodon::CLI::Cache do
let(:arguments) { ['other-type'] }
it 'Exits with an error message' do
- expect { cli.invoke(:recount, arguments) }.to output(
- a_string_including('Unknown')
- ).to_stdout.and raise_error(SystemExit)
+ expect { subject }
+ .to output_results('Unknown')
+ .and raise_error(SystemExit)
end
end
end
diff --git a/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb b/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb
index 6e4675748..1745ea01b 100644
--- a/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb
+++ b/spec/lib/mastodon/cli/canonical_email_blocks_spec.rb
@@ -4,42 +4,45 @@ require 'rails_helper'
require 'mastodon/cli/canonical_email_blocks'
describe Mastodon::CLI::CanonicalEmailBlocks do
+ subject { cli.invoke(action, arguments, options) }
+
let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#find' do
+ let(:action) { :find }
let(:arguments) { ['user@example.com'] }
context 'when a block is present' do
before { Fabricate(:canonical_email_block, email: 'user@example.com') }
it 'announces the presence of the block' do
- expect { cli.invoke(:find, arguments) }.to output(
- a_string_including('user@example.com is blocked')
- ).to_stdout
+ expect { subject }
+ .to output_results('user@example.com is blocked')
end
end
context 'when a block is not present' do
it 'announces the absence of the block' do
- expect { cli.invoke(:find, arguments) }.to output(
- a_string_including('user@example.com is not blocked')
- ).to_stdout
+ expect { subject }
+ .to output_results('user@example.com is not blocked')
end
end
end
describe '#remove' do
+ let(:action) { :remove }
let(:arguments) { ['user@example.com'] }
context 'when a block is present' do
before { Fabricate(:canonical_email_block, email: 'user@example.com') }
it 'removes the block' do
- expect { cli.invoke(:remove, arguments) }.to output(
- a_string_including('Unblocked user@example.com')
- ).to_stdout
+ expect { subject }
+ .to output_results('Unblocked user@example.com')
expect(CanonicalEmailBlock.matching_email('user@example.com')).to be_empty
end
@@ -47,9 +50,8 @@ describe Mastodon::CLI::CanonicalEmailBlocks do
context 'when a block is not present' do
it 'announces the absence of the block' do
- expect { cli.invoke(:remove, arguments) }.to output(
- a_string_including('user@example.com is not blocked')
- ).to_stdout
+ expect { subject }
+ .to output_results('user@example.com is not blocked')
end
end
end
diff --git a/spec/lib/mastodon/cli/domains_spec.rb b/spec/lib/mastodon/cli/domains_spec.rb
index 765b63e2a..24f341c12 100644
--- a/spec/lib/mastodon/cli/domains_spec.rb
+++ b/spec/lib/mastodon/cli/domains_spec.rb
@@ -4,5 +4,75 @@ require 'rails_helper'
require 'mastodon/cli/domains'
describe Mastodon::CLI::Domains do
+ subject { cli.invoke(action, arguments, options) }
+
+ let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
+
it_behaves_like 'CLI Command'
+
+ describe '#purge' do
+ let(:action) { :purge }
+
+ context 'with accounts from the domain' do
+ let(:domain) { 'host.example' }
+ let!(:account) { Fabricate(:account, domain: domain) }
+ let(:arguments) { [domain] }
+
+ it 'removes the account' do
+ expect { subject }
+ .to output_results('Removed 1 accounts')
+
+ expect { account.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+
+ describe '#crawl' do
+ let(:action) { :crawl }
+
+ context 'with accounts from the domain' do
+ let(:domain) { 'host.example' }
+
+ before do
+ Fabricate(:account, domain: domain)
+ stub_request(:get, 'https://host.example/api/v1/instance').to_return(status: 200, body: {}.to_json)
+ stub_request(:get, 'https://host.example/api/v1/instance/peers').to_return(status: 200, body: {}.to_json)
+ stub_request(:get, 'https://host.example/api/v1/instance/activity').to_return(status: 200, body: {}.to_json)
+ stub_const('Mastodon::CLI::Domains::CRAWL_SLEEP_TIME', 0)
+ end
+
+ context 'with --format of summary' do
+ let(:options) { { format: 'summary' } }
+
+ it 'crawls the domains and summarizes results' do
+ expect { subject }
+ .to output_results('Visited 1 domains, 0 failed')
+ end
+ end
+
+ context 'with --format of domains' do
+ let(:options) { { format: 'domains' } }
+
+ it 'crawls the domains and summarizes results' do
+ expect { subject }
+ .to output_results(domain)
+ end
+ end
+
+ context 'with --format of json' do
+ let(:options) { { format: 'json' } }
+
+ it 'crawls the domains and summarizes results' do
+ expect { subject }
+ .to output_results(json_summary)
+ end
+
+ def json_summary
+ Oj.dump('host.example': { activity: {} })
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb
index 060943b18..13deb05b6 100644
--- a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb
+++ b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb
@@ -4,5 +4,101 @@ require 'rails_helper'
require 'mastodon/cli/email_domain_blocks'
describe Mastodon::CLI::EmailDomainBlocks do
+ subject { cli.invoke(action, arguments, options) }
+
+ let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
+
it_behaves_like 'CLI Command'
+
+ describe '#list' do
+ let(:action) { :list }
+
+ context 'with email domain block records' do
+ let!(:parent_block) { Fabricate(:email_domain_block) }
+ let!(:child_block) { Fabricate(:email_domain_block, parent: parent_block) }
+
+ it 'lists the blocks' do
+ expect { subject }
+ .to output_results(
+ parent_block.domain,
+ child_block.domain
+ )
+ end
+ end
+ end
+
+ describe '#add' do
+ let(:action) { :add }
+
+ context 'without any options' do
+ it 'warns about usage and exits' do
+ expect { subject }
+ .to output_results('No domain(s) given')
+ .and raise_error(SystemExit)
+ end
+ end
+
+ context 'when blocks exist' do
+ let(:options) { {} }
+ let(:domain) { 'host.example' }
+ let(:arguments) { [domain] }
+
+ before { Fabricate(:email_domain_block, domain: domain) }
+
+ it 'does not add a new block' do
+ expect { subject }
+ .to output_results('is already blocked')
+ .and(not_change(EmailDomainBlock, :count))
+ end
+ end
+
+ context 'when no blocks exist' do
+ let(:domain) { 'host.example' }
+ let(:arguments) { [domain] }
+
+ it 'adds a new block' do
+ expect { subject }
+ .to output_results('Added 1')
+ .and(change(EmailDomainBlock, :count).by(1))
+ end
+ end
+ end
+
+ describe '#remove' do
+ let(:action) { :remove }
+
+ context 'without any options' do
+ it 'warns about usage and exits' do
+ expect { subject }
+ .to output_results('No domain(s) given')
+ .and raise_error(SystemExit)
+ end
+ end
+
+ context 'when blocks exist' do
+ let(:domain) { 'host.example' }
+ let(:arguments) { [domain] }
+
+ before { Fabricate(:email_domain_block, domain: domain) }
+
+ it 'removes the block' do
+ expect { subject }
+ .to output_results('Removed 1')
+ .and(change(EmailDomainBlock, :count).by(-1))
+ end
+ end
+
+ context 'when no blocks exist' do
+ let(:domain) { 'host.example' }
+ let(:arguments) { [domain] }
+
+ it 'does not remove a block' do
+ expect { subject }
+ .to output_results('is not yet blocked')
+ .and(not_change(EmailDomainBlock, :count))
+ end
+ end
+ end
end
diff --git a/spec/lib/mastodon/cli/emoji_spec.rb b/spec/lib/mastodon/cli/emoji_spec.rb
index 5d109eb52..d05e972e7 100644
--- a/spec/lib/mastodon/cli/emoji_spec.rb
+++ b/spec/lib/mastodon/cli/emoji_spec.rb
@@ -4,5 +4,61 @@ require 'rails_helper'
require 'mastodon/cli/emoji'
describe Mastodon::CLI::Emoji do
+ subject { cli.invoke(action, arguments, options) }
+
+ let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
+
it_behaves_like 'CLI Command'
+
+ describe '#purge' do
+ let(:action) { :purge }
+
+ context 'with existing custom emoji' do
+ before { Fabricate(:custom_emoji) }
+
+ it 'reports a successful purge' do
+ expect { subject }
+ .to output_results('OK')
+ end
+ end
+ end
+
+ describe '#import' do
+ context 'with existing custom emoji' do
+ let(:import_path) { Rails.root.join('spec', 'fixtures', 'files', 'elite-assets.tar.gz') }
+ let(:action) { :import }
+ let(:arguments) { [import_path] }
+
+ it 'reports about imported emoji' do
+ expect { subject }
+ .to output_results('Imported 1')
+ .and change(CustomEmoji, :count).by(1)
+ end
+ end
+ end
+
+ describe '#export' do
+ context 'with existing custom emoji' do
+ before do
+ FileUtils.rm_rf(export_path.dirname)
+ FileUtils.mkdir_p(export_path.dirname)
+
+ Fabricate(:custom_emoji)
+ end
+
+ after { FileUtils.rm_rf(export_path.dirname) }
+
+ let(:export_path) { Rails.root.join('tmp', 'cli-tests', 'export.tar.gz') }
+ let(:arguments) { [export_path.dirname.to_s] }
+ let(:action) { :export }
+
+ it 'reports about exported emoji' do
+ expect { subject }
+ .to output_results('Exported 1')
+ .and change { File.exist?(export_path) }.from(false).to(true)
+ end
+ end
+ end
end
diff --git a/spec/lib/mastodon/cli/feeds_spec.rb b/spec/lib/mastodon/cli/feeds_spec.rb
index e16113c85..199798052 100644
--- a/spec/lib/mastodon/cli/feeds_spec.rb
+++ b/spec/lib/mastodon/cli/feeds_spec.rb
@@ -4,20 +4,25 @@ require 'rails_helper'
require 'mastodon/cli/feeds'
describe Mastodon::CLI::Feeds do
+ subject { cli.invoke(action, arguments, options) }
+
let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#build' do
+ let(:action) { :build }
+
before { Fabricate(:account) }
context 'with --all option' do
let(:options) { { all: true } }
it 'regenerates feeds for all accounts' do
- expect { cli.invoke(:build, [], options) }.to output(
- a_string_including('Regenerated feeds')
- ).to_stdout
+ expect { subject }
+ .to output_results('Regenerated feeds')
end
end
@@ -27,9 +32,8 @@ describe Mastodon::CLI::Feeds do
let(:arguments) { ['alice'] }
it 'regenerates feeds for the account' do
- expect { cli.invoke(:build, arguments) }.to output(
- a_string_including('OK')
- ).to_stdout
+ expect { subject }
+ .to output_results('OK')
end
end
@@ -37,22 +41,23 @@ describe Mastodon::CLI::Feeds do
let(:arguments) { ['invalid-username'] }
it 'displays an error and exits' do
- expect { cli.invoke(:build, arguments) }.to output(
- a_string_including('No such account')
- ).to_stdout.and raise_error(SystemExit)
+ expect { subject }
+ .to output_results('No such account')
+ .and raise_error(SystemExit)
end
end
end
describe '#clear' do
+ let(:action) { :clear }
+
before do
allow(redis).to receive(:del).with(key_namespace)
end
it 'clears the redis `feed:*` namespace' do
- expect { cli.invoke(:clear) }.to output(
- a_string_including('OK')
- ).to_stdout
+ expect { subject }
+ .to output_results('OK')
expect(redis).to have_received(:del).with(key_namespace).once
end
diff --git a/spec/lib/mastodon/cli/ip_blocks_spec.rb b/spec/lib/mastodon/cli/ip_blocks_spec.rb
index 684314dc7..1d6c47268 100644
--- a/spec/lib/mastodon/cli/ip_blocks_spec.rb
+++ b/spec/lib/mastodon/cli/ip_blocks_spec.rb
@@ -4,11 +4,16 @@ require 'rails_helper'
require 'mastodon/cli/ip_blocks'
describe Mastodon::CLI::IpBlocks do
+ subject { cli.invoke(action, arguments, options) }
+
let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#add' do
+ let(:action) { :add }
let(:ip_list) do
[
'192.0.2.1',
@@ -25,29 +30,28 @@ describe Mastodon::CLI::IpBlocks do
]
end
let(:options) { { severity: 'no_access' } }
+ let(:arguments) { ip_list }
shared_examples 'ip address blocking' do
- it 'blocks all specified IP addresses' do
- cli.invoke(:add, ip_list, options)
-
- blocked_ip_addresses = IpBlock.where(ip: ip_list).pluck(:ip)
- expected_ip_addresses = ip_list.map { |ip| IPAddr.new(ip) }
-
- expect(blocked_ip_addresses).to match_array(expected_ip_addresses)
+ def blocked_ip_addresses
+ IpBlock.where(ip: ip_list).pluck(:ip)
end
- it 'sets the severity for all blocked IP addresses' do
- cli.invoke(:add, ip_list, options)
-
- blocked_ips_severity = IpBlock.where(ip: ip_list).pluck(:severity).all?(options[:severity])
-
- expect(blocked_ips_severity).to be(true)
+ def expected_ip_addresses
+ ip_list.map { |ip| IPAddr.new(ip) }
end
- it 'displays a success message with a summary' do
- expect { cli.invoke(:add, ip_list, options) }.to output(
- a_string_including("Added #{ip_list.size}, skipped 0, failed 0")
- ).to_stdout
+ def blocked_ips_severity
+ IpBlock.where(ip: ip_list).pluck(:severity).all?(options[:severity])
+ end
+
+ it 'blocks and sets severity for ip address and displays summary' do
+ expect { subject }
+ .to output_results("Added #{ip_list.size}, skipped 0, failed 0")
+ expect(blocked_ip_addresses)
+ .to match_array(expected_ip_addresses)
+ expect(blocked_ips_severity)
+ .to be(true)
end
end
@@ -57,27 +61,23 @@ describe Mastodon::CLI::IpBlocks do
context 'when a specified IP address is already blocked' do
let!(:blocked_ip) { IpBlock.create(ip: ip_list.last, severity: options[:severity]) }
+ let(:arguments) { ip_list }
- it 'skips the already blocked IP address' do
- allow(IpBlock).to receive(:new).and_call_original
+ before { allow(IpBlock).to receive(:new).and_call_original }
- cli.invoke(:add, ip_list, options)
+ it 'skips already block ip and displays the correct summary' do
+ expect { subject }
+ .to output_results("#{ip_list.last} is already blocked\nAdded #{ip_list.size - 1}, skipped 1, failed 0")
expect(IpBlock).to_not have_received(:new).with(ip: ip_list.last)
end
- it 'displays the correct summary' do
- expect { cli.invoke(:add, ip_list, options) }.to output(
- a_string_including("#{ip_list.last} is already blocked\nAdded #{ip_list.size - 1}, skipped 1, failed 0")
- ).to_stdout
- end
-
context 'with --force option' do
let!(:blocked_ip) { IpBlock.create(ip: ip_list.last, severity: 'no_access') }
let(:options) { { severity: 'sign_up_requires_approval', force: true } }
it 'overwrites the existing IP block record' do
- expect { cli.invoke(:add, ip_list, options) }
+ expect { subject }
.to change { blocked_ip.reload.severity }
.from('no_access')
.to('sign_up_requires_approval')
@@ -89,11 +89,11 @@ describe Mastodon::CLI::IpBlocks do
context 'when a specified IP address is invalid' do
let(:ip_list) { ['320.15.175.0', '9.5.105.255', '0.0.0.0'] }
+ let(:arguments) { ip_list }
it 'displays the correct summary' do
- expect { cli.invoke(:add, ip_list, options) }.to output(
- a_string_including("#{ip_list.first} is invalid\nAdded #{ip_list.size - 1}, skipped 0, failed 1")
- ).to_stdout
+ expect { subject }
+ .to output_results("#{ip_list.first} is invalid\nAdded #{ip_list.size - 1}, skipped 0, failed 1")
end
end
@@ -124,6 +124,7 @@ describe Mastodon::CLI::IpBlocks do
context 'when a specified IP address fails to be blocked' do
let(:ip_address) { '127.0.0.1' }
let(:ip_block) { instance_double(IpBlock, ip: ip_address, save: false) }
+ let(:arguments) { [ip_address] }
before do
allow(IpBlock).to receive(:new).and_return(ip_block)
@@ -132,24 +133,25 @@ describe Mastodon::CLI::IpBlocks do
end
it 'displays an error message' do
- expect { cli.invoke(:add, [ip_address], options) }
- .to output(
- a_string_including("#{ip_address} could not be saved")
- ).to_stdout
+ expect { subject }
+ .to output_results("#{ip_address} could not be saved")
end
end
context 'when no IP address is provided' do
+ let(:arguments) { [] }
+
it 'exits with an error message' do
- expect { cli.add }.to output(
- a_string_including('No IP(s) given')
- ).to_stdout
+ expect { subject }
+ .to output_results('No IP(s) given')
.and raise_error(SystemExit)
end
end
end
describe '#remove' do
+ let(:action) { :remove }
+
context 'when removing exact matches' do
let(:ip_list) do
[
@@ -166,22 +168,17 @@ describe Mastodon::CLI::IpBlocks do
'::/128',
]
end
+ let(:arguments) { ip_list }
before do
ip_list.each { |ip| IpBlock.create(ip: ip, severity: :no_access) }
end
- it 'removes exact IP blocks' do
- cli.invoke(:remove, ip_list)
-
+ it 'removes exact ip blocks and displays success message with a summary' do
+ expect { subject }
+ .to output_results("Removed #{ip_list.size}, skipped 0")
expect(IpBlock.where(ip: ip_list)).to_not exist
end
-
- it 'displays success message with a summary' do
- expect { cli.invoke(:remove, ip_list) }.to output(
- a_string_including("Removed #{ip_list.size}, skipped 0")
- ).to_stdout
- end
end
context 'with --force option' do
@@ -191,62 +188,60 @@ describe Mastodon::CLI::IpBlocks do
let(:arguments) { ['192.168.0.5', '10.0.1.50'] }
let(:options) { { force: true } }
- it 'removes blocks for IP ranges that cover given IP(s)' do
- cli.invoke(:remove, arguments, options)
+ it 'removes blocks for IP ranges that cover given IP(s) and keeps other ranges' do
+ subject
- expect(IpBlock.where(id: [first_ip_range_block.id, second_ip_range_block.id])).to_not exist
+ expect(covered_ranges).to_not exist
+ expect(other_ranges).to exist
end
- it 'does not remove other IP ranges' do
- cli.invoke(:remove, arguments, options)
+ def covered_ranges
+ IpBlock.where(id: [first_ip_range_block.id, second_ip_range_block.id])
+ end
- expect(IpBlock.where(id: third_ip_range_block.id)).to exist
+ def other_ranges
+ IpBlock.where(id: third_ip_range_block.id)
end
end
context 'when a specified IP address is not blocked' do
let(:unblocked_ip) { '192.0.2.1' }
+ let(:arguments) { [unblocked_ip] }
- it 'skips the IP address' do
- expect { cli.invoke(:remove, [unblocked_ip]) }.to output(
- a_string_including("#{unblocked_ip} is not yet blocked")
- ).to_stdout
- end
-
- it 'displays the summary correctly' do
- expect { cli.invoke(:remove, [unblocked_ip]) }.to output(
- a_string_including('Removed 0, skipped 1')
- ).to_stdout
+ it 'skips the IP address and displays summary' do
+ expect { subject }
+ .to output_results(
+ "#{unblocked_ip} is not yet blocked",
+ 'Removed 0, skipped 1'
+ )
end
end
context 'when a specified IP address is invalid' do
let(:invalid_ip) { '320.15.175.0' }
+ let(:arguments) { [invalid_ip] }
- it 'skips the invalid IP address' do
- expect { cli.invoke(:remove, [invalid_ip]) }.to output(
- a_string_including("#{invalid_ip} is invalid")
- ).to_stdout
- end
-
- it 'displays the summary correctly' do
- expect { cli.invoke(:remove, [invalid_ip]) }.to output(
- a_string_including('Removed 0, skipped 1')
- ).to_stdout
+ it 'skips the invalid IP address and displays summary' do
+ expect { subject }
+ .to output_results(
+ "#{invalid_ip} is invalid",
+ 'Removed 0, skipped 1'
+ )
end
end
context 'when no IP address is provided' do
it 'exits with an error message' do
- expect { cli.remove }.to output(
- a_string_including('No IP(s) given')
- ).to_stdout
+ expect { subject }
+ .to output_results('No IP(s) given')
.and raise_error(SystemExit)
end
end
end
describe '#export' do
+ let(:action) { :export }
+
let(:first_ip_range_block) { IpBlock.create(ip: '192.168.0.0/24', severity: :no_access) }
let(:second_ip_range_block) { IpBlock.create(ip: '10.0.0.0/16', severity: :no_access) }
let(:third_ip_range_block) { IpBlock.create(ip: '127.0.0.1', severity: :sign_up_block) }
@@ -255,15 +250,13 @@ describe Mastodon::CLI::IpBlocks do
let(:options) { { format: 'plain' } }
it 'exports blocked IPs with "no_access" severity in plain format' do
- expect { cli.invoke(:export, nil, options) }.to output(
- a_string_including("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
- ).to_stdout
+ expect { subject }
+ .to output_results("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
end
- it 'does not export bloked IPs with different severities' do
- expect { cli.invoke(:export, nil, options) }.to_not output(
- a_string_including("#{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}")
- ).to_stdout
+ it 'does not export blocked IPs with different severities' do
+ expect { subject }
+ .to_not output_results("#{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}")
end
end
@@ -271,23 +264,20 @@ describe Mastodon::CLI::IpBlocks do
let(:options) { { format: 'nginx' } }
it 'exports blocked IPs with "no_access" severity in plain format' do
- expect { cli.invoke(:export, nil, options) }.to output(
- a_string_including("deny #{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};\ndeny #{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix};")
- ).to_stdout
+ expect { subject }
+ .to output_results("deny #{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};\ndeny #{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix};")
end
- it 'does not export bloked IPs with different severities' do
- expect { cli.invoke(:export, nil, options) }.to_not output(
- a_string_including("deny #{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};")
- ).to_stdout
+ it 'does not export blocked IPs with different severities' do
+ expect { subject }
+ .to_not output_results("deny #{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};")
end
end
context 'when --format option is not provided' do
it 'exports blocked IPs in plain format by default' do
- expect { cli.export }.to output(
- a_string_including("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
- ).to_stdout
+ expect { subject }
+ .to output_results("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
end
end
end
diff --git a/spec/lib/mastodon/cli/main_spec.rb b/spec/lib/mastodon/cli/main_spec.rb
index b5b5d6906..59f1fc478 100644
--- a/spec/lib/mastodon/cli/main_spec.rb
+++ b/spec/lib/mastodon/cli/main_spec.rb
@@ -4,13 +4,20 @@ require 'rails_helper'
require 'mastodon/cli/main'
describe Mastodon::CLI::Main do
+ subject { cli.invoke(action, arguments, options) }
+
+ let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
+
it_behaves_like 'CLI Command'
- describe 'version' do
+ describe '#version' do
+ let(:action) { :version }
+
it 'returns the Mastodon version' do
- expect { described_class.new.invoke(:version) }.to output(
- a_string_including(Mastodon::Version.to_s)
- ).to_stdout
+ expect { subject }
+ .to output_results(Mastodon::Version.to_s)
end
end
end
diff --git a/spec/lib/mastodon/cli/maintenance_spec.rb b/spec/lib/mastodon/cli/maintenance_spec.rb
index 95e695ab5..02169b7a4 100644
--- a/spec/lib/mastodon/cli/maintenance_spec.rb
+++ b/spec/lib/mastodon/cli/maintenance_spec.rb
@@ -4,20 +4,26 @@ require 'rails_helper'
require 'mastodon/cli/maintenance'
describe Mastodon::CLI::Maintenance do
+ subject { cli.invoke(action, arguments, options) }
+
let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#fix_duplicates' do
+ let(:action) { :fix_duplicates }
+
context 'when the database version is too old' do
before do
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(2000_01_01_000000) # Earlier than minimum
end
it 'Exits with error message' do
- expect { cli.invoke :fix_duplicates }.to output(
- a_string_including('is too old')
- ).to_stdout.and raise_error(SystemExit)
+ expect { subject }
+ .to output_results('is too old')
+ .and raise_error(SystemExit)
end
end
@@ -28,9 +34,9 @@ describe Mastodon::CLI::Maintenance do
end
it 'Exits with error message' do
- expect { cli.invoke :fix_duplicates }.to output(
- a_string_including('more recent')
- ).to_stdout.and raise_error(SystemExit)
+ expect { subject }
+ .to output_results('more recent')
+ .and raise_error(SystemExit)
end
end
@@ -41,9 +47,9 @@ describe Mastodon::CLI::Maintenance do
end
it 'Exits with error message' do
- expect { cli.invoke :fix_duplicates }.to output(
- a_string_including('Sidekiq is running')
- ).to_stdout.and raise_error(SystemExit)
+ expect { subject }
+ .to output_results('Sidekiq is running')
+ .and raise_error(SystemExit)
end
end
end
diff --git a/spec/lib/mastodon/cli/media_spec.rb b/spec/lib/mastodon/cli/media_spec.rb
index 6d510c1f5..24e1467a3 100644
--- a/spec/lib/mastodon/cli/media_spec.rb
+++ b/spec/lib/mastodon/cli/media_spec.rb
@@ -4,18 +4,24 @@ require 'rails_helper'
require 'mastodon/cli/media'
describe Mastodon::CLI::Media do
+ subject { cli.invoke(action, arguments, options) }
+
let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#remove' do
+ let(:action) { :remove }
+
context 'with --prune-profiles and --remove-headers' do
let(:options) { { prune_profiles: true, remove_headers: true } }
it 'warns about usage and exits' do
- expect { cli.invoke(:remove, [], options) }.to output(
- a_string_including('--prune-profiles and --remove-headers should not be specified simultaneously')
- ).to_stdout.and raise_error(SystemExit)
+ expect { subject }
+ .to output_results('--prune-profiles and --remove-headers should not be specified simultaneously')
+ .and raise_error(SystemExit)
end
end
@@ -23,9 +29,9 @@ describe Mastodon::CLI::Media do
let(:options) { { include_follows: true } }
it 'warns about usage and exits' do
- expect { cli.invoke(:remove, [], options) }.to output(
- a_string_including('--include-follows can only be used with --prune-profiles or --remove-headers')
- ).to_stdout.and raise_error(SystemExit)
+ expect { subject }
+ .to output_results('--include-follows can only be used with --prune-profiles or --remove-headers')
+ .and raise_error(SystemExit)
end
end
@@ -38,9 +44,8 @@ describe Mastodon::CLI::Media do
let(:options) { { prune_profiles: true } }
it 'removes account avatars' do
- expect { cli.invoke(:remove, [], options) }.to output(
- a_string_including('Visited 1')
- ).to_stdout
+ expect { subject }
+ .to output_results('Visited 1')
expect(account.reload.avatar).to be_blank
end
@@ -50,9 +55,8 @@ describe Mastodon::CLI::Media do
let(:options) { { remove_headers: true } }
it 'removes account header' do
- expect { cli.invoke(:remove, [], options) }.to output(
- a_string_including('Visited 1')
- ).to_stdout
+ expect { subject }
+ .to output_results('Visited 1')
expect(account.reload.header).to be_blank
end
@@ -64,9 +68,8 @@ describe Mastodon::CLI::Media do
context 'without options' do
it 'removes account avatars' do
- expect { cli.invoke(:remove) }.to output(
- a_string_including('Removed 1')
- ).to_stdout
+ expect { subject }
+ .to output_results('Removed 1')
expect(media_attachment.reload.file).to be_blank
expect(media_attachment.reload.thumbnail).to be_blank
@@ -76,25 +79,50 @@ describe Mastodon::CLI::Media do
end
describe '#usage' do
- context 'without options' do
- let(:options) { {} }
+ let(:action) { :usage }
+ context 'without options' do
it 'reports about storage size' do
- expect { cli.invoke(:usage, [], options) }.to output(
- a_string_including('0 Bytes')
- ).to_stdout
+ expect { subject }
+ .to output_results('0 Bytes')
+ end
+ end
+ end
+
+ describe '#lookup' do
+ let(:action) { :lookup }
+ let(:arguments) { [url] }
+
+ context 'with valid url not connected to a record' do
+ let(:url) { 'https://example.host/assets/1' }
+
+ it 'warns about url and exits' do
+ expect { subject }
+ .to output_results('Not a media URL')
+ .and raise_error(SystemExit)
+ end
+ end
+
+ context 'with a valid media url' do
+ let(:status) { Fabricate(:status) }
+ let(:media_attachment) { Fabricate(:media_attachment, status: status) }
+ let(:url) { media_attachment.file.url(:original) }
+
+ it 'displays the url of a connected status' do
+ expect { subject }
+ .to output_results(status.id.to_s)
end
end
end
describe '#refresh' do
- context 'without any options' do
- let(:options) { {} }
+ let(:action) { :refresh }
+ context 'without any options' do
it 'warns about usage and exits' do
- expect { cli.invoke(:refresh, [], options) }.to output(
- a_string_including('Specify the source')
- ).to_stdout.and raise_error(SystemExit)
+ expect { subject }
+ .to output_results('Specify the source')
+ .and raise_error(SystemExit)
end
end
@@ -108,9 +136,8 @@ describe Mastodon::CLI::Media do
let(:status) { Fabricate(:status) }
it 'redownloads the attachment file' do
- expect { cli.invoke(:refresh, [], options) }.to output(
- a_string_including('Downloaded 1 media')
- ).to_stdout
+ expect { subject }
+ .to output_results('Downloaded 1 media')
end
end
@@ -119,9 +146,9 @@ describe Mastodon::CLI::Media do
let(:options) { { account: 'not-real-user@example.host' } }
it 'warns about usage and exits' do
- expect { cli.invoke(:refresh, [], options) }.to output(
- a_string_including('No such account')
- ).to_stdout.and raise_error(SystemExit)
+ expect { subject }
+ .to output_results('No such account')
+ .and raise_error(SystemExit)
end
end
@@ -135,9 +162,8 @@ describe Mastodon::CLI::Media do
let(:account) { Fabricate(:account) }
it 'redownloads the attachment file' do
- expect { cli.invoke(:refresh, [], options) }.to output(
- a_string_including('Downloaded 1 media')
- ).to_stdout
+ expect { subject }
+ .to output_results('Downloaded 1 media')
end
end
end
@@ -153,9 +179,8 @@ describe Mastodon::CLI::Media do
let(:account) { Fabricate(:account, domain: domain) }
it 'redownloads the attachment file' do
- expect { cli.invoke(:refresh, [], options) }.to output(
- a_string_including('Downloaded 1 media')
- ).to_stdout
+ expect { subject }
+ .to output_results('Downloaded 1 media')
end
end
end
diff --git a/spec/lib/mastodon/cli/preview_cards_spec.rb b/spec/lib/mastodon/cli/preview_cards_spec.rb
index a766d250e..951ae3758 100644
--- a/spec/lib/mastodon/cli/preview_cards_spec.rb
+++ b/spec/lib/mastodon/cli/preview_cards_spec.rb
@@ -4,11 +4,17 @@ require 'rails_helper'
require 'mastodon/cli/preview_cards'
describe Mastodon::CLI::PreviewCards do
+ subject { cli.invoke(action, arguments, options) }
+
let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#remove' do
+ let(:action) { :remove }
+
context 'with relevant preview cards' do
before do
Fabricate(:preview_card, updated_at: 10.years.ago, type: :link)
@@ -18,10 +24,11 @@ describe Mastodon::CLI::PreviewCards do
context 'with no arguments' do
it 'deletes thumbnails for local preview cards' do
- expect { cli.invoke(:remove) }.to output(
- a_string_including('Removed 2 preview cards')
- .and(a_string_including('approx. 119 KB'))
- ).to_stdout
+ expect { subject }
+ .to output_results(
+ 'Removed 2 preview cards',
+ 'approx. 119 KB'
+ )
end
end
@@ -29,10 +36,11 @@ describe Mastodon::CLI::PreviewCards do
let(:options) { { link: true } }
it 'deletes thumbnails for local preview cards' do
- expect { cli.invoke(:remove, [], options) }.to output(
- a_string_including('Removed 1 link-type preview cards')
- .and(a_string_including('approx. 59.6 KB'))
- ).to_stdout
+ expect { subject }
+ .to output_results(
+ 'Removed 1 link-type preview cards',
+ 'approx. 59.6 KB'
+ )
end
end
@@ -40,10 +48,11 @@ describe Mastodon::CLI::PreviewCards do
let(:options) { { days: 365 } }
it 'deletes thumbnails for local preview cards' do
- expect { cli.invoke(:remove, [], options) }.to output(
- a_string_including('Removed 1 preview cards')
- .and(a_string_including('approx. 59.6 KB'))
- ).to_stdout
+ expect { subject }
+ .to output_results(
+ 'Removed 1 preview cards',
+ 'approx. 59.6 KB'
+ )
end
end
end
diff --git a/spec/lib/mastodon/cli/search_spec.rb b/spec/lib/mastodon/cli/search_spec.rb
index 785dc2bd6..cb0c80c11 100644
--- a/spec/lib/mastodon/cli/search_spec.rb
+++ b/spec/lib/mastodon/cli/search_spec.rb
@@ -4,5 +4,79 @@ require 'rails_helper'
require 'mastodon/cli/search'
describe Mastodon::CLI::Search do
+ subject { cli.invoke(action, arguments, options) }
+
+ let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
+
it_behaves_like 'CLI Command'
+
+ describe '#deploy' do
+ let(:action) { :deploy }
+
+ context 'with concurrency out of range' do
+ let(:options) { { concurrency: -100 } }
+
+ it 'Exits with error message' do
+ expect { subject }
+ .to output_results('this concurrency setting')
+ .and raise_error(SystemExit)
+ end
+ end
+
+ context 'with batch size out of range' do
+ let(:options) { { batch_size: -100_000 } }
+
+ it 'Exits with error message' do
+ expect { subject }
+ .to output_results('this batch_size setting')
+ .and raise_error(SystemExit)
+ end
+ end
+
+ context 'without options' do
+ before { stub_search_indexes }
+
+ let(:indexed_count) { 1 }
+ let(:deleted_count) { 2 }
+
+ it 'reports about storage size' do
+ expect { subject }
+ .to output_results(
+ "Indexed #{described_class::INDICES.size * indexed_count} records",
+ "de-indexed #{described_class::INDICES.size * deleted_count}"
+ )
+ end
+ end
+
+ def stub_search_indexes
+ described_class::INDICES.each do |index|
+ allow(index)
+ .to receive_messages(
+ specification: instance_double(Chewy::Index::Specification, changed?: true, lock!: nil),
+ purge: nil
+ )
+
+ importer_double = importer_double_for(index)
+ allow(importer_double).to receive(:on_progress).and_yield([indexed_count, deleted_count])
+ allow("Importer::#{index}Importer".constantize)
+ .to receive(:new)
+ .and_return(importer_double)
+ end
+ end
+
+ def importer_double_for(index)
+ instance_double(
+ "Importer::#{index}Importer".constantize,
+ clean_up!: nil,
+ estimate!: 100,
+ import!: nil,
+ on_failure: nil,
+ # on_progress: nil,
+ optimize_for_import!: nil,
+ optimize_for_search!: nil
+ )
+ end
+ end
end
diff --git a/spec/lib/mastodon/cli/settings_spec.rb b/spec/lib/mastodon/cli/settings_spec.rb
index 7dcd1110b..568ee0039 100644
--- a/spec/lib/mastodon/cli/settings_spec.rb
+++ b/spec/lib/mastodon/cli/settings_spec.rb
@@ -7,59 +7,53 @@ describe Mastodon::CLI::Settings do
it_behaves_like 'CLI Command'
describe 'subcommand "registrations"' do
+ subject { cli.invoke(action, arguments, options) }
+
let(:cli) { Mastodon::CLI::Registrations.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
before do
Setting.registrations_mode = nil
end
describe '#open' do
- it 'changes "registrations_mode" to "open"' do
- expect { cli.open }.to change(Setting, :registrations_mode).from(nil).to('open')
- end
+ let(:action) { :open }
- it 'displays success message' do
- expect { cli.open }.to output(
- a_string_including('OK')
- ).to_stdout
+ it 'changes "registrations_mode" to "open" and displays success' do
+ expect { subject }
+ .to change(Setting, :registrations_mode).from(nil).to('open')
+ .and output_results('OK')
end
end
describe '#approved' do
- it 'changes "registrations_mode" to "approved"' do
- expect { cli.approved }.to change(Setting, :registrations_mode).from(nil).to('approved')
- end
+ let(:action) { :approved }
- it 'displays success message' do
- expect { cli.approved }.to output(
- a_string_including('OK')
- ).to_stdout
+ it 'changes "registrations_mode" to "approved" and displays success' do
+ expect { subject }
+ .to change(Setting, :registrations_mode).from(nil).to('approved')
+ .and output_results('OK')
end
context 'with --require-reason' do
- before do
- cli.options = { require_reason: true }
- end
+ let(:options) { { require_reason: true } }
- it 'changes "registrations_mode" to "approved"' do
- expect { cli.approved }.to change(Setting, :registrations_mode).from(nil).to('approved')
- end
-
- it 'sets "require_invite_text" to "true"' do
- expect { cli.approved }.to change(Setting, :require_invite_text).from(false).to(true)
+ it 'changes registrations_mode and require_invite_text' do
+ expect { subject }
+ .to change(Setting, :registrations_mode).from(nil).to('approved')
+ .and change(Setting, :require_invite_text).from(false).to(true)
end
end
end
describe '#close' do
- it 'changes "registrations_mode" to "none"' do
- expect { cli.close }.to change(Setting, :registrations_mode).from(nil).to('none')
- end
+ let(:action) { :close }
- it 'displays success message' do
- expect { cli.close }.to output(
- a_string_including('OK')
- ).to_stdout
+ it 'changes "registrations_mode" to "none" and displays success' do
+ expect { subject }
+ .to change(Setting, :registrations_mode).from(nil).to('none')
+ .and output_results('OK')
end
end
end
diff --git a/spec/lib/mastodon/cli/statuses_spec.rb b/spec/lib/mastodon/cli/statuses_spec.rb
index 70e4e2c08..63d494bbb 100644
--- a/spec/lib/mastodon/cli/statuses_spec.rb
+++ b/spec/lib/mastodon/cli/statuses_spec.rb
@@ -4,26 +4,31 @@ require 'rails_helper'
require 'mastodon/cli/statuses'
describe Mastodon::CLI::Statuses do
+ subject { cli.invoke(action, arguments, options) }
+
let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#remove', use_transactional_tests: false do
+ let(:action) { :remove }
+
context 'with small batch size' do
let(:options) { { batch_size: 0 } }
it 'exits with error message' do
- expect { cli.invoke :remove, [], options }.to output(
- a_string_including('Cannot run')
- ).to_stdout.and raise_error(SystemExit)
+ expect { subject }
+ .to output_results('Cannot run')
+ .and raise_error(SystemExit)
end
end
context 'with default batch size' do
it 'removes unreferenced statuses' do
- expect { cli.invoke :remove }.to output(
- a_string_including('Done after')
- ).to_stdout
+ expect { subject }
+ .to output_results('Done after')
end
end
end
diff --git a/spec/lib/mastodon/cli/upgrade_spec.rb b/spec/lib/mastodon/cli/upgrade_spec.rb
index 817044f7e..6861e0488 100644
--- a/spec/lib/mastodon/cli/upgrade_spec.rb
+++ b/spec/lib/mastodon/cli/upgrade_spec.rb
@@ -4,5 +4,27 @@ require 'rails_helper'
require 'mastodon/cli/upgrade'
describe Mastodon::CLI::Upgrade do
+ subject { cli.invoke(action, arguments, options) }
+
+ let(:cli) { described_class.new }
+ let(:arguments) { [] }
+ let(:options) { {} }
+
it_behaves_like 'CLI Command'
+
+ describe '#storage_schema' do
+ let(:action) { :storage_schema }
+
+ context 'with records that dont need upgrading' do
+ before do
+ Fabricate(:account)
+ Fabricate(:media_attachment)
+ end
+
+ it 'does not upgrade storage for the attachments' do
+ expect { subject }
+ .to output_results('Upgraded storage schema of 0 records')
+ end
+ end
+ end
end
diff --git a/spec/models/form/account_batch_spec.rb b/spec/models/form/account_batch_spec.rb
index fd8e90901..26fb1b953 100644
--- a/spec/models/form/account_batch_spec.rb
+++ b/spec/models/form/account_batch_spec.rb
@@ -37,12 +37,10 @@ RSpec.describe Form::AccountBatch do
let(:select_all_matching) { '0' }
let(:account_ids) { [target_account.id, target_account2.id] }
- it 'suspends the expected users' do
- expect { subject }.to change { [target_account.reload.suspended?, target_account2.reload.suspended?] }.from([false, false]).to([true, true])
- end
-
- it 'closes open reports targeting the suspended users' do
- expect { subject }.to change { Report.unresolved.where(target_account: [target_account, target_account2]).count }.from(2).to(0)
+ it 'suspends the expected users and closes open reports' do
+ expect { subject }
+ .to change_account_suspensions
+ .and change_open_reports_for_accounts
end
end
@@ -50,13 +48,33 @@ RSpec.describe Form::AccountBatch do
let(:select_all_matching) { '1' }
let(:query) { Account.where(id: [target_account.id, target_account2.id]) }
- it 'suspends the expected users' do
- expect { subject }.to change { [target_account.reload.suspended?, target_account2.reload.suspended?] }.from([false, false]).to([true, true])
+ it 'suspends the expected users and closes open reports' do
+ expect { subject }
+ .to change_account_suspensions
+ .and change_open_reports_for_accounts
end
+ end
- it 'closes open reports targeting the suspended users' do
- expect { subject }.to change { Report.unresolved.where(target_account: [target_account, target_account2]).count }.from(2).to(0)
- end
+ private
+
+ def change_account_suspensions
+ change { relevant_account_suspension_statuses }
+ .from([false, false])
+ .to([true, true])
+ end
+
+ def change_open_reports_for_accounts
+ change(relevant_account_unresolved_reports, :count)
+ .from(2)
+ .to(0)
+ end
+
+ def relevant_account_unresolved_reports
+ Report.unresolved.where(target_account: [target_account, target_account2])
+ end
+
+ def relevant_account_suspension_statuses
+ [target_account.reload, target_account2.reload].map(&:suspended?)
end
end
end
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
index d30e7201c..4394b470e 100644
--- a/spec/rails_helper.rb
+++ b/spec/rails_helper.rb
@@ -88,6 +88,7 @@ RSpec.configure do |config|
config.include Chewy::Rspec::Helpers
config.include Redisable
config.include SignedRequestHelpers, type: :request
+ config.include CommandLineHelpers, type: :cli
config.around(:each, use_transactional_tests: false) do |example|
self.use_transactional_tests = false
diff --git a/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb b/spec/requests/api/v1/accounts/familiar_followers_spec.rb
similarity index 53%
rename from spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb
rename to spec/requests/api/v1/accounts/familiar_followers_spec.rb
index 3c7c7e8b8..fdc0a3a93 100644
--- a/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb
+++ b/spec/requests/api/v1/accounts/familiar_followers_spec.rb
@@ -2,20 +2,16 @@
require 'rails_helper'
-describe Api::V1::Accounts::FamiliarFollowersController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:follows') }
+describe 'Accounts Familiar Followers API' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'read:follows' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
let(:account) { Fabricate(:account) }
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
+ describe 'GET /api/v1/accounts/familiar_followers' do
it 'returns http success' do
- get :index, params: { account_id: account.id, limit: 2 }
+ get '/api/v1/accounts/familiar_followers', params: { account_id: account.id, limit: 2 }, headers: headers
expect(response).to have_http_status(200)
end
@@ -26,7 +22,7 @@ describe Api::V1::Accounts::FamiliarFollowersController do
it 'removes duplicate account IDs from params' do
account_ids = [account_a, account_b, account_b, account_a, account_a].map { |a| a.id.to_s }
- get :index, params: { id: account_ids }
+ get '/api/v1/accounts/familiar_followers', params: { id: account_ids }, headers: headers
expect(body_as_json.pluck(:id)).to contain_exactly(account_a.id.to_s, account_b.id.to_s)
end
diff --git a/spec/requests/api/v1/accounts/identity_proofs_spec.rb b/spec/requests/api/v1/accounts/identity_proofs_spec.rb
new file mode 100644
index 000000000..3727af7e8
--- /dev/null
+++ b/spec/requests/api/v1/accounts/identity_proofs_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Accounts Identity Proofs API' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'read:accounts' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+ let(:account) { Fabricate(:account) }
+
+ describe 'GET /api/v1/accounts/identity_proofs' do
+ it 'returns http success' do
+ get "/api/v1/accounts/#{account.id}/identity_proofs", params: { limit: 2 }, headers: headers
+
+ expect(response).to have_http_status(200)
+ end
+ end
+end
diff --git a/spec/requests/api/v1/accounts/lists_spec.rb b/spec/requests/api/v1/accounts/lists_spec.rb
new file mode 100644
index 000000000..48c0337e5
--- /dev/null
+++ b/spec/requests/api/v1/accounts/lists_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Accounts Lists API' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'read:lists' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+ let(:account) { Fabricate(:account) }
+ let(:list) { Fabricate(:list, account: user.account) }
+
+ before do
+ user.account.follow!(account)
+ list.accounts << account
+ end
+
+ describe 'GET /api/v1/accounts/lists' do
+ it 'returns http success' do
+ get "/api/v1/accounts/#{account.id}/lists", headers: headers
+
+ expect(response).to have_http_status(200)
+ end
+ end
+end
diff --git a/spec/requests/api/v1/accounts/lookup_spec.rb b/spec/requests/api/v1/accounts/lookup_spec.rb
new file mode 100644
index 000000000..4c022c7c1
--- /dev/null
+++ b/spec/requests/api/v1/accounts/lookup_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Accounts Lookup API' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'read:accounts' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+ let(:account) { Fabricate(:account) }
+
+ describe 'GET /api/v1/accounts/lookup' do
+ it 'returns http success' do
+ get '/api/v1/accounts/lookup', params: { account_id: account.id, acct: account.acct }, headers: headers
+
+ expect(response).to have_http_status(200)
+ end
+ end
+end
diff --git a/spec/controllers/api/v1/accounts/notes_controller_spec.rb b/spec/requests/api/v1/accounts/notes_spec.rb
similarity index 66%
rename from spec/controllers/api/v1/accounts/notes_controller_spec.rb
rename to spec/requests/api/v1/accounts/notes_spec.rb
index 75599b32b..4f3ac68c7 100644
--- a/spec/controllers/api/v1/accounts/notes_controller_spec.rb
+++ b/spec/requests/api/v1/accounts/notes_spec.rb
@@ -2,21 +2,17 @@
require 'rails_helper'
-describe Api::V1::Accounts::NotesController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:accounts') }
+describe 'Accounts Notes API' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'write:accounts' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
let(:account) { Fabricate(:account) }
let(:comment) { 'foo' }
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
+ describe 'POST /api/v1/accounts/:account_id/note' do
subject do
- post :create, params: { account_id: account.id, comment: comment }
+ post "/api/v1/accounts/#{account.id}/note", params: { comment: comment }, headers: headers
end
context 'when account note has reasonable length', :aggregate_failures do
diff --git a/spec/requests/api/v1/accounts/pins_spec.rb b/spec/requests/api/v1/accounts/pins_spec.rb
new file mode 100644
index 000000000..c293715f7
--- /dev/null
+++ b/spec/requests/api/v1/accounts/pins_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Accounts Pins API' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'write:accounts' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+ let(:kevin) { Fabricate(:user) }
+
+ before do
+ kevin.account.followers << user.account
+ end
+
+ describe 'POST /api/v1/accounts/:account_id/pin' do
+ subject { post "/api/v1/accounts/#{kevin.account.id}/pin", headers: headers }
+
+ it 'creates account_pin', :aggregate_failures do
+ expect do
+ subject
+ end.to change { AccountPin.where(account: user.account, target_account: kevin.account).count }.by(1)
+ expect(response).to have_http_status(200)
+ end
+ end
+
+ describe 'POST /api/v1/accounts/:account_id/unpin' do
+ subject { post "/api/v1/accounts/#{kevin.account.id}/unpin", headers: headers }
+
+ before do
+ Fabricate(:account_pin, account: user.account, target_account: kevin.account)
+ end
+
+ it 'destroys account_pin', :aggregate_failures do
+ expect do
+ subject
+ end.to change { AccountPin.where(account: user.account, target_account: kevin.account).count }.by(-1)
+ expect(response).to have_http_status(200)
+ end
+ end
+end
diff --git a/spec/requests/api/v1/accounts/relationships_spec.rb b/spec/requests/api/v1/accounts/relationships_spec.rb
index cea45168a..b06ce0509 100644
--- a/spec/requests/api/v1/accounts/relationships_spec.rb
+++ b/spec/requests/api/v1/accounts/relationships_spec.rb
@@ -31,8 +31,8 @@ describe 'GET /api/v1/accounts/relationships' do
.to have_http_status(200)
expect(body_as_json)
.to be_an(Enumerable)
- .and have_attributes(
- first: include(
+ .and contain_exactly(
+ include(
following: true,
followed_by: false
)
@@ -53,9 +53,11 @@ describe 'GET /api/v1/accounts/relationships' do
expect(body_as_json)
.to be_an(Enumerable)
.and have_attributes(
- size: 2,
- first: include(simon_item),
- second: include(lewis_item)
+ size: 2
+ )
+ .and contain_exactly(
+ include(simon_item),
+ include(lewis_item)
)
end
end
@@ -71,10 +73,12 @@ describe 'GET /api/v1/accounts/relationships' do
expect(body_as_json)
.to be_an(Enumerable)
.and have_attributes(
- size: 3,
- first: include(simon_item),
- second: include(lewis_item),
- third: include(bob_item)
+ size: 3
+ )
+ .and contain_exactly(
+ include(simon_item),
+ include(lewis_item),
+ include(bob_item)
)
end
end
@@ -88,9 +92,11 @@ describe 'GET /api/v1/accounts/relationships' do
expect(body_as_json)
.to be_an(Enumerable)
.and have_attributes(
- size: 2,
- first: include(simon_item),
- second: include(lewis_item)
+ size: 2
+ )
+ .and contain_exactly(
+ include(simon_item),
+ include(lewis_item)
)
end
end
@@ -116,7 +122,6 @@ describe 'GET /api/v1/accounts/relationships' do
muting: false,
requested: false,
domain_blocking: false,
-
}
end
@@ -129,7 +134,6 @@ describe 'GET /api/v1/accounts/relationships' do
muting: false,
requested: false,
domain_blocking: false,
-
}
end
end
@@ -149,8 +153,10 @@ describe 'GET /api/v1/accounts/relationships' do
expect(body_as_json)
.to be_an(Enumerable)
.and have_attributes(
- size: 1,
- first: include(
+ size: 1
+ )
+ .and contain_exactly(
+ include(
following: true,
showing_reblogs: true
)
@@ -168,8 +174,8 @@ describe 'GET /api/v1/accounts/relationships' do
expect(body_as_json)
.to be_an(Enumerable)
- .and have_attributes(
- first: include(
+ .and contain_exactly(
+ include(
following: false,
showing_reblogs: false
)
diff --git a/spec/requests/api/v1/accounts/search_spec.rb b/spec/requests/api/v1/accounts/search_spec.rb
new file mode 100644
index 000000000..76b32e7b2
--- /dev/null
+++ b/spec/requests/api/v1/accounts/search_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Accounts Search API' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'read:accounts' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+
+ describe 'GET /api/v1/accounts/search' do
+ it 'returns http success' do
+ get '/api/v1/accounts/search', params: { q: 'query' }, headers: headers
+
+ expect(response).to have_http_status(200)
+ end
+ end
+end
diff --git a/spec/requests/api/v1/admin/account_actions_spec.rb b/spec/requests/api/v1/admin/account_actions_spec.rb
index c14e08c21..4167911a1 100644
--- a/spec/requests/api/v1/admin/account_actions_spec.rb
+++ b/spec/requests/api/v1/admin/account_actions_spec.rb
@@ -21,12 +21,19 @@ RSpec.describe 'Account actions' do
it 'logs action' do
subject
- log_item = Admin::ActionLog.last
+ expect(latest_admin_action_log)
+ .to be_present
+ .and have_attributes(
+ action: eq(action_type),
+ account_id: eq(user.account_id),
+ target_id: eq(target_type == :user ? target_account.user.id : target_account.id)
+ )
+ end
- expect(log_item).to be_present
- expect(log_item.action).to eq(action_type)
- expect(log_item.account_id).to eq(user.account_id)
- expect(log_item.target_id).to eq(target_type == :user ? target_account.user.id : target_account.id)
+ private
+
+ def latest_admin_action_log
+ Admin::ActionLog.last
end
end
diff --git a/spec/requests/api/v1/admin/accounts_spec.rb b/spec/requests/api/v1/admin/accounts_spec.rb
index 8e158f623..1615581f0 100644
--- a/spec/requests/api/v1/admin/accounts_spec.rb
+++ b/spec/requests/api/v1/admin/accounts_spec.rb
@@ -151,12 +151,13 @@ RSpec.describe 'Accounts' do
it 'logs action', :aggregate_failures do
subject
- log_item = Admin::ActionLog.last
-
- expect(log_item).to be_present
- expect(log_item.action).to eq :approve
- expect(log_item.account_id).to eq user.account_id
- expect(log_item.target_id).to eq account.user.id
+ expect(latest_admin_action_log)
+ .to be_present
+ .and have_attributes(
+ action: eq(:approve),
+ account_id: eq(user.account_id),
+ target_id: eq(account.user.id)
+ )
end
end
@@ -202,12 +203,13 @@ RSpec.describe 'Accounts' do
it 'logs action', :aggregate_failures do
subject
- log_item = Admin::ActionLog.last
-
- expect(log_item).to be_present
- expect(log_item.action).to eq :reject
- expect(log_item.account_id).to eq user.account_id
- expect(log_item.target_id).to eq account.user.id
+ expect(latest_admin_action_log)
+ .to be_present
+ .and have_attributes(
+ action: eq(:reject),
+ account_id: eq(user.account_id),
+ target_id: eq(account.user.id)
+ )
end
end
@@ -398,4 +400,10 @@ RSpec.describe 'Accounts' do
end
end
end
+
+ private
+
+ def latest_admin_action_log
+ Admin::ActionLog.last
+ end
end
diff --git a/spec/requests/api/v1/featured_tags/suggestions_spec.rb b/spec/requests/api/v1/featured_tags/suggestions_spec.rb
new file mode 100644
index 000000000..f7b453b74
--- /dev/null
+++ b/spec/requests/api/v1/featured_tags/suggestions_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Featured Tags Suggestions API' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'read:accounts' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+ let(:account) { Fabricate(:account) }
+
+ describe 'GET /api/v1/featured_tags/suggestions' do
+ it 'returns http success' do
+ get '/api/v1/featured_tags/suggestions', params: { account_id: account.id, limit: 2 }, headers: headers
+
+ expect(response).to have_http_status(200)
+ end
+ end
+end
diff --git a/spec/requests/api/v1/lists_spec.rb b/spec/requests/api/v1/lists_spec.rb
index 22dde43a1..4635e936f 100644
--- a/spec/requests/api/v1/lists_spec.rb
+++ b/spec/requests/api/v1/lists_spec.rb
@@ -135,8 +135,11 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'read read:lists'
- it 'returns the updated list', :aggregate_failures do
- subject
+ it 'returns the updated list and updates values', :aggregate_failures do
+ expect { subject }
+ .to change_list_title
+ .and change_list_replies_policy
+ .and change_list_exclusive
expect(response).to have_http_status(200)
list.reload
@@ -149,16 +152,16 @@ RSpec.describe 'Lists' do
})
end
- it 'updates the list title' do
- expect { subject }.to change { list.reload.title }.from('my list').to('list')
+ def change_list_title
+ change { list.reload.title }.from('my list').to('list')
end
- it 'updates the list replies_policy' do
- expect { subject }.to change { list.reload.replies_policy }.from('list').to('followed')
+ def change_list_replies_policy
+ change { list.reload.replies_policy }.from('list').to('followed')
end
- it 'updates the list exclusive' do
- expect { subject }.to change { list.reload.exclusive }.from(false).to(true)
+ def change_list_exclusive
+ change { list.reload.exclusive }.from(false).to(true)
end
context 'when the list does not exist' do
diff --git a/spec/controllers/api/v2/search_controller_spec.rb b/spec/requests/api/v2/search_spec.rb
similarity index 79%
rename from spec/controllers/api/v2/search_controller_spec.rb
rename to spec/requests/api/v2/search_spec.rb
index a16716a10..d0778cba4 100644
--- a/spec/controllers/api/v2/search_controller_spec.rb
+++ b/spec/requests/api/v2/search_spec.rb
@@ -2,25 +2,21 @@
require 'rails_helper'
-RSpec.describe Api::V2::SearchController do
- render_views
-
+describe 'Search API' do
context 'with token' do
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:search') }
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'read:search' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
+ describe 'GET /api/v2/search' do
let!(:bob) { Fabricate(:account, username: 'bob_test') }
let!(:ana) { Fabricate(:account, username: 'ana_test') }
let!(:tom) { Fabricate(:account, username: 'tom_test') }
let(:params) { { q: 'test' } }
it 'returns http success' do
- get :index, params: params
+ get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(200)
end
@@ -29,7 +25,7 @@ RSpec.describe Api::V2::SearchController do
let(:params) { { q: 'test', type: 'accounts' } }
it 'returns all matching accounts' do
- get :index, params: params
+ get '/api/v2/search', headers: headers, params: params
expect(body_as_json[:accounts].pluck(:id)).to contain_exactly(bob.id.to_s, ana.id.to_s, tom.id.to_s)
end
@@ -38,7 +34,7 @@ RSpec.describe Api::V2::SearchController do
let(:params) { { q: 'test1', resolve: '1' } }
it 'returns http unauthorized' do
- get :index, params: params
+ get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(200)
end
@@ -48,7 +44,7 @@ RSpec.describe Api::V2::SearchController do
let(:params) { { q: 'test1', offset: 1 } }
it 'returns http unauthorized' do
- get :index, params: params
+ get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(200)
end
@@ -62,7 +58,7 @@ RSpec.describe Api::V2::SearchController do
end
it 'returns only the followed accounts' do
- get :index, params: params
+ get '/api/v2/search', headers: headers, params: params
expect(body_as_json[:accounts].pluck(:id)).to contain_exactly(ana.id.to_s)
end
@@ -73,7 +69,7 @@ RSpec.describe Api::V2::SearchController do
before { allow(Search).to receive(:new).and_raise(Mastodon::SyntaxError) }
it 'returns http unprocessable_entity' do
- get :index, params: params
+ get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(422)
end
@@ -83,7 +79,7 @@ RSpec.describe Api::V2::SearchController do
before { allow(Search).to receive(:new).and_raise(ActiveRecord::RecordNotFound) }
it 'returns http not_found' do
- get :index, params: params
+ get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(404)
end
@@ -92,11 +88,11 @@ RSpec.describe Api::V2::SearchController do
end
context 'without token' do
- describe 'GET #index' do
+ describe 'GET /api/v2/search' do
let(:search_params) { nil }
before do
- get :index, params: search_params
+ get '/api/v2/search', params: search_params
end
context 'without a `q` param' do
diff --git a/spec/requests/api/v2/suggestions_spec.rb b/spec/requests/api/v2/suggestions_spec.rb
new file mode 100644
index 000000000..5f1c97b8a
--- /dev/null
+++ b/spec/requests/api/v2/suggestions_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Suggestions API' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'read' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+
+ describe 'GET /api/v2/suggestions' do
+ it 'returns http success' do
+ get '/api/v2/suggestions', headers: headers
+
+ expect(response).to have_http_status(200)
+ end
+ end
+end
diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb
index c02a0800a..09eb5ddee 100644
--- a/spec/services/activitypub/process_account_service_spec.rb
+++ b/spec/services/activitypub/process_account_service_spec.rb
@@ -129,12 +129,10 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
stub_const 'ActivityPub::ProcessAccountService::SUBDOMAINS_RATELIMIT', 5
end
- it 'creates at least some accounts' do
- expect { subject }.to change { Account.remote.count }.by_at_least(2)
- end
-
- it 'creates no more account than the limit allows' do
- expect { subject }.to change { Account.remote.count }.by_at_most(5)
+ it 'creates accounts without exceeding rate limit' do
+ expect { subject }
+ .to create_some_remote_accounts
+ .and create_fewer_than_rate_limit_accounts
end
end
@@ -195,12 +193,20 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
end
end
- it 'creates at least some accounts' do
- expect { subject.call('user1', 'foo.test', payload) }.to change { Account.remote.count }.by_at_least(2)
- end
-
- it 'creates no more account than the limit allows' do
- expect { subject.call('user1', 'foo.test', payload) }.to change { Account.remote.count }.by_at_most(5)
+ it 'creates accounts without exceeding rate limit' do
+ expect { subject.call('user1', 'foo.test', payload) }
+ .to create_some_remote_accounts
+ .and create_fewer_than_rate_limit_accounts
end
end
+
+ private
+
+ def create_some_remote_accounts
+ change(Account.remote, :count).by_at_least(2)
+ end
+
+ def create_fewer_than_rate_limit_accounts
+ change(Account.remote, :count).by_at_most(5)
+ end
end
diff --git a/spec/services/delete_account_service_spec.rb b/spec/services/delete_account_service_spec.rb
index 68ab491e4..8a19d3cf7 100644
--- a/spec/services/delete_account_service_spec.rb
+++ b/spec/services/delete_account_service_spec.rb
@@ -27,8 +27,15 @@ RSpec.describe DeleteAccountService, type: :service do
let!(:account_note) { Fabricate(:account_note, account: account) }
- it 'deletes associated owned records' do
- expect { subject }.to change {
+ it 'deletes associated owned and target records and target notifications' do
+ expect { subject }
+ .to delete_associated_owned_records
+ .and delete_associated_target_records
+ .and delete_associated_target_notifications
+ end
+
+ def delete_associated_owned_records
+ change do
[
account.statuses,
account.media_attachments,
@@ -39,23 +46,23 @@ RSpec.describe DeleteAccountService, type: :service do
account.polls,
account.account_notes,
].map(&:count)
- }.from([2, 1, 1, 1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0, 0, 0, 0])
+ end.from([2, 1, 1, 1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0, 0, 0, 0])
end
- it 'deletes associated target records' do
- expect { subject }.to change {
+ def delete_associated_target_records
+ change do
[
AccountPin.where(target_account: account),
].map(&:count)
- }.from([1]).to([0])
+ end.from([1]).to([0])
end
- it 'deletes associated target notifications' do
- expect { subject }.to change {
+ def delete_associated_target_notifications
+ change do
%w(
poll favourite status mention follow
).map { |type| Notification.where(type: type).count }
- }.from([1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0])
+ end.from([1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0])
end
end
diff --git a/spec/services/suspend_account_service_spec.rb b/spec/services/suspend_account_service_spec.rb
index edb705008..c258995b7 100644
--- a/spec/services/suspend_account_service_spec.rb
+++ b/spec/services/suspend_account_service_spec.rb
@@ -18,14 +18,15 @@ RSpec.describe SuspendAccountService, type: :service do
account.suspend!
end
- it "unmerges from local followers' feeds" do
- subject
+ it 'unmerges from feeds of local followers and preserves suspended flag' do
+ expect { subject }
+ .to_not change_suspended_flag
expect(FeedManager.instance).to have_received(:unmerge_from_home).with(account, local_follower)
expect(FeedManager.instance).to have_received(:unmerge_from_list).with(account, list)
end
- it 'does not change the “suspended” flag' do
- expect { subject }.to_not change(account, :suspended?)
+ def change_suspended_flag
+ change(account, :suspended?)
end
end
diff --git a/spec/services/unsuspend_account_service_spec.rb b/spec/services/unsuspend_account_service_spec.rb
index c555b661e..2f737c621 100644
--- a/spec/services/unsuspend_account_service_spec.rb
+++ b/spec/services/unsuspend_account_service_spec.rb
@@ -45,14 +45,19 @@ RSpec.describe UnsuspendAccountService, type: :service do
remote_follower.follow!(account)
end
- it "merges back into local followers' feeds" do
+ it 'merges back into feeds of local followers and sends update' do
subject
+
+ expect_feeds_merged
+ expect_updates_sent
+ end
+
+ def expect_feeds_merged
expect(FeedManager.instance).to have_received(:merge_into_home).with(account, local_follower)
expect(FeedManager.instance).to have_received(:merge_into_list).with(account, list)
end
- it 'sends an update actor to followers and reporters' do
- subject
+ def expect_updates_sent
expect(a_request(:post, remote_follower.inbox_url).with { |req| match_update_actor_request(req, account) }).to have_been_made.once
expect(a_request(:post, remote_reporter.inbox_url).with { |req| match_update_actor_request(req, account) }).to have_been_made.once
end
@@ -73,19 +78,20 @@ RSpec.describe UnsuspendAccountService, type: :service do
allow(resolve_account_service).to receive(:call).with(account).and_return(account)
end
- it 're-fetches the account' do
- subject
+ it 're-fetches the account, merges feeds, and preserves suspended' do
+ expect { subject }
+ .to_not change_suspended_flag
+ expect_feeds_merged
expect(resolve_account_service).to have_received(:call).with(account)
end
- it "merges back into local followers' feeds" do
- subject
+ def expect_feeds_merged
expect(FeedManager.instance).to have_received(:merge_into_home).with(account, local_follower)
expect(FeedManager.instance).to have_received(:merge_into_list).with(account, list)
end
- it 'does not change the “suspended” flag' do
- expect { subject }.to_not change(account, :suspended?)
+ def change_suspended_flag
+ change(account, :suspended?)
end
end
@@ -97,19 +103,20 @@ RSpec.describe UnsuspendAccountService, type: :service do
end
end
- it 're-fetches the account' do
- subject
+ it 're-fetches the account, does not merge feeds, marks suspended' do
+ expect { subject }
+ .to change_suspended_to_true
expect(resolve_account_service).to have_received(:call).with(account)
+ expect_feeds_not_merged
end
- it "does not merge back into local followers' feeds" do
- subject
+ def expect_feeds_not_merged
expect(FeedManager.instance).to_not have_received(:merge_into_home).with(account, local_follower)
expect(FeedManager.instance).to_not have_received(:merge_into_list).with(account, list)
end
- it 'marks account as suspended' do
- expect { subject }.to change(account, :suspended?).from(false).to(true)
+ def change_suspended_to_true
+ change(account, :suspended?).from(false).to(true)
end
end
@@ -118,13 +125,14 @@ RSpec.describe UnsuspendAccountService, type: :service do
allow(resolve_account_service).to receive(:call).with(account).and_return(nil)
end
- it 're-fetches the account' do
+ it 're-fetches the account and does not merge feeds' do
subject
+
expect(resolve_account_service).to have_received(:call).with(account)
+ expect_feeds_not_merged
end
- it "does not merge back into local followers' feeds" do
- subject
+ def expect_feeds_not_merged
expect(FeedManager.instance).to_not have_received(:merge_into_home).with(account, local_follower)
expect(FeedManager.instance).to_not have_received(:merge_into_list).with(account, list)
end
diff --git a/spec/support/command_line_helpers.rb b/spec/support/command_line_helpers.rb
new file mode 100644
index 000000000..6f9d63d93
--- /dev/null
+++ b/spec/support/command_line_helpers.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module CommandLineHelpers
+ def output_results(*args)
+ output(
+ include(*args)
+ ).to_stdout
+ end
+end
diff --git a/yarn.lock b/yarn.lock
index ad792d26c..71f1ad160 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -52,7 +52,7 @@ __metadata:
languageName: node
linkType: hard
-"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5":
+"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5":
version: 7.23.5
resolution: "@babel/compat-data@npm:7.23.5"
checksum: 081278ed46131a890ad566a59c61600a5f9557bd8ee5e535890c8548192532ea92590742fd74bd9db83d74c669ef8a04a7e1c85cdea27f960233e3b83c3a957c
@@ -60,37 +60,37 @@ __metadata:
linkType: hard
"@babel/core@npm:^7.10.4, @babel/core@npm:^7.11.1, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1":
- version: 7.23.5
- resolution: "@babel/core@npm:7.23.5"
+ version: 7.23.6
+ resolution: "@babel/core@npm:7.23.6"
dependencies:
"@ampproject/remapping": "npm:^2.2.0"
"@babel/code-frame": "npm:^7.23.5"
- "@babel/generator": "npm:^7.23.5"
- "@babel/helper-compilation-targets": "npm:^7.22.15"
+ "@babel/generator": "npm:^7.23.6"
+ "@babel/helper-compilation-targets": "npm:^7.23.6"
"@babel/helper-module-transforms": "npm:^7.23.3"
- "@babel/helpers": "npm:^7.23.5"
- "@babel/parser": "npm:^7.23.5"
+ "@babel/helpers": "npm:^7.23.6"
+ "@babel/parser": "npm:^7.23.6"
"@babel/template": "npm:^7.22.15"
- "@babel/traverse": "npm:^7.23.5"
- "@babel/types": "npm:^7.23.5"
+ "@babel/traverse": "npm:^7.23.6"
+ "@babel/types": "npm:^7.23.6"
convert-source-map: "npm:^2.0.0"
debug: "npm:^4.1.0"
gensync: "npm:^1.0.0-beta.2"
json5: "npm:^2.2.3"
semver: "npm:^6.3.1"
- checksum: 311a512a870ee330a3f9a7ea89e5df790b2b5af0b1bd98b10b4edc0de2ac440f0df4d69ea2c0ee38a4b89041b9a495802741d93603be7d4fd834ec8bb6970bd2
+ checksum: a02bae7d916029b70706dc301535e1b31e5d216f55d4ee6f64a15825c6b69ee2c14c52a213d1497ec414e925ed4e9d897d41fb0d75df9fea28ed2c0008790e31
languageName: node
linkType: hard
-"@babel/generator@npm:^7.23.5, @babel/generator@npm:^7.7.2":
- version: 7.23.5
- resolution: "@babel/generator@npm:7.23.5"
+"@babel/generator@npm:^7.23.6, @babel/generator@npm:^7.7.2":
+ version: 7.23.6
+ resolution: "@babel/generator@npm:7.23.6"
dependencies:
- "@babel/types": "npm:^7.23.5"
+ "@babel/types": "npm:^7.23.6"
"@jridgewell/gen-mapping": "npm:^0.3.2"
"@jridgewell/trace-mapping": "npm:^0.3.17"
jsesc: "npm:^2.5.1"
- checksum: 14c6e874f796c4368e919bed6003bb0adc3ce837760b08f9e646d20aeb5ae7d309723ce6e4f06bcb4a2b5753145446c8e4425851380f695e40e71e1760f49e7b
+ checksum: 53540e905cd10db05d9aee0a5304e36927f455ce66f95d1253bb8a179f286b88fa7062ea0db354c566fe27f8bb96567566084ffd259f8feaae1de5eccc8afbda
languageName: node
linkType: hard
@@ -122,16 +122,16 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.6":
- version: 7.22.15
- resolution: "@babel/helper-compilation-targets@npm:7.22.15"
+"@babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.23.6":
+ version: 7.23.6
+ resolution: "@babel/helper-compilation-targets@npm:7.23.6"
dependencies:
- "@babel/compat-data": "npm:^7.22.9"
- "@babel/helper-validator-option": "npm:^7.22.15"
- browserslist: "npm:^4.21.9"
+ "@babel/compat-data": "npm:^7.23.5"
+ "@babel/helper-validator-option": "npm:^7.23.5"
+ browserslist: "npm:^4.22.2"
lru-cache: "npm:^5.1.1"
semver: "npm:^6.3.1"
- checksum: 45b9286861296e890f674a3abb199efea14a962a27d9b8adeb44970a9fd5c54e73a9e342e8414d2851cf4f98d5994537352fbce7b05ade32e9849bbd327f9ff1
+ checksum: ba38506d11185f48b79abf439462ece271d3eead1673dd8814519c8c903c708523428806f05f2ec5efd0c56e4e278698fac967e5a4b5ee842c32415da54bc6fa
languageName: node
linkType: hard
@@ -342,14 +342,14 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helpers@npm:^7.23.5":
- version: 7.23.5
- resolution: "@babel/helpers@npm:7.23.5"
+"@babel/helpers@npm:^7.23.6":
+ version: 7.23.6
+ resolution: "@babel/helpers@npm:7.23.6"
dependencies:
"@babel/template": "npm:^7.22.15"
- "@babel/traverse": "npm:^7.23.5"
- "@babel/types": "npm:^7.23.5"
- checksum: a37e2728eb4378a4888e5d614e28de7dd79b55ac8acbecd0e5c761273e2a02a8f33b34b1932d9069db55417ace2937cbf8ec37c42f1030ce6d228857d7ccaa4f
+ "@babel/traverse": "npm:^7.23.6"
+ "@babel/types": "npm:^7.23.6"
+ checksum: df1cf6607676ad36f52f652ec03536f2732d70aef5e76dba5c964e34d49f3c2d3dcf9fb3740db359f53071d74b64606a833d5ba156f79f437f71bfe06e2e7e19
languageName: node
linkType: hard
@@ -364,12 +364,12 @@ __metadata:
languageName: node
linkType: hard
-"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.5":
- version: 7.23.5
- resolution: "@babel/parser@npm:7.23.5"
+"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.6":
+ version: 7.23.6
+ resolution: "@babel/parser@npm:7.23.6"
bin:
parser: ./bin/babel-parser.js
- checksum: 3356aa90d7bafb4e2c7310e7c2c3d443c4be4db74913f088d3d577a1eb914ea4188e05fd50a47ce907a27b755c4400c4e3cbeee73dbeb37761f6ca85954f5a20
+ checksum: 6f76cd5ccae1fa9bcab3525b0865c6222e9c1d22f87abc69f28c5c7b2c8816a13361f5bd06bddbd5faf903f7320a8feba02545c981468acec45d12a03db7755e
languageName: node
linkType: hard
@@ -836,14 +836,15 @@ __metadata:
languageName: node
linkType: hard
-"@babel/plugin-transform-for-of@npm:^7.23.3":
- version: 7.23.3
- resolution: "@babel/plugin-transform-for-of@npm:7.23.3"
+"@babel/plugin-transform-for-of@npm:^7.23.6":
+ version: 7.23.6
+ resolution: "@babel/plugin-transform-for-of@npm:7.23.6"
dependencies:
"@babel/helper-plugin-utils": "npm:^7.22.5"
+ "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5"
peerDependencies:
"@babel/core": ^7.0.0-0
- checksum: 8a36202cfee312ba80e509c7c2131e6773524e572b4dc64a8ee95bd912634fdeb5ea91c6c7747ee30e03562d0f0d333f88ed7dbb929b36b60b8d74189189e12f
+ checksum: 46681b6ab10f3ca2d961f50d4096b62ab5d551e1adad84e64be1ee23e72eb2f26a1e30e617e853c74f1349fffe4af68d33921a128543b6f24b6d46c09a3e2aec
languageName: node
linkType: hard
@@ -1200,8 +1201,8 @@ __metadata:
linkType: hard
"@babel/plugin-transform-runtime@npm:^7.22.4":
- version: 7.23.4
- resolution: "@babel/plugin-transform-runtime@npm:7.23.4"
+ version: 7.23.6
+ resolution: "@babel/plugin-transform-runtime@npm:7.23.6"
dependencies:
"@babel/helper-module-imports": "npm:^7.22.15"
"@babel/helper-plugin-utils": "npm:^7.22.5"
@@ -1211,7 +1212,7 @@ __metadata:
semver: "npm:^6.3.1"
peerDependencies:
"@babel/core": ^7.0.0-0
- checksum: 6ac29012550cdd10b65ec43fef0c7f43904ec458c43d597f627d8f52807413e57ea94e3986dbace576d734e67c2d09be5e43e77c72567d18f8c4ac5e19844625
+ checksum: 94a7ee92f073df53fd8bebf9ed391a95553716077da1c6c3a57f10f042358c938495d55e6b09b4b50544c01f03560c4770c17698e1c24817a15d3668e8231249
languageName: node
linkType: hard
@@ -1333,11 +1334,11 @@ __metadata:
linkType: hard
"@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.22.4":
- version: 7.23.5
- resolution: "@babel/preset-env@npm:7.23.5"
+ version: 7.23.6
+ resolution: "@babel/preset-env@npm:7.23.6"
dependencies:
"@babel/compat-data": "npm:^7.23.5"
- "@babel/helper-compilation-targets": "npm:^7.22.15"
+ "@babel/helper-compilation-targets": "npm:^7.23.6"
"@babel/helper-plugin-utils": "npm:^7.22.5"
"@babel/helper-validator-option": "npm:^7.23.5"
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.23.3"
@@ -1377,7 +1378,7 @@ __metadata:
"@babel/plugin-transform-dynamic-import": "npm:^7.23.4"
"@babel/plugin-transform-exponentiation-operator": "npm:^7.23.3"
"@babel/plugin-transform-export-namespace-from": "npm:^7.23.4"
- "@babel/plugin-transform-for-of": "npm:^7.23.3"
+ "@babel/plugin-transform-for-of": "npm:^7.23.6"
"@babel/plugin-transform-function-name": "npm:^7.23.3"
"@babel/plugin-transform-json-strings": "npm:^7.23.4"
"@babel/plugin-transform-literals": "npm:^7.23.3"
@@ -1418,7 +1419,7 @@ __metadata:
semver: "npm:^6.3.1"
peerDependencies:
"@babel/core": ^7.0.0-0
- checksum: 2a0e1274dec045186e131c6433659b75492583290e8d41633c616f6bff829cb2e4b2f9a57f556283a54db3bd6aa697911e56a36f607911a29b731c445a5b5a06
+ checksum: 5b24d179af52f082d04b9b98cc4777e37bf31a97cef5a91d8917e996dbd75f2f743c88c40f80744cb8529355bb674619d150c0260c32d834aa4067e21d0c8962
languageName: node
linkType: hard
@@ -1483,11 +1484,11 @@ __metadata:
linkType: hard
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
- version: 7.23.5
- resolution: "@babel/runtime@npm:7.23.5"
+ version: 7.23.6
+ resolution: "@babel/runtime@npm:7.23.6"
dependencies:
regenerator-runtime: "npm:^0.14.0"
- checksum: ca679cc91bb7e424bc2db87bb58cc3b06ade916b9adb21fbbdc43e54cdaacb3eea201ceba2a0464b11d2eb65b9fe6a6ffcf4d7521fa52994f19be96f1af14788
+ checksum: d886954e985ef8e421222f7a2848884d96a752e0020d3078b920dd104e672fdf23bcc6f51a44313a048796319f1ac9d09c2c88ec8cbb4e1f09174bcd3335b9ff
languageName: node
linkType: hard
@@ -1502,32 +1503,32 @@ __metadata:
languageName: node
linkType: hard
-"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.5":
- version: 7.23.5
- resolution: "@babel/traverse@npm:7.23.5"
+"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.6":
+ version: 7.23.6
+ resolution: "@babel/traverse@npm:7.23.6"
dependencies:
"@babel/code-frame": "npm:^7.23.5"
- "@babel/generator": "npm:^7.23.5"
+ "@babel/generator": "npm:^7.23.6"
"@babel/helper-environment-visitor": "npm:^7.22.20"
"@babel/helper-function-name": "npm:^7.23.0"
"@babel/helper-hoist-variables": "npm:^7.22.5"
"@babel/helper-split-export-declaration": "npm:^7.22.6"
- "@babel/parser": "npm:^7.23.5"
- "@babel/types": "npm:^7.23.5"
- debug: "npm:^4.1.0"
+ "@babel/parser": "npm:^7.23.6"
+ "@babel/types": "npm:^7.23.6"
+ debug: "npm:^4.3.1"
globals: "npm:^11.1.0"
- checksum: c5ea793080ca6719b0a1612198fd25e361cee1f3c14142d7a518d2a1eeb5c1d21f7eec1b26c20ea6e1ddd8ed12ab50b960ff95ffd25be353b6b46e1b54d6f825
+ checksum: 5b4ebb94a00a7e1daf111e4b0b45a7998d5b7598637a14e75e855e88cc1b702789e09a958726b5d599a003be1e9032dbdfde4b88ea6061332228738950d5582d
languageName: node
linkType: hard
-"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
- version: 7.23.5
- resolution: "@babel/types@npm:7.23.5"
+"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
+ version: 7.23.6
+ resolution: "@babel/types@npm:7.23.6"
dependencies:
"@babel/helper-string-parser": "npm:^7.23.4"
"@babel/helper-validator-identifier": "npm:^7.22.20"
to-fast-properties: "npm:^2.0.0"
- checksum: 7dd5e2f59828ed046ad0b06b039df2524a8b728d204affb4fc08da2502b9dd3140b1356b5166515d229dc811539a8b70dcd4bc507e06d62a89f4091a38d0b0fb
+ checksum: 42cefce8a68bd09bb5828b4764aa5586c53c60128ac2ac012e23858e1c179347a4aac9c66fc577994fbf57595227611c5ec8270bf0cfc94ff033bbfac0550b70
languageName: node
linkType: hard
@@ -1726,9 +1727,9 @@ __metadata:
languageName: node
linkType: hard
-"@eslint/eslintrc@npm:^2.1.3":
- version: 2.1.3
- resolution: "@eslint/eslintrc@npm:2.1.3"
+"@eslint/eslintrc@npm:^2.1.4":
+ version: 2.1.4
+ resolution: "@eslint/eslintrc@npm:2.1.4"
dependencies:
ajv: "npm:^6.12.4"
debug: "npm:^4.3.2"
@@ -1739,14 +1740,14 @@ __metadata:
js-yaml: "npm:^4.1.0"
minimatch: "npm:^3.1.2"
strip-json-comments: "npm:^3.1.1"
- checksum: f4103f4346126292eb15581c5a1d12bef03410fd3719dedbdb92e1f7031d46a5a2d60de8566790445d5d4b70b75ba050876799a11f5fff8265a91ee3fa77dab0
+ checksum: 32f67052b81768ae876c84569ffd562491ec5a5091b0c1e1ca1e0f3c24fb42f804952fdd0a137873bc64303ba368a71ba079a6f691cee25beee9722d94cc8573
languageName: node
linkType: hard
-"@eslint/js@npm:8.54.0":
- version: 8.54.0
- resolution: "@eslint/js@npm:8.54.0"
- checksum: d61fb4a0be6af2d8cb290121c329697664a75d6255a29926d5454fb02aeb02b87112f67fdf218d10abac42f90c570ac366126751baefc5405d0e017ed0c946c5
+"@eslint/js@npm:8.55.0":
+ version: 8.55.0
+ resolution: "@eslint/js@npm:8.55.0"
+ checksum: 88ab9fc57a651becd2b32ec40a3958db27fae133b1ae77bebd733aa5bbd00a92f325bb02f20ad680d31c731fa49b22f060a4777dd52eb3e27da013d940bd978d
languageName: node
linkType: hard
@@ -2371,7 +2372,7 @@ __metadata:
eslint-plugin-jsx-a11y: "npm:~6.8.0"
eslint-plugin-prettier: "npm:^5.0.0"
eslint-plugin-promise: "npm:~6.1.1"
- eslint-plugin-react: "npm:~7.33.0"
+ eslint-plugin-react: "npm:^7.33.2"
eslint-plugin-react-hooks: "npm:^4.6.0"
file-loader: "npm:^6.2.0"
font-awesome: "npm:^4.7.0"
@@ -2893,8 +2894,8 @@ __metadata:
linkType: hard
"@testing-library/jest-dom@npm:^6.0.0":
- version: 6.1.4
- resolution: "@testing-library/jest-dom@npm:6.1.4"
+ version: 6.1.5
+ resolution: "@testing-library/jest-dom@npm:6.1.5"
dependencies:
"@adobe/css-tools": "npm:^4.3.1"
"@babel/runtime": "npm:^7.9.2"
@@ -2918,7 +2919,7 @@ __metadata:
optional: true
vitest:
optional: true
- checksum: 2e23f120613fd8ae6d5169bbc94f1a2e4c82b07182057dc94db8ec54ebf32555833442e6c43a187e59715d83704ffb5df49ba88a71f6f32d2683f3d95ba721c7
+ checksum: f3643a56fcd970b5c7e8fd10faf3c4817d8ab0e74fb1198d726643bdc5ac675ceaac3b0068c5b4fbad254470e8f98ed50028741de875a29ceaa2f854570979c9
languageName: node
linkType: hard
@@ -3027,11 +3028,11 @@ __metadata:
linkType: hard
"@types/emoji-mart@npm:^3.0.9":
- version: 3.0.13
- resolution: "@types/emoji-mart@npm:3.0.13"
+ version: 3.0.14
+ resolution: "@types/emoji-mart@npm:3.0.14"
dependencies:
"@types/react": "npm:*"
- checksum: 840f920c3242e1d274f0102e67cb2d00434e1fd370e0bcc8983b43b6b62322b01e3ddcd5fb078c60883e613530a7c70b8c40060624897543cd4da9441ca81486
+ checksum: 23ded65fce9b3355fbe903d3971cb67cc827a5d587464bb7e3f349615527ef4a9197b3bb59fa84c4391d1b901e7f200f686a7fc83f649ae2a51a0fb948cbadfb
languageName: node
linkType: hard
@@ -3175,12 +3176,12 @@ __metadata:
linkType: hard
"@types/jest@npm:^29.5.2":
- version: 29.5.10
- resolution: "@types/jest@npm:29.5.10"
+ version: 29.5.11
+ resolution: "@types/jest@npm:29.5.11"
dependencies:
expect: "npm:^29.0.0"
pretty-format: "npm:^29.0.0"
- checksum: b46171d59d12a5f69bbe710f65eaf59a8073337c6b4a67dff8158575caec53f1c61f8a7d645b34d6ac3c4ea398acd30f0c5d1c4a131c0c918798019264a3397d
+ checksum: 524a3394845214581278bf4d75055927261fbeac7e1a89cd621bd0636da37d265fe0a85eac58b5778758faad1cbd7c7c361dfc190c78ebde03a91cce33463261
languageName: node
linkType: hard
@@ -3374,11 +3375,11 @@ __metadata:
linkType: hard
"@types/react-helmet@npm:^6.1.6":
- version: 6.1.9
- resolution: "@types/react-helmet@npm:6.1.9"
+ version: 6.1.11
+ resolution: "@types/react-helmet@npm:6.1.11"
dependencies:
"@types/react": "npm:*"
- checksum: d1823582903d6e70f1f447c7bec9e844b6f85f5de84cbcde5c8bbeecc064db1394c786ed9b9ded30544afe5c91e57c7e8105171df1643998f64c0aeab9f7f2aa
+ checksum: f7b3bb2151d992a108ae46fed876fb9c8119108397d9a01d150c5642782997542c8b3c52e742b56e8689b7dbfa62ca9cfc76aa7e05dec4e60c652f7ef53fa783
languageName: node
linkType: hard
@@ -3495,13 +3496,13 @@ __metadata:
linkType: hard
"@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7":
- version: 18.2.38
- resolution: "@types/react@npm:18.2.38"
+ version: 18.2.43
+ resolution: "@types/react@npm:18.2.43"
dependencies:
"@types/prop-types": "npm:*"
"@types/scheduler": "npm:*"
csstype: "npm:^3.0.2"
- checksum: 56edd4756081b677e38ee23ad6d340658c5e2468785cb20968318cec357e1ea7ccf3ecd9534981741192dd1b894200acfaf0f1551b4795c6077668f6afc19345
+ checksum: 10477a50fbd3c0cc5b8a2ade679f442717f68fb27c8460b2aa1d3256cd18c48f742bbe5b9ee37a8c4c5f832ffa37b3a23c09fd96dd880a8e3182d8929c05e803
languageName: node
linkType: hard
@@ -3657,11 +3658,11 @@ __metadata:
linkType: hard
"@types/ws@npm:^8.5.9":
- version: 8.5.9
- resolution: "@types/ws@npm:8.5.9"
+ version: 8.5.10
+ resolution: "@types/ws@npm:8.5.10"
dependencies:
"@types/node": "npm:*"
- checksum: 678bdd6461c4653f2975c537fb673cb1918c331558e2d2422b69761c9ced67200bb07c664e2593f3864077a891cb7c13ef2a40d303b4aacb06173d095d8aa3ce
+ checksum: e9af279b984c4a04ab53295a40aa95c3e9685f04888df5c6920860d1dd073fcc57c7bd33578a04b285b2c655a0b52258d34bee0a20569dca8defb8393e1e5d29
languageName: node
linkType: hard
@@ -3682,14 +3683,14 @@ __metadata:
linkType: hard
"@typescript-eslint/eslint-plugin@npm:^6.0.0":
- version: 6.11.0
- resolution: "@typescript-eslint/eslint-plugin@npm:6.11.0"
+ version: 6.13.2
+ resolution: "@typescript-eslint/eslint-plugin@npm:6.13.2"
dependencies:
"@eslint-community/regexpp": "npm:^4.5.1"
- "@typescript-eslint/scope-manager": "npm:6.11.0"
- "@typescript-eslint/type-utils": "npm:6.11.0"
- "@typescript-eslint/utils": "npm:6.11.0"
- "@typescript-eslint/visitor-keys": "npm:6.11.0"
+ "@typescript-eslint/scope-manager": "npm:6.13.2"
+ "@typescript-eslint/type-utils": "npm:6.13.2"
+ "@typescript-eslint/utils": "npm:6.13.2"
+ "@typescript-eslint/visitor-keys": "npm:6.13.2"
debug: "npm:^4.3.4"
graphemer: "npm:^1.4.0"
ignore: "npm:^5.2.4"
@@ -3702,44 +3703,44 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: 6645aa09b9d51c5e3ea781eaf74da75b94f83f3e2d7b3dd988d5ce7eb82dd87e3509471cf2ee8c6b2428d907df5f1b02f29dbd04f54c2653f9566c8c4ce98009
+ checksum: 531a4406d872738d165c6a66cb26e976523c94053b022a8210dc9fd10e91b79b705bc0fcc77145e9744e4108b53bdba55e02a10dc17757b22be92aff57849384
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:^6.0.0":
- version: 6.11.0
- resolution: "@typescript-eslint/parser@npm:6.11.0"
+ version: 6.13.2
+ resolution: "@typescript-eslint/parser@npm:6.13.2"
dependencies:
- "@typescript-eslint/scope-manager": "npm:6.11.0"
- "@typescript-eslint/types": "npm:6.11.0"
- "@typescript-eslint/typescript-estree": "npm:6.11.0"
- "@typescript-eslint/visitor-keys": "npm:6.11.0"
+ "@typescript-eslint/scope-manager": "npm:6.13.2"
+ "@typescript-eslint/types": "npm:6.13.2"
+ "@typescript-eslint/typescript-estree": "npm:6.13.2"
+ "@typescript-eslint/visitor-keys": "npm:6.13.2"
debug: "npm:^4.3.4"
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
peerDependenciesMeta:
typescript:
optional: true
- checksum: e7caeb20069102e21f468fc0dbe7ff6fb6b1efa9e72f4c9f39d4a865ed0633f39130b593ef9ae8f394ca1d70563e15410faf30a482a97809951eaac6ed3a67da
+ checksum: 2c62b8cd8a37eb2ea59cd00e559f51a9f57af746e2040e872af3c58ddd3f4071ad7b7009789bdeb0e0d4ee0343bfe96ee77288020f3ae22d08e1674203f5e156
languageName: node
linkType: hard
-"@typescript-eslint/scope-manager@npm:6.11.0":
- version: 6.11.0
- resolution: "@typescript-eslint/scope-manager@npm:6.11.0"
+"@typescript-eslint/scope-manager@npm:6.13.2":
+ version: 6.13.2
+ resolution: "@typescript-eslint/scope-manager@npm:6.13.2"
dependencies:
- "@typescript-eslint/types": "npm:6.11.0"
- "@typescript-eslint/visitor-keys": "npm:6.11.0"
- checksum: d8999e2d1a4cbde8a79df5e3ec416f0e3db9532d39f2f4bb5a0ebdf954ae75c183d3277579ba05268fe2c88e88ef87f0fa12f02bb8d95d9e67d92e411241f3a3
+ "@typescript-eslint/types": "npm:6.13.2"
+ "@typescript-eslint/visitor-keys": "npm:6.13.2"
+ checksum: 9b159e5bb10dfb5953e71488200b4126378fc7e987ce7d90946aea9ec40cd66c7ada92399657c5d9794189b764ca6f4eb38a8dcb9e4c5aa50ab6000a39636b9c
languageName: node
linkType: hard
-"@typescript-eslint/type-utils@npm:6.11.0":
- version: 6.11.0
- resolution: "@typescript-eslint/type-utils@npm:6.11.0"
+"@typescript-eslint/type-utils@npm:6.13.2":
+ version: 6.13.2
+ resolution: "@typescript-eslint/type-utils@npm:6.13.2"
dependencies:
- "@typescript-eslint/typescript-estree": "npm:6.11.0"
- "@typescript-eslint/utils": "npm:6.11.0"
+ "@typescript-eslint/typescript-estree": "npm:6.13.2"
+ "@typescript-eslint/utils": "npm:6.13.2"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^1.0.1"
peerDependencies:
@@ -3747,23 +3748,23 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: ff68f2e052b8d688f1dc1a0050746704c8e0ab6263b47f1f52da73a7d251678e4950af23a95e1cd8e3fcea2457e6e5294ddbe01d29dafa2fdfb5b11ed9452a3f
+ checksum: 1ca97c78abdf479aea0c54e869fda2ae2f69de1974cc063062ce7b5b16c7fdf497ea15c50a29dd5941ea1b6b77e8f1213a5c272a747e334ac69ede083f327468
languageName: node
linkType: hard
-"@typescript-eslint/types@npm:6.11.0":
- version: 6.11.0
- resolution: "@typescript-eslint/types@npm:6.11.0"
- checksum: 23182813db39a5e9b9bcc1e85306c953f7b8b22d3885e41fcac0bd725c170fbcb70f4ce55633678cc5921dcf062fa0e55635eb39480c118a4411a00354820223
+"@typescript-eslint/types@npm:6.13.2":
+ version: 6.13.2
+ resolution: "@typescript-eslint/types@npm:6.13.2"
+ checksum: 029918ca5b1442bb4bc435773504ce32191e2c3e2fde8d4176bb6513f03e3dfa2aa9724b2d22b1640656d666b97f7a7ebfeaf67b881d5e07250828fa83e3ebe8
languageName: node
linkType: hard
-"@typescript-eslint/typescript-estree@npm:6.11.0":
- version: 6.11.0
- resolution: "@typescript-eslint/typescript-estree@npm:6.11.0"
+"@typescript-eslint/typescript-estree@npm:6.13.2":
+ version: 6.13.2
+ resolution: "@typescript-eslint/typescript-estree@npm:6.13.2"
dependencies:
- "@typescript-eslint/types": "npm:6.11.0"
- "@typescript-eslint/visitor-keys": "npm:6.11.0"
+ "@typescript-eslint/types": "npm:6.13.2"
+ "@typescript-eslint/visitor-keys": "npm:6.13.2"
debug: "npm:^4.3.4"
globby: "npm:^11.1.0"
is-glob: "npm:^4.0.3"
@@ -3772,34 +3773,34 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: 3e183e554e1bc74f065da3015f7137eb40c262f989c547701b1e3f4f20134e574e56b749288cd00d77b9d1ddb705546613c2457661ffc63b6060ffa97ba3aac8
+ checksum: 1c4c59dce0c51fdfee34d9f418e64fe28e3ec1a97661efc8a3d2780bdff36aff38de9090d356a968f394fa6d4e9c058936ce9cd260d4c44a52761ecd74915bce
languageName: node
linkType: hard
-"@typescript-eslint/utils@npm:6.11.0, @typescript-eslint/utils@npm:^6.5.0":
- version: 6.11.0
- resolution: "@typescript-eslint/utils@npm:6.11.0"
+"@typescript-eslint/utils@npm:6.13.2, @typescript-eslint/utils@npm:^6.5.0":
+ version: 6.13.2
+ resolution: "@typescript-eslint/utils@npm:6.13.2"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.4.0"
"@types/json-schema": "npm:^7.0.12"
"@types/semver": "npm:^7.5.0"
- "@typescript-eslint/scope-manager": "npm:6.11.0"
- "@typescript-eslint/types": "npm:6.11.0"
- "@typescript-eslint/typescript-estree": "npm:6.11.0"
+ "@typescript-eslint/scope-manager": "npm:6.13.2"
+ "@typescript-eslint/types": "npm:6.13.2"
+ "@typescript-eslint/typescript-estree": "npm:6.13.2"
semver: "npm:^7.5.4"
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
- checksum: c91eb4578607959acc2b43ddc791571682e45601a19b25d5d120786ed4af607656f83c5c1fa71972e549ddfb5542acf2f7d443ae93b32ee28192c22c106b8883
+ checksum: 84969be91e7949868eaaa289288c9d71927f0e427b572501b0991d8d62b40a4234f7287c35b35d276ccbb53e9ea5457b8250fcf4941e60e6b9ba4065fbfba416
languageName: node
linkType: hard
-"@typescript-eslint/visitor-keys@npm:6.11.0":
- version: 6.11.0
- resolution: "@typescript-eslint/visitor-keys@npm:6.11.0"
+"@typescript-eslint/visitor-keys@npm:6.13.2":
+ version: 6.13.2
+ resolution: "@typescript-eslint/visitor-keys@npm:6.13.2"
dependencies:
- "@typescript-eslint/types": "npm:6.11.0"
+ "@typescript-eslint/types": "npm:6.13.2"
eslint-visitor-keys: "npm:^3.4.1"
- checksum: 5f48329422b7f286196661d39e93e9defd7c5cf80e6c84c8d03459853f5d9f86a5e91c5e80ea572dcdb907ebbe503bbcc77aeb8b468c294b2aa7b3ccfc81cb88
+ checksum: c173bc1fcc42c3075a5ee094e7f3bf0279d98315c25ff49e20d02d79022b1d0402accfa113b070afb4d52a6f6d180594b67baa8b6a784eabdf82b54dd1ff454c
languageName: node
linkType: hard
@@ -4168,12 +4169,12 @@ __metadata:
languageName: node
linkType: hard
-"ansi-escapes@npm:^5.0.0":
- version: 5.0.0
- resolution: "ansi-escapes@npm:5.0.0"
+"ansi-escapes@npm:^6.2.0":
+ version: 6.2.0
+ resolution: "ansi-escapes@npm:6.2.0"
dependencies:
- type-fest: "npm:^1.0.2"
- checksum: f705cc7fbabb981ddf51562cd950792807bccd7260cc3d9478a619dda62bff6634c87ca100f2545ac7aade9b72652c4edad8c7f0d31a0b949b5fa58f33eaf0d0
+ type-fest: "npm:^3.0.0"
+ checksum: 3eec75deedd8b10192c5f98e4cd9715cc3ff268d33fc463c24b7d22446668bfcd4ad1803993ea89c0f51f88b5a3399572bacb7c8cb1a067fc86e189c5f3b0c7e
languageName: node
linkType: hard
@@ -4239,7 +4240,7 @@ __metadata:
languageName: node
linkType: hard
-"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0":
+"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1":
version: 6.2.1
resolution: "ansi-styles@npm:6.2.1"
checksum: 5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c
@@ -5170,17 +5171,17 @@ __metadata:
languageName: node
linkType: hard
-"browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.21.9, browserslist@npm:^4.22.1":
- version: 4.22.1
- resolution: "browserslist@npm:4.22.1"
+"browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.22.1, browserslist@npm:^4.22.2":
+ version: 4.22.2
+ resolution: "browserslist@npm:4.22.2"
dependencies:
- caniuse-lite: "npm:^1.0.30001541"
- electron-to-chromium: "npm:^1.4.535"
- node-releases: "npm:^2.0.13"
+ caniuse-lite: "npm:^1.0.30001565"
+ electron-to-chromium: "npm:^1.4.601"
+ node-releases: "npm:^2.0.14"
update-browserslist-db: "npm:^1.0.13"
bin:
browserslist: cli.js
- checksum: 6810f2d63f171d0b7b8d38cf091708e00cb31525501810a507839607839320d66e657293b0aa3d7f051ecbc025cb07390a90c037682c1d05d12604991e41050b
+ checksum: 2a331aab90503130043ca41dd5d281fa1e89d5e076d07a2d75e76bf4d693bd56e73d5abcd8c4f39119da6328d450578c216cf1cd5c99b82d8a90a2ae6271b465
languageName: node
linkType: hard
@@ -5408,10 +5409,10 @@ __metadata:
languageName: node
linkType: hard
-"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001541":
- version: 1.0.30001561
- resolution: "caniuse-lite@npm:1.0.30001561"
- checksum: 6e84c84026fee53edbdbb5aded7a04a036aae4c2e367cf6bdc90c6783a591e2fdcfcdebcc4e774aca61092e542a61200c8c16b06659396492426033c4dbcc618
+"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001565":
+ version: 1.0.30001568
+ resolution: "caniuse-lite@npm:1.0.30001568"
+ checksum: 13f01e5a2481134bd61cf565ce9fecbd8e107902927a0dcf534230a92191a81f1715792170f5f39719c767c3a96aa6df9917a8d5601f15bbd5e4041a8cfecc99
languageName: node
linkType: hard
@@ -5584,13 +5585,13 @@ __metadata:
languageName: node
linkType: hard
-"cli-truncate@npm:^3.1.0":
- version: 3.1.0
- resolution: "cli-truncate@npm:3.1.0"
+"cli-truncate@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "cli-truncate@npm:4.0.0"
dependencies:
slice-ansi: "npm:^5.0.0"
- string-width: "npm:^5.0.0"
- checksum: a19088878409ec0e5dc2659a5166929629d93cfba6d68afc9cde2282fd4c751af5b555bf197047e31c87c574396348d011b7aa806fec29c4139ea4f7f00b324c
+ string-width: "npm:^7.0.0"
+ checksum: d7f0b73e3d9b88cb496e6c086df7410b541b56a43d18ade6a573c9c18bd001b1c3fba1ad578f741a4218fdc794d042385f8ac02c25e1c295a2d8b9f3cb86eb4c
languageName: node
linkType: hard
@@ -5960,9 +5961,9 @@ __metadata:
linkType: hard
"core-js@npm:^3.30.2":
- version: 3.33.3
- resolution: "core-js@npm:3.33.3"
- checksum: 08abdc9470c8228b9d09f61e62ab312738681202c4c34e9638889125b304b235f34c4fe22e9d41c20906ac0fcc807dca57c5ff7d6b90021bf64e8fe23461d9ab
+ version: 3.34.0
+ resolution: "core-js@npm:3.34.0"
+ checksum: 408a77898abe03bf3e5dec2a451c36f4745081cca9022f8bdf9b817d57bb6d3a534d555f47a4b95e1daa5e21dbc79122eac2402e25720d425f5925127e55dcd8
languageName: node
linkType: hard
@@ -6413,7 +6414,7 @@ __metadata:
languageName: node
linkType: hard
-"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.4":
+"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4":
version: 4.3.4
resolution: "debug@npm:4.3.4"
dependencies:
@@ -6955,10 +6956,10 @@ __metadata:
languageName: node
linkType: hard
-"electron-to-chromium@npm:^1.4.535":
- version: 1.4.576
- resolution: "electron-to-chromium@npm:1.4.576"
- checksum: b0b9e7ba803bf93ffac9cb830ed2b0e0eb07f20066127065f9ab9e08e4e6a5812040e03d76f6ee9bc59e03fb938fd414e83d4883b29111303e9e88633cf2dce4
+"electron-to-chromium@npm:^1.4.601":
+ version: 1.4.609
+ resolution: "electron-to-chromium@npm:1.4.609"
+ checksum: 9675a79388acbaff5953a4c61589af7da93e0d1f9d6a3b284c7630f10126eb0998557b07448514214d5a3d19025310039b55f405ab701b1253130fc94907f743
languageName: node
linkType: hard
@@ -6997,7 +6998,7 @@ __metadata:
languageName: node
linkType: hard
-"emoji-regex@npm:10.3.0, emoji-regex@npm:^10.2.1":
+"emoji-regex@npm:10.3.0, emoji-regex@npm:^10.2.1, emoji-regex@npm:^10.3.0":
version: 10.3.0
resolution: "emoji-regex@npm:10.3.0"
checksum: b4838e8dcdceb44cf47f59abe352c25ff4fe7857acaf5fb51097c427f6f75b44d052eb907a7a3b86f86bc4eae3a93f5c2b7460abe79c407307e6212d65c91163
@@ -7313,13 +7314,13 @@ __metadata:
linkType: hard
"eslint-config-prettier@npm:^9.0.0":
- version: 9.0.0
- resolution: "eslint-config-prettier@npm:9.0.0"
+ version: 9.1.0
+ resolution: "eslint-config-prettier@npm:9.1.0"
peerDependencies:
eslint: ">=7.0.0"
bin:
eslint-config-prettier: bin/cli.js
- checksum: bc1f661915845c631824178942e5d02f858fe6d0ea796f0050d63e0f681927b92696e81139dd04714c08c3e7de580fd079c66162e40070155ba79eaee78ab5d0
+ checksum: 6d332694b36bc9ac6fdb18d3ca2f6ac42afa2ad61f0493e89226950a7091e38981b66bac2b47ba39d15b73fff2cd32c78b850a9cf9eed9ca9a96bfb2f3a2f10d
languageName: node
linkType: hard
@@ -7501,7 +7502,7 @@ __metadata:
languageName: node
linkType: hard
-"eslint-plugin-react@npm:~7.33.0":
+"eslint-plugin-react@npm:^7.33.2":
version: 7.33.2
resolution: "eslint-plugin-react@npm:7.33.2"
dependencies:
@@ -7555,13 +7556,13 @@ __metadata:
linkType: hard
"eslint@npm:^8.41.0":
- version: 8.54.0
- resolution: "eslint@npm:8.54.0"
+ version: 8.55.0
+ resolution: "eslint@npm:8.55.0"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.2.0"
"@eslint-community/regexpp": "npm:^4.6.1"
- "@eslint/eslintrc": "npm:^2.1.3"
- "@eslint/js": "npm:8.54.0"
+ "@eslint/eslintrc": "npm:^2.1.4"
+ "@eslint/js": "npm:8.55.0"
"@humanwhocodes/config-array": "npm:^0.11.13"
"@humanwhocodes/module-importer": "npm:^1.0.1"
"@nodelib/fs.walk": "npm:^1.2.8"
@@ -7598,7 +7599,7 @@ __metadata:
text-table: "npm:^0.2.0"
bin:
eslint: bin/eslint.js
- checksum: 4f205f832bdbd0218cde374b067791f4f76d7abe8de86b2dc849c273899051126d912ebf71531ee49b8eeaa22cad77febdc8f2876698dc2a76e84a8cb976af22
+ checksum: d28c0b60f19bb7d355cb8393e77b018c8f548dba3f820b799c89bb2e0c436ee26084e700c5e57e1e97e7972ec93065277849141b82e7b0c0d02c2dc1e553a2a1
languageName: node
linkType: hard
@@ -8387,6 +8388,13 @@ __metadata:
languageName: node
linkType: hard
+"get-east-asian-width@npm:^1.0.0":
+ version: 1.2.0
+ resolution: "get-east-asian-width@npm:1.2.0"
+ checksum: 914b1e217cf38436c24b4c60b4c45289e39a45bf9e65ef9fd343c2815a1a02b8a0215aeec8bf9c07c516089004b6e3826332481f40a09529fcadbf6e579f286b
+ languageName: node
+ linkType: hard
+
"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2":
version: 1.2.2
resolution: "get-intrinsic@npm:1.2.2"
@@ -9610,6 +9618,15 @@ __metadata:
languageName: node
linkType: hard
+"is-fullwidth-code-point@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "is-fullwidth-code-point@npm:5.0.0"
+ dependencies:
+ get-east-asian-width: "npm:^1.0.0"
+ checksum: cd591b27d43d76b05fa65ed03eddce57a16e1eca0b7797ff7255de97019bcaf0219acfc0c4f7af13319e13541f2a53c0ace476f442b13267b9a6a7568f2b65c8
+ languageName: node
+ linkType: hard
+
"is-generator-fn@npm:^2.0.0":
version: 2.1.0
resolution: "is-generator-fn@npm:2.1.0"
@@ -10892,7 +10909,14 @@ __metadata:
languageName: node
linkType: hard
-"lilconfig@npm:2.1.0, lilconfig@npm:^2.1.0":
+"lilconfig@npm:3.0.0":
+ version: 3.0.0
+ resolution: "lilconfig@npm:3.0.0"
+ checksum: 7f5ee7a658dc016cacf146815e8d88b06f06f4402823b8b0934e305a57a197f55ccc9c5cd4fb5ea1b2b821c8ccaf2d54abd59602a4931af06eabda332388d3e6
+ languageName: node
+ linkType: hard
+
+"lilconfig@npm:^2.1.0":
version: 2.1.0
resolution: "lilconfig@npm:2.1.0"
checksum: 64645641aa8d274c99338e130554abd6a0190533c0d9eb2ce7ebfaf2e05c7d9961f3ffe2bfa39efd3b60c521ba3dd24fa236fe2775fc38501bf82bf49d4678b8
@@ -10907,36 +10931,36 @@ __metadata:
linkType: hard
"lint-staged@npm:^15.0.0":
- version: 15.1.0
- resolution: "lint-staged@npm:15.1.0"
+ version: 15.2.0
+ resolution: "lint-staged@npm:15.2.0"
dependencies:
chalk: "npm:5.3.0"
commander: "npm:11.1.0"
debug: "npm:4.3.4"
execa: "npm:8.0.1"
- lilconfig: "npm:2.1.0"
- listr2: "npm:7.0.2"
+ lilconfig: "npm:3.0.0"
+ listr2: "npm:8.0.0"
micromatch: "npm:4.0.5"
pidtree: "npm:0.6.0"
string-argv: "npm:0.3.2"
yaml: "npm:2.3.4"
bin:
lint-staged: bin/lint-staged.js
- checksum: d427408be98df7558e918593cb765d5caaa67a5cdca89671fb54280a6c959f4e448db36d4f85e8e0bd9c2c1e996aa133916925cf47c9df573b47308d5e298d84
+ checksum: 4a1ff25dd06dbd4346fd244c9a0ebb936532ba18c0caedeb895c2e232f3c6c5fd08f6667624716660bc29e3e0f9f0440a9175114394616e991ebd5fab4b1f092
languageName: node
linkType: hard
-"listr2@npm:7.0.2":
- version: 7.0.2
- resolution: "listr2@npm:7.0.2"
+"listr2@npm:8.0.0":
+ version: 8.0.0
+ resolution: "listr2@npm:8.0.0"
dependencies:
- cli-truncate: "npm:^3.1.0"
+ cli-truncate: "npm:^4.0.0"
colorette: "npm:^2.0.20"
eventemitter3: "npm:^5.0.1"
- log-update: "npm:^5.0.1"
+ log-update: "npm:^6.0.0"
rfdc: "npm:^1.3.0"
- wrap-ansi: "npm:^8.1.0"
- checksum: 37b6501be84ebea66dcce07c5f86c224aff0c01c9fb43f5055cc38a063030281d58198aad0aad481f174438309831ddf5f763b890e820cd7b7b4f4a5dfa229c9
+ wrap-ansi: "npm:^9.0.0"
+ checksum: 6e356df9127c68b69186c927c993645223557e941a76b0bb210e35786aedc53f577df437251db804606ff37ac509c5d945289a84b3daee7fadf2e3dcb889ecc9
languageName: node
linkType: hard
@@ -11104,16 +11128,16 @@ __metadata:
languageName: node
linkType: hard
-"log-update@npm:^5.0.1":
- version: 5.0.1
- resolution: "log-update@npm:5.0.1"
+"log-update@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "log-update@npm:6.0.0"
dependencies:
- ansi-escapes: "npm:^5.0.0"
+ ansi-escapes: "npm:^6.2.0"
cli-cursor: "npm:^4.0.0"
- slice-ansi: "npm:^5.0.0"
- strip-ansi: "npm:^7.0.1"
- wrap-ansi: "npm:^8.0.1"
- checksum: 1050ea2027e80f32e132aace909987cb00c2719368c78b82ffca681a5b3f4020eeb5f4b4e310c47c35c6c36aff258c1d1bc51485ac44d6fdac9eb0a4275c539f
+ slice-ansi: "npm:^7.0.0"
+ strip-ansi: "npm:^7.1.0"
+ wrap-ansi: "npm:^9.0.0"
+ checksum: e0b3c3401ef49ce3eb17e2f83d644765e4f7988498fc1344eaa4f31ab30e510dcc469a7fb64dc01bd1c8d9237d917598fa677a9818705fb3774c10f6e9d4b27c
languageName: node
linkType: hard
@@ -11761,12 +11785,12 @@ __metadata:
languageName: node
linkType: hard
-"nanoid@npm:^3.3.6":
- version: 3.3.6
- resolution: "nanoid@npm:3.3.6"
+"nanoid@npm:^3.3.7":
+ version: 3.3.7
+ resolution: "nanoid@npm:3.3.7"
bin:
nanoid: bin/nanoid.cjs
- checksum: 606b355960d0fcbe3d27924c4c52ef7d47d3b57208808ece73279420d91469b01ec1dce10fae512b6d4a8c5a5432b352b228336a8b2202a6ea68e67fa348e2ee
+ checksum: e3fb661aa083454f40500473bb69eedb85dc160e763150b9a2c567c7e9ff560ce028a9f833123b618a6ea742e311138b591910e795614a629029e86e180660f3
languageName: node
linkType: hard
@@ -11907,10 +11931,10 @@ __metadata:
languageName: node
linkType: hard
-"node-releases@npm:^2.0.13":
- version: 2.0.13
- resolution: "node-releases@npm:2.0.13"
- checksum: 2fb44bf70fc949d27f3a48a7fd1a9d1d603ddad4ccd091f26b3fb8b1da976605d919330d7388ccd55ca2ade0dc8b2e12841ba19ef249c8bb29bf82532d401af7
+"node-releases@npm:^2.0.14":
+ version: 2.0.14
+ resolution: "node-releases@npm:2.0.14"
+ checksum: 199fc93773ae70ec9969bc6d5ac5b2bbd6eb986ed1907d751f411fef3ede0e4bfdb45ceb43711f8078bea237b6036db8b1bf208f6ff2b70c7d615afd157f3ab9
languageName: node
linkType: hard
@@ -13195,13 +13219,13 @@ __metadata:
linkType: hard
"postcss@npm:^8.2.15, postcss@npm:^8.4.24, postcss@npm:^8.4.28":
- version: 8.4.31
- resolution: "postcss@npm:8.4.31"
+ version: 8.4.32
+ resolution: "postcss@npm:8.4.32"
dependencies:
- nanoid: "npm:^3.3.6"
+ nanoid: "npm:^3.3.7"
picocolors: "npm:^1.0.0"
source-map-js: "npm:^1.0.2"
- checksum: 748b82e6e5fc34034dcf2ae88ea3d11fd09f69b6c50ecdd3b4a875cfc7cdca435c958b211e2cb52355422ab6fccb7d8f2f2923161d7a1b281029e4a913d59acf
+ checksum: 39308a9195fa34d4dbdd7b58a896cff0c7809f84f7a4ac1b95b68ca86c9138a395addff33075668ed3983d41b90aac05754c445237a9365eb1c3a5602ebd03ad
languageName: node
linkType: hard
@@ -13289,11 +13313,11 @@ __metadata:
linkType: hard
"prettier@npm:^3.0.0":
- version: 3.1.0
- resolution: "prettier@npm:3.1.0"
+ version: 3.1.1
+ resolution: "prettier@npm:3.1.1"
bin:
prettier: bin/prettier.cjs
- checksum: a45ea70aa97fde162ea4c4aba3dfc7859aa6a732a1db34458d9535dc3c2c16d3bc3fb5689e6cd76aa835562555303b02d9449fd2e15af3b73c8053557e25c5b6
+ checksum: facc944ba20e194ff4db765e830ffbcb642803381f0d2033ed397e79904fa4ccc877dc25ad68f42d36985c01d051c990ca1b905fb83d2d7d65fe69e4386fa1a3
languageName: node
linkType: hard
@@ -14640,8 +14664,8 @@ __metadata:
linkType: hard
"sass-loader@npm:^10.2.0":
- version: 10.4.1
- resolution: "sass-loader@npm:10.4.1"
+ version: 10.5.0
+ resolution: "sass-loader@npm:10.5.0"
dependencies:
klona: "npm:^2.0.4"
loader-utils: "npm:^2.0.0"
@@ -14650,7 +14674,7 @@ __metadata:
semver: "npm:^7.3.2"
peerDependencies:
fibers: ">= 3.1.0"
- node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+ node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
sass: ^1.3.0
webpack: ^4.36.0 || ^5.0.0
peerDependenciesMeta:
@@ -14660,7 +14684,7 @@ __metadata:
optional: true
sass:
optional: true
- checksum: bf04a440fe471928f3cf884bc12c6b70bc391795b35510b1b9021e8a2cca3b8f966aef9518f4171e87e9cb78193a774f695921e6b61881a1580ae0a3c7b1b5e4
+ checksum: be5da7784fd21c4f526cc3afaa1a765ba44cdc2f9798ecbac87b296ab44184ac5ba9bbda68a7a86f8cdcb6130acceefeb8912260fca14bdfc97f9dad02658400
languageName: node
linkType: hard
@@ -15050,6 +15074,16 @@ __metadata:
languageName: node
linkType: hard
+"slice-ansi@npm:^7.0.0":
+ version: 7.1.0
+ resolution: "slice-ansi@npm:7.1.0"
+ dependencies:
+ ansi-styles: "npm:^6.2.1"
+ is-fullwidth-code-point: "npm:^5.0.0"
+ checksum: 631c971d4abf56cf880f034d43fcc44ff883624867bf11ecbd538c47343911d734a4656d7bc02362b40b89d765652a7f935595441e519b59e2ad3f4d5d6fe7ca
+ languageName: node
+ linkType: hard
+
"smart-buffer@npm:^4.2.0":
version: 4.2.0
resolution: "smart-buffer@npm:4.2.0"
@@ -15493,7 +15527,7 @@ __metadata:
languageName: node
linkType: hard
-"string-width@npm:^5.0.0, string-width@npm:^5.0.1, string-width@npm:^5.1.2":
+"string-width@npm:^5.0.1, string-width@npm:^5.1.2":
version: 5.1.2
resolution: "string-width@npm:5.1.2"
dependencies:
@@ -15504,6 +15538,17 @@ __metadata:
languageName: node
linkType: hard
+"string-width@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "string-width@npm:7.0.0"
+ dependencies:
+ emoji-regex: "npm:^10.3.0"
+ get-east-asian-width: "npm:^1.0.0"
+ strip-ansi: "npm:^7.1.0"
+ checksum: 8ffaeeccf4a56ccce5b6235d0b99ee3a581e3e3e5d453708efe7aa8e264fa3a858b4fe2244310cb71c6a20d8c05921cedc8b2ccd88cbaad9f5c92051ff68edc6
+ languageName: node
+ linkType: hard
+
"string.prototype.matchall@npm:^4.0.6, string.prototype.matchall@npm:^4.0.8":
version: 4.0.8
resolution: "string.prototype.matchall@npm:4.0.8"
@@ -15618,7 +15663,7 @@ __metadata:
languageName: node
linkType: hard
-"strip-ansi@npm:^7.0.1":
+"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0":
version: 7.1.0
resolution: "strip-ansi@npm:7.1.0"
dependencies:
@@ -16379,13 +16424,20 @@ __metadata:
languageName: node
linkType: hard
-"type-fest@npm:^1.0.1, type-fest@npm:^1.0.2, type-fest@npm:^1.2.1, type-fest@npm:^1.2.2":
+"type-fest@npm:^1.0.1, type-fest@npm:^1.2.1, type-fest@npm:^1.2.2":
version: 1.4.0
resolution: "type-fest@npm:1.4.0"
checksum: a3c0f4ee28ff6ddf800d769eafafcdeab32efa38763c1a1b8daeae681920f6e345d7920bf277245235561d8117dab765cb5f829c76b713b4c9de0998a5397141
languageName: node
linkType: hard
+"type-fest@npm:^3.0.0":
+ version: 3.13.1
+ resolution: "type-fest@npm:3.13.1"
+ checksum: 547d22186f73a8c04590b70dcf63baff390078c75ea8acd366bbd510fd0646e348bd1970e47ecf795b7cff0b41d26e9c475c1fedd6ef5c45c82075fbf916b629
+ languageName: node
+ linkType: hard
+
"type-is@npm:~1.6.18":
version: 1.6.18
resolution: "type-is@npm:1.6.18"
@@ -16444,22 +16496,22 @@ __metadata:
linkType: hard
"typescript@npm:5, typescript@npm:^5.0.4":
- version: 5.3.2
- resolution: "typescript@npm:5.3.2"
+ version: 5.3.3
+ resolution: "typescript@npm:5.3.3"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
- checksum: d7dbe1fbe19039e36a65468ea64b5d338c976550394ba576b7af9c68ed40c0bc5d12ecce390e4b94b287a09a71bd3229f19c2d5680611f35b7c53a3898791159
+ checksum: e33cef99d82573624fc0f854a2980322714986bc35b9cb4d1ce736ed182aeab78e2cb32b385efa493b2a976ef52c53e20d6c6918312353a91850e2b76f1ea44f
languageName: node
linkType: hard
"typescript@patch:typescript@npm%3A5#optional!builtin