diff --git a/.eslintrc.js b/.eslintrc.js index d5f0ae1ac5..3bac9ed694 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,7 +9,6 @@ module.exports = { 'plugin:import/recommended', 'plugin:promise/recommended', 'plugin:jsdoc/recommended', - 'plugin:prettier/recommended', ], env: { @@ -63,7 +62,9 @@ module.exports = { 'consistent-return': 'error', 'dot-notation': 'error', eqeqeq: ['error', 'always', { 'null': 'ignore' }], + 'indent': ['error', 2], 'jsx-quotes': ['error', 'prefer-single'], + 'semi': ['error', 'always'], 'no-case-declarations': 'off', 'no-catch-shadow': 'error', 'no-console': [ diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml index bace35f112..6ba6945cd4 100644 --- a/.haml-lint_todo.yml +++ b/.haml-lint_todo.yml @@ -1,13 +1,13 @@ # This configuration was generated by # `haml-lint --auto-gen-config` -# on 2023-10-03 08:32:28 -0400 using Haml-Lint version 0.51.0. +# on 2023-10-11 11:31:24 -0400 using Haml-Lint version 0.51.0. # The point is for the user to remove these configuration records # one by one as the lints are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of Haml-Lint, may require this file to be generated again. linters: - # Offense count: 944 + # Offense count: 946 LineLength: enabled: false @@ -30,10 +30,6 @@ linters: # Offense count: 15 InstanceVariables: exclude: - - 'app/views/admin/reports/_actions.html.haml' - - 'app/views/auth/registrations/_status.html.haml' - - 'app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml' - - 'app/views/relationships/_account.html.haml' - 'app/views/application/_sidebar.html.haml' # Offense count: 2 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index a31e00d540..1936bc6815 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -180,7 +180,6 @@ RSpec/LetSetup: - 'spec/controllers/api/v1/accounts/statuses_controller_spec.rb' - 'spec/controllers/api/v1/admin/accounts_controller_spec.rb' - 'spec/controllers/api/v1/filters_controller_spec.rb' - - 'spec/controllers/api/v1/followed_tags_controller_spec.rb' - 'spec/controllers/api/v2/admin/accounts_controller_spec.rb' - 'spec/controllers/api/v2/filters/keywords_controller_spec.rb' - 'spec/controllers/api/v2/filters/statuses_controller_spec.rb' diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eebe5c85d..f9303f0115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. ### Fixed +- Fix duplicate reports being sent when reporting some remote posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27355)) - Fix clicking on already-opened thread post scrolling to the top of the thread ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27331), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27338), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27350)) - Fix some remote posts getting truncated ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27307)) - Fix some cases of infinite scroll code trying to fetch inaccessible posts in a loop ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27286)) diff --git a/Gemfile.lock b/Gemfile.lock index ec52cb2c4b..0e1423aebe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -146,7 +146,7 @@ GEM net-http-persistent (~> 4.0) nokogiri (~> 1, >= 1.10.8) base64 (0.1.1) - bcrypt (3.1.18) + bcrypt (3.1.19) better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) @@ -210,17 +210,17 @@ GEM database_cleaner-core (2.0.1) date (3.3.3) debug_inspector (1.1.0) - devise (4.9.2) + devise (4.9.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-two-factor (4.1.0) - activesupport (< 7.1) + devise-two-factor (4.1.1) + activesupport (~> 7.0) attr_encrypted (>= 1.3, < 5, != 2) devise (~> 4.0) - railties (< 7.1) + railties (~> 7.0) rotp (~> 6.0) devise_pam_authenticatable2 (9.2.0) devise (>= 4.0.0) @@ -412,12 +412,12 @@ GEM llhttp-ffi (0.4.0) ffi-compiler (~> 1.0) rake (~> 13.0) - lograge (0.13.0) + lograge (0.14.0) actionpack (>= 4) activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.21.3) + loofah (2.21.4) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -440,7 +440,7 @@ GEM mime-types-data (3.2023.0808) mini_mime (1.1.5) mini_portile2 (2.8.4) - minitest (5.19.0) + minitest (5.20.0) msgpack (1.7.1) multi_json (1.15.0) multipart-post (2.3.0) @@ -493,7 +493,7 @@ GEM orm_adapter (0.5.0) ox (2.14.17) parallel (1.23.0) - parser (3.2.2.3) + parser (3.2.2.4) ast (~> 2.4.1) racc parslet (2.0.0) @@ -554,7 +554,7 @@ GEM actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) activesupport (>= 5.0.1.rc1) - rails-dom-testing (2.1.1) + rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) @@ -583,10 +583,10 @@ GEM redis (>= 4) redlock (1.3.2) redis (>= 3.0.0, < 6.0) - regexp_parser (2.8.1) + regexp_parser (2.8.2) request_store (1.5.1) rack (>= 1.4) - responders (3.1.0) + responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) rexml (3.2.6) @@ -622,12 +622,12 @@ GEM sidekiq (>= 5, < 8) rspec-support (3.12.1) rspec_chunked (0.6) - rubocop (1.56.4) + rubocop (1.57.1) base64 (~> 0.1.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 3.2.2.3) + parser (>= 3.2.2.4) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) @@ -673,7 +673,7 @@ GEM rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) semantic_range (3.0.0) - sidekiq (6.5.10) + sidekiq (6.5.12) connection_pool (>= 2.2.5, < 3) rack (~> 2.0) redis (>= 4.5.0, < 5) @@ -791,7 +791,7 @@ GEM xorcist (1.1.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.11) + zeitwerk (2.6.12) PLATFORMS ruby diff --git a/app/controllers/concerns/two_factor_authentication_concern.rb b/app/controllers/concerns/two_factor_authentication_concern.rb index 9eb45b90d6..bc2d194c33 100644 --- a/app/controllers/concerns/two_factor_authentication_concern.rb +++ b/app/controllers/concerns/two_factor_authentication_concern.rb @@ -5,6 +5,7 @@ module TwoFactorAuthenticationConcern included do prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create] + helper_method :webauthn_enabled? end def two_factor_enabled? @@ -87,4 +88,10 @@ module TwoFactorAuthenticationConcern set_locale { render :two_factor } end + + protected + + def webauthn_enabled? + @webauthn_enabled + end end diff --git a/app/javascript/mastodon/actions/alerts.js b/app/javascript/mastodon/actions/alerts.js index 051a9675b3..42834146bf 100644 --- a/app/javascript/mastodon/actions/alerts.js +++ b/app/javascript/mastodon/actions/alerts.js @@ -56,4 +56,4 @@ export const showAlertForError = (error, skipNotFound = false) => { title: messages.unexpectedTitle, message: messages.unexpectedMessage, }); -} +}; diff --git a/app/javascript/mastodon/actions/bookmark_categories.js b/app/javascript/mastodon/actions/bookmark_categories.js index b6f82b49c8..7d458b85ec 100644 --- a/app/javascript/mastodon/actions/bookmark_categories.js +++ b/app/javascript/mastodon/actions/bookmark_categories.js @@ -213,9 +213,10 @@ export const deleteBookmarkCategoryFail = (id, error) => ({ export const fetchBookmarkCategoryStatuses = bookmarkCategoryId => (dispatch, getState) => { dispatch(fetchBookmarkCategoryStatusesRequest(bookmarkCategoryId)); - api(getState).get(`/api/v1/bookmark_categories/${bookmarkCategoryId}/statuses`, { params: { limit: 0 } }).then(({ data }) => { - dispatch(importFetchedStatuses(data)); - dispatch(fetchBookmarkCategoryStatusesSuccess(bookmarkCategoryId, data)); + api(getState).get(`/api/v1/bookmark_categories/${bookmarkCategoryId}/statuses`).then((response) => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(importFetchedStatuses(response.data)); + dispatch(fetchBookmarkCategoryStatusesSuccess(bookmarkCategoryId, response.data, next ? next.uri : null)); }).catch(err => dispatch(fetchBookmarkCategoryStatusesFail(bookmarkCategoryId, err))); }; diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index efe4c56406..608c1f07aa 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -290,7 +290,7 @@ export function submitComposeWithCircleSuccess(status, circleId) { type: COMPOSE_WITH_CIRCLE_SUCCESS, status, circleId, - } + }; } export function submitComposeFail(error) { diff --git a/app/javascript/mastodon/actions/importer/normalizer.js b/app/javascript/mastodon/actions/importer/normalizer.js index a376992b7e..3965c477c0 100644 --- a/app/javascript/mastodon/actions/importer/normalizer.js +++ b/app/javascript/mastodon/actions/importer/normalizer.js @@ -121,7 +121,7 @@ export function normalizeStatus(status, normalOldStatus) { normalStatus.media_attachments.forEach(item => { const oldItem = list.find(i => i.get('id') === item.id); if (oldItem && oldItem.get('description') === item.description) { - item.translation = oldItem.get('translation') + item.translation = oldItem.get('translation'); } }); } @@ -165,13 +165,13 @@ export function normalizePoll(poll, normalOldPoll) { ...option, voted: poll.own_votes && poll.own_votes.includes(index), titleHtml: emojify(escapeTextContentForBrowser(option.title), emojiMap), - } + }; if (normalOldPoll && normalOldPoll.getIn(['options', index, 'title']) === option.title) { normalOption.translation = normalOldPoll.getIn(['options', index, 'translation']); } - return normalOption + return normalOption; }); return normalPoll; diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js index 262d055448..d430ae7acf 100644 --- a/app/javascript/mastodon/actions/streaming.js +++ b/app/javascript/mastodon/actions/streaming.js @@ -192,4 +192,4 @@ export const connectListStream = listId => * @returns {function(): void} */ export const connectAntennaStream = antennaId => -connectTimelineStream(`antenna:${antennaId}`, 'antenna', { antenna: antennaId }, { fillGaps: () => fillAntennaTimelineGaps(antennaId) }); + connectTimelineStream(`antenna:${antennaId}`, 'antenna', { antenna: antennaId }, { fillGaps: () => fillAntennaTimelineGaps(antennaId) }); diff --git a/app/javascript/mastodon/components/column.jsx b/app/javascript/mastodon/components/column.jsx index cf9df3ba27..abc87a57e5 100644 --- a/app/javascript/mastodon/components/column.jsx +++ b/app/javascript/mastodon/components/column.jsx @@ -22,7 +22,7 @@ export default class Column extends PureComponent { scrollable = document.scrollingElement; } else { scrollable = this.node.querySelector('.scrollable'); - } + } if (!scrollable) { return; diff --git a/app/javascript/mastodon/components/compacted_status.jsx b/app/javascript/mastodon/components/compacted_status.jsx index 7ab5ee2025..3ce8a542d3 100644 --- a/app/javascript/mastodon/components/compacted_status.jsx +++ b/app/javascript/mastodon/components/compacted_status.jsx @@ -184,7 +184,7 @@ class CompactedStatus extends ImmutablePureComponent { } else if (attachments.getIn([0, 'type']) === 'audio') { return '16 / 9'; } else { - return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2' + return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2'; } } diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx index 536842481f..cc4ca95fb8 100644 --- a/app/javascript/mastodon/components/media_gallery.jsx +++ b/app/javascript/mastodon/components/media_gallery.jsx @@ -356,10 +356,10 @@ class MediaGallery extends PureComponent { const rowClass = (size === 5 || size === 6 || size === 9 || size === 10 || size === 11 || size === 12) ? 'media-gallery--row3' : (size === 7 || size === 8 || size === 13 || size === 14 || size === 15 || size === 16) ? 'media-gallery--row4' : - 'media-gallery--row2'; + 'media-gallery--row2'; const columnClass = (size === 9) ? 'media-gallery--column3' : (size === 10 || size === 11 || size === 12 || size === 13 || size === 14 || size === 15 || size === 16) ? 'media-gallery--column4' : - 'media-gallery--column2'; + 'media-gallery--column2'; const compactClass = compact ? 'media-gallery__compact' : null; return ( diff --git a/app/javascript/mastodon/components/poll.jsx b/app/javascript/mastodon/components/poll.jsx index 4304f9acd4..2d992d73ae 100644 --- a/app/javascript/mastodon/components/poll.jsx +++ b/app/javascript/mastodon/components/poll.jsx @@ -132,7 +132,7 @@ class Poll extends ImmutablePureComponent { handleReveal = () => { this.setState({ revealed: true }); - } + }; renderOption (option, optionIndex, showResults) { const { poll, lang, disabled, intl } = this.props; diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index 644d44fd4f..65fff3c7c1 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -13,7 +13,7 @@ import AttachmentList from 'mastodon/components/attachment_list'; import { Icon } from 'mastodon/components/icon'; import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder'; -import CompactedStatusContainer from '../containers/compacted_status_container' +import CompactedStatusContainer from '../containers/compacted_status_container'; import Card from '../features/status/components/card'; // We use the component (and not the container) since we do not want // to use the progress bar to show download progress @@ -213,7 +213,7 @@ class Status extends ImmutablePureComponent { } else if (attachments.getIn([0, 'type']) === 'audio') { return '16 / 9'; } else { - return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2' + return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2'; } } @@ -489,12 +489,12 @@ class Status extends ImmutablePureComponent {
%{comment}' - private_comment_template: Tuotu lähteestä %{source}, pvm %{date} - title: Tuo luettelo verkkoalue-estoista - invalid_domain_block: 'Yksi tai useampi verkkotunnuksen lohko ohitettiin seuraavien virheiden vuoksi: %{error}' + private_comment_description_html: 'Seurataksesi tuotujen estojen alkuperää lisätään estojen yhteyteen seuraava yksityinen kommentti:
%{comment}' + private_comment_template: Tuotu lähteestä %{source} %{date} + title: Tuo verkkotunnusten estoja + invalid_domain_block: 'Yksi tai useampi verkkotunnuksen esto ohitettiin seuraavien virheiden vuoksi: %{error}' new: - title: Tuo luettelo verkkoalue-estoista + title: Tuo verkkotunnusten estoja no_file: Yhtäkään tiedostoa ei ole valittu follow_recommendations: description_html: "Seuraamissuositukset auttavat uusia käyttäjiä löytämään nopeasti kiinnostavaa sisältöä. Kun käyttäjä ei ole ollut tarpeeksi vuorovaikutuksessa muiden kanssa, jotta hänelle olisi muodostunut henkilökohtaisia seuraamissuosituksia, suositellaan niiden sijaan näitä tilejä. Ne lasketaan päivittäin uudelleen yhdistelmästä tilejä, jotka ovat viime aikoina olleet aktiivisimmin sitoutuneita ja joilla on suurimmat paikalliset seuraajamäärät tietyllä kielellä." @@ -481,9 +481,9 @@ fi: back_to_limited: Rajoitettu back_to_warning: Varoitus by_domain: Verkkotunnus - confirm_purge: Oletko varma, että haluat pysyvästi poistaa tiedot tältä verkkotunnukselta? + confirm_purge: Haluatko varmasti poistaa pysyvästi tämän verkkotunnuksen tiedot? content_policies: - comment: Sisäinen huomautus + comment: Sisäinen muistiinpano description_html: Voit määrittää sisältökäytännöt, joita sovelletaan kaikkiin tämän verkkotunnuksen ja sen aliverkkotunnuksien tileihin. limited_federation_mode_description_html: Voit valita sallitaanko federointi tällä verkkotunnuksella. policies: @@ -527,7 +527,7 @@ fi: purge: Tyhjennä purge_description_html: Jos uskot, että tämä verkkotunnus on offline-tilassa tarkoituksella, voit poistaa kaikki verkkotunnuksen tilitietueet ja niihin liittyvät tiedot tallennustilastasi. Tämä voi kestää jonkin aikaa. title: Federointi - total_blocked_by_us: Estetty meidän toimesta + total_blocked_by_us: Estämämme total_followed_by_them: Heidän seuraama total_followed_by_us: Meidän seuraama total_reported: Niitä koskevat raportit @@ -554,7 +554,7 @@ fi: '94670856': 3 vuotta new: title: Luo uusi IP-sääntö - no_ip_block_selected: IP-sääntöjä ei muutettu, koska yhtään ei ole valittuna + no_ip_block_selected: IP-sääntöjä ei muutettu, koska yhtään ei ollut valittuna title: IP-säännöt relationships: title: "%{acct}n suhteet" @@ -575,13 +575,13 @@ fi: status: Tila title: Välittäjät report_notes: - created_msg: Muistiinpano onnistuneesti lisätty raporttiin! - destroyed_msg: Muistiinpano onnistuneesti poistettu raportista! + created_msg: Muistiinpano lisätty raporttiin onnistuneesti! + destroyed_msg: Muistiinpano poistettu raportista onnistuneesti! reports: account: notes: - one: "%{count} ilmoitus" - other: "%{count} ilmoitusta" + one: "%{count} muistiinpano" + other: "%{count} muistiinpanoa" action_log: Tarkastusloki action_taken_by: Toimen tehnyt actions: @@ -620,8 +620,8 @@ fi: create_and_unresolve: Avaa uudelleen ja lisää muistiinpano delete: Poista placeholder: Kuvaile mitä toimia on tehty tai muita päivityksiä tähän raporttiin… - title: Merkinnät - notes_description_html: Tarkastele ja jätä merkintöjä muille valvojille ja itsellesi tulevaisuuteen + title: Muistiinpanot + notes_description_html: Tarkastele ja jätä muistiinpanoja muille valvojille ja itsellesi tulevaisuuteen processed_msg: 'Raportti #%{id} käsitelty' quick_actions_description_html: 'Suorita nopea toiminto tai vieritä alas nähdäksesi raportoitu sisältö:' remote_user_placeholder: etäkäyttäjä instanssista %{instance} @@ -707,7 +707,7 @@ fi: manage_settings: Hallitse asetuksia manage_settings_description: Sallii käyttäjien muuttaa sivuston asetuksia manage_taxonomies: Hallitse luokittelua - manage_taxonomies_description: Sallii käyttäjien tarkistaa nousussa olevan sisällön ja päivittää aihetunnisteiden asetuksia + manage_taxonomies_description: Sallii käyttäjien tarkistaa suositun sisällön ja päivittää aihetunnisteiden asetuksia manage_user_access: Hallitse käyttäjäoikeuksia manage_user_access_description: Sallii käyttäjien poistaa muiden käyttäjien kaksivaiheinen todennus käytöstä, vaihtaa heidän sähköpostiosoitteensa ja nollata heidän salasanansa manage_users: Hallitse käyttäjiä @@ -735,10 +735,10 @@ fi: rules_hint: On olemassa erityinen alue sääntöjä, joita käyttäjien odotetaan noudattavan. title: Tietoja appearance: - preamble: Mukauta Mastodonin verkkokäyttöliittymää. + preamble: Mukauta Mastodonin selainkäyttöliittymää. title: Ulkoasu branding: - preamble: Palvelimesi brändäys erottaa sen muista verkon palvelimista. Nämä tiedot voivat näkyä monissa eri ympäristöissä, kuten Mastodonin verkkokäyttöliittymässä, natiivisovelluksissa, linkkien esikatseluissa muilla sivustoilla, viestintäsovelluksissa ja niin edelleen. Siksi nämä tiedot kannattaa pitää selkeinä, lyhyinä ja ytimekkäinä. + preamble: Palvelimesi brändäys erottaa sen muista verkon palvelimista. Nämä tiedot voivat näkyä monissa eri ympäristöissä, kuten Mastodonin selainkäyttöliittymässä, natiivisovelluksissa, linkkien esikatseluissa muilla sivustoilla, viestintäsovelluksissa ja niin edelleen. Siksi nämä tiedot kannattaa pitää selkeinä, lyhyinä ja ytimekkäinä. title: Brändäys captcha_enabled: desc_html: Tämä perustuu ulkoisiin skripteihin hCaptchasta, mikä voi olla turvallisuus- ja yksityisyysongelma. Lisäksi tämä voi tehdä rekisteröinnin ihmisille huomattavasti (erityisesti vammaisten) helpommaksi. Harkitse vaihtoehtoisia toimenpiteitä, kuten hyväksymisperusteista tai kutsupohjaista rekisteröintiä. @@ -807,13 +807,13 @@ fi: media: title: Media metadata: Metadata - no_status_selected: Julkaisuja ei muutettu, koska yhtään ei ole valittuna + no_status_selected: Julkaisuja ei muutettu, koska yhtään ei ollut valittuna open: Avaa julkaisu original_status: Alkuperäinen julkaisu reblogs: Edelleen jako status_changed: Julkaisua muutettu title: Tilin tilat - trending: Nousussa + trending: Suosituttua visibility: Näkyvyys with_media: Sisältää mediaa strikes: @@ -832,7 +832,7 @@ fi: database_schema_check: message_html: Tietokannan siirto on vireillä. Suorita ne varmistaaksesi, että sovellus toimii odotetulla tavalla elasticsearch_health_red: - message_html: Elasticsearch-klusteri on vikatilassa (punainen tila); hakuominaisuudet eivät ole käytettävissä + message_html: Elasticsearch-klusteri on vikatilassa (punainen tila), joten hakuominaisuudet eivät ole käytettävissä elasticsearch_health_yellow: message_html: Elasticsearch-klusteri on häiriötilassa (keltainen tila), joten suosittelemme tutkimaan syyn elasticsearch_index_mismatch: @@ -842,13 +842,13 @@ fi: message_html: Elasticsearch-klusterissa on useampi kuin yksi solmu, mutta Mastodonia ei ole määritetty käyttämään niitä. elasticsearch_preset_single_node: action: Katso käyttöohjeet - message_html: Elasticsearch-klusterissa on vain yksi solmu,
ES_PRESET
tulisi asettaa arvoon single_node_cluster
.
+ message_html: Elasticsearch-klusterissa on vain yksi solmu. ES_PRESET
tulisi asettaa arvoon single_node_cluster
.
elasticsearch_reset_chewy:
message_html: Elasticsearch-järjestelmäindeksi on vanhentunut asetusmuutoksen vuoksi. Suorita tootctl search deploy --reset-chewy
päivittääksesi sen.
elasticsearch_running_check:
- message_html: Ei saatu yhteyttä Elasticsearch. Tarkista, että se on käynnissä tai poista kokotekstihaku käytöstä
+ message_html: Ei saatu yhteyttä Elasticsearchiin. Tarkista, että se on käynnissä tai poista kokotekstihaku käytöstä
elasticsearch_version_check:
- message_html: 'Yhteensopimaton Elasticsearch versio: %{value}'
+ message_html: 'Yhteensopimaton Elasticsearch-versio: %{value}'
version_comparison: Elasticsearch %{running_version} on käynnissä, kun %{required_version} vaaditaan
rules_check:
action: Hallitse palvelimen sääntöjä
@@ -881,9 +881,9 @@ fi:
description_html: Nämä ovat linkkejä, joita jaetaan tällä hetkellä paljon tileillä, joilta palvelimesi näkee viestejä. Se voi auttaa käyttäjiäsi saamaan selville, mitä maailmassa tapahtuu. Linkkejä ei näytetä julkisesti, ennen kuin hyväksyt julkaisijan. Voit myös sallia tai hylätä yksittäiset linkit.
disallow: Hylkää linkki
disallow_provider: Estä julkaisija
- no_link_selected: Yhtään linkkiä ei muutettu, koska yhtään ei valittu
+ no_link_selected: Linkkejä ei muutettu, koska yhtään ei ollut valittuna
publishers:
- no_publisher_selected: Julkaisijoita ei muutettu, koska yhtään ei valittu
+ no_publisher_selected: Julkaisijoita ei muutettu, koska yhtään ei ollut valittuna
shared_by_over_week:
one: Yksi henkilö jakanut viimeisen viikon aikana
other: Jakanut %{count} henkilöä viimeisen viikon aikana
@@ -904,7 +904,7 @@ fi:
description_html: Nämä ovat julkaisuja, joita palvelimesi tietää jaettavan ja lisättävän suosikkeihin paljon tällä hetkellä. Listaus voi auttaa uusia ja palaavia käyttäjiäsi löytämään lisää seurattavia. Julkaisut eivät näy julkisesti ennen kuin hyväksyt niiden julkaisijan ja julkaisija sallii tilinsä ehdottamisen. Voit myös sallia tai hylätä yksittäisiä julkaisuja.
disallow: Kiellä julkaisu
disallow_account: Estä tekijä
- no_status_selected: Suosittuja julkaisuja ei muutettu, koska yhtään ei ole valittuna
+ no_status_selected: Suosittuja julkaisuja ei muutettu, koska yhtään ei ollut valittuna
not_discoverable: Tekijä ei ole ilmoittanut olevansa löydettävissä
shared_by:
one: Jaettu tai lisätty suosikkeihin kerran
@@ -920,21 +920,21 @@ fi:
tag_uses_measure: käyttökerrat
description_html: Nämä ovat aihetunnisteita, jotka näkyvät tällä hetkellä monissa julkaisuissa, jotka palvelimesi näkee. Tämä voi auttaa käyttäjiäsi selvittämään, mistä ihmiset puhuvat eniten tällä hetkellä. Mitään aihetunnisteita ei näytetä julkisesti, ennen kuin hyväksyt ne.
listable: Voidaan ehdottaa
- no_tag_selected: Yhtään tagia ei muutettu, koska yhtään ei valittu
+ no_tag_selected: Tunnisteita ei muutettu, koska yhtään ei ollut valittuna
not_listable: Ei tulla ehdottamaan
not_trendable: Ei näy trendien alla
not_usable: Ei voida käyttää
peaked_on_and_decaying: Saavutti huipun %{date}, nyt hiipuu
title: Suositut aihetunnisteet
trendable: Voi näkyä trendien alla
- trending_rank: 'Nousussa #%{rank}'
+ trending_rank: 'Suosittua #%{rank}'
usable: Voidaan käyttää
usage_comparison: Käytetty %{today} kertaa tänään, verrattuna %{yesterday} eiliseen
used_by_over_week:
one: Yhden henkilön käyttämä viime viikon aikana
other: Käyttänyt %{count} henkilöä viimeisen viikon aikana
title: Trendit
- trending: Nousussa
+ trending: Suosittua
warning_presets:
add_new: Lisää uusi
delete: Poista
@@ -994,8 +994,8 @@ fi:
new_trending_statuses:
title: Suositut julkaisut
new_trending_tags:
- no_approved_tags: Tällä hetkellä ei ole hyväksyttyjä trendikkäitä aihetunnisteita.
- requirements: 'Mikä tahansa näistä ehdokkaista voisi ylittää #%{rank} hyväksytyn trendikkään aihetunnisteen, joka on tällä hetkellä #%{lowest_tag_name} arvosanalla %{lowest_tag_score}.'
+ no_approved_tags: Tällä hetkellä ei ole hyväksyttyjä suosittuja aihetunnisteita.
+ requirements: 'Mikä tahansa näistä ehdokkaista voisi ylittää #%{rank} hyväksytyn suositun aihetunnisteen, joka on tällä hetkellä #%{lowest_tag_name} %{lowest_tag_score} pisteellä.'
title: Suositut aihetunnisteet
subject: Uusia trendejä tarkistettavaksi instanssissa %{instance}
aliases:
@@ -1007,7 +1007,7 @@ fi:
remove: Poista aliaksen linkitys
appearance:
advanced_web_interface: Edistynyt selainkäyttöliittymä
- advanced_web_interface_hint: 'Jos haluat hyödyntää näytön koko leveyttä, edistyneen webkäyttöliittymän avulla voit määrittää useita erilaisia sarakkeita, niin näet kerralla niin paljon tietoa kuin haluat: kotisyöte, ilmoitukset, yleinen aikajana, mikä tahansa määrä listoja ja aihetunnisteita.'
+ advanced_web_interface_hint: 'Jos haluat hyödyntää näytön koko leveyttä, edistyneen selainkäyttöliittymän avulla voit määrittää useita erilaisia sarakkeita, niin näet kerralla niin paljon tietoa kuin haluat: kotisyöte, ilmoitukset, yleinen aikajana, mikä tahansa määrä listoja ja aihetunnisteita.'
animations_and_accessibility: Animaatiot ja saavutettavuus
confirmation_dialogs: Vahvistusvalinnat
discovery: Löytäminen
@@ -1088,7 +1088,7 @@ fi:
new_confirmation_instructions_sent: Saat uuden vahvistuslinkin sisältävän sähköpostiviestin muutamassa minuutissa!
title: Tarkista sähköpostilaatikkosi
sign_in:
- preamble_html: Kirjaudu %{domain}-tunnuksellasi. Jos tilisi sijaitsee eri palvelimella, et voi kirjautua täällä.
+ preamble_html: Kirjaudu %{domain}-tunnuksellasi. Jos tilisi sijaitsee eri palvelimella, et voi kirjautua tässä.
title: Kirjaudu palvelimelle %{domain}
sign_up:
manual_review: Palvelimen %{domain} valvojat tarkistavat rekisteröitymiset käsin. Helpottaaksesi rekisteröitymisesi käsittelyä kerro hieman itsestäsi ja miksi haluat luoda käyttäjätilin palvelimelle %{domain}.
@@ -1219,8 +1219,8 @@ fi:
featured_tags:
add_new: Lisää uusi
errors:
- limit: Olet jo nostanut esille enimmäismäärän aihetunnisteita
- hint_html: "Mitä ovat näkyvillä olevat hashtagit eli aihetunnisteet? Ne ovat näkyvissä julkisessa profiilissasi ja niiden avulla ihmiset voivat selata julkisia viestejäsi nimenomaan näiden aihetunnisteiden alla. Ne auttavat esimerkiksi luovan työn tai pitkäaikaisten projektien seurannassa."
+ limit: Pidät jo esillä aihetunnisteiden enimmäismäärää
+ hint_html: "Pidä tärkeimpiä aihetunnisteitasi esillä profiilissasi. Erinomainen työkalu, jolla pidät kirjaa luovista teoksistasi ja pitkäaikaisista projekteistasi. Esillä pitämäsi aihetunnisteet ovat näyttävällä paikalla profiilissasi ja mahdollistavat nopean pääsyn omiin julkaisuihisi."
filters:
contexts:
account: Profiilit
@@ -1235,7 +1235,7 @@ fi:
statuses_hint_html: Tämä suodatin koskee yksittäisten julkaisujen valintaa riippumatta siitä, vastaavatko ne alla olevia avainsanoja. Tarkista tai poista julkaisut suodattimesta.
title: Muokkaa suodatinta
errors:
- deprecated_api_multiple_keywords: Näitä parametreja ei voi muuttaa tästä sovelluksesta, koska ne koskevat useampaa kuin yhtä suodattimen avainsanaa. Käytä uudempaa sovellusta tai verkkokäyttöliittymää.
+ deprecated_api_multiple_keywords: Näitä parametreja ei voi muuttaa tästä sovelluksesta, koska ne koskevat useampaa kuin yhtä suodattimen avainsanaa. Käytä uudempaa sovellusta tai selainkäyttöliittymää.
invalid_context: Ei sisältöä tai se on virheellinen
index:
contexts: Suodattimet %{contexts}
@@ -1261,7 +1261,7 @@ fi:
batch:
remove: Poista suodattimista
index:
- hint: Tämä suodatin koskee yksittäisten julkaisujen valintaa muista kriteereistä riippumatta. Voit lisätä lisää julkaisuja tähän suodattimeen verkkokäyttöliittymästä.
+ hint: Tämä suodatin koskee yksittäisten julkaisujen valintaa muista kriteereistä riippumatta. Voit lisätä lisää julkaisuja tähän suodattimeen selainkäyttöliittymästä.
title: Suodatetut julkaisut
generic:
all: Kaikki
@@ -1270,7 +1270,7 @@ fi:
other: Kaikki %{count} kohdetta tällä sivulla on valittu.
all_matching_items_selected_html:
one: "%{count} kohde, joka vastaa hakuasi."
- other: Kaikki %{count} kohdetta, jotka vastaavat hakuasi.
+ other: Kaikki %{count} hakuasi vastaavaa kohdetta.
cancel: Peruuta
changes_saved_msg: Muutosten tallennus onnistui!
confirm: Vahvista
@@ -1282,7 +1282,7 @@ fi:
save_changes: Tallenna muutokset
select_all_matching_items:
one: Valitse %{count} kohde, joka vastaa hakuasi.
- other: Valitse kaikki %{count} kohdetta, jotka vastaavat hakuasi.
+ other: Valitse kaikki %{count} hakuasi vastaavaa kohdetta.
today: tänään
validation_errors:
one: Kaikki ei ole aivan oikein! Tarkasta alla oleva virhe
@@ -1290,7 +1290,7 @@ fi:
imports:
errors:
empty: Tyhjä CSV-tiedosto
- incompatible_type: Yhteensopimaton valitun tuontilajin kanssa
+ incompatible_type: Yhteensopimaton valitun tuontityypin kanssa
invalid_csv_file: 'Epäkelpo CSV-tiedosto. Virhe: %{error}'
over_rows_processing_limit: sisältää yli %{count} riviä
too_large: Tiedosto on liian suuri
@@ -1331,8 +1331,8 @@ fi:
bookmarks: Tuodaan kirjanmerkkejä
domain_blocking: Tuodaan estettyjä verkkotunnuksia
following: Tuodaan seurattuja tilejä
- lists: Listojen tuonti
- muting: Tuodaan hiljennettyjä tilejä
+ lists: Tuodaan listoja
+ muting: Tuodaan mykistettyjä tilejä
type: Tuonnin tyyppi
type_groups:
constructive: Seuratut ja kirjanmerkit
@@ -1340,7 +1340,7 @@ fi:
types:
blocking: Estoluettelo
bookmarks: Kirjanmerkit
- domain_blocking: Verkkotunnuksen estoluettelo
+ domain_blocking: Verkkotunnusten estoluettelo
following: Seurattujen luettelo
lists: Listat
muting: Mykistettyjen luettelo
@@ -1402,7 +1402,7 @@ fi:
not_ready: Ei voi liittää tiedostoja, joiden käsittely on kesken. Yritä hetken kuluttua uudelleen!
too_many: Tiedostoja voi liittää enintään 4
migrations:
- acct: uuden tilin käyttäjätunnus@verkkotunnus
+ acct: Muuttanut tunnukselle
cancel: Peruuta uudelleenohjaus
cancel_explanation: Uudelleenohjauksen peruuttaminen aktivoi uudelleen nykyisen tilisi, mutta ei palauta seuraajia, jotka on siirretty kyseiselle tilille.
cancelled_msg: Uudelleenohjaus peruttu onnistuneesti.
@@ -1436,7 +1436,7 @@ fi:
title: Valvonta
move_handler:
carry_blocks_over_text: Tämä käyttäjä siirtyi paikasta %{acct}, jonka olit estänyt.
- carry_mutes_over_text: Tämä käyttäjä siirtyi paikasta %{acct}, jonka mykistit.
+ carry_mutes_over_text: Tämä käyttäjä siirtyi tililtä %{acct}, jonka olet mykistänyt.
copy_account_note_text: 'Tämä käyttäjä siirtyi paikasta %{acct}, tässä olivat aiemmat muistiinpanosi niistä:'
navigation:
toggle_menu: Avaa/sulje valikko
@@ -1525,7 +1525,7 @@ fi:
privacy_hint_html: Määritä, kuinka paljon muita avustavia tietoja haluat paljastaa. Käyttäjät löytävät kiinnostavia profiileja ja hienoja sovelluksia, kun he selaavat toisten seuraamia käyttäjiä ja kun he näkevät, millä sovelluksilla nämä julkaisevat. Saatat kuitenkin haluta piilottaa nämä tiedot.
reach: Tavoittavuus
reach_hint_html: Määritä, haluatko tulla uusien käyttäjien löytämäksi ja seuraamaksi. Haluatko julkaisujesi näkyvän Selaa-sivulla? Haluatko muiden käyttäjien näkevän sinut seuraamissuosituksissaan? Haluatko hyväksyä kaikki uudet seuraajat automaattisesti vai päättää jokaisesta erikseen?
- search: Haku
+ search: Hae
search_hint_html: Määritä, kuinka haluat tulla löydetyksi. Haluatko, että ihmiset löytävät sinut julkisten julkaisujesi perusteella? Haluatko, että ihmiset Mastodonin ulkopuolella löytävät profiilisi tehdessään hakuja verkossa? Otathan huomioon, ettei julkisten tietojen täyttä kaikista hakukoneista poisjäämistä voi taata.
title: Yksityisyys ja tavoittavuus
privacy_policy:
@@ -1625,7 +1625,7 @@ fi:
development: Kehitys
edit_profile: Muokkaa profiilia
export: Vie tietoja
- featured_tags: Esiteltävät aihetunnisteet
+ featured_tags: Esillä pidettävät aihetunnisteet
import: Tuo
import_and_export: Tuonti ja vienti
migrate: Tilin muutto muualle
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 2c24017c36..1b5890e67e 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -1866,11 +1866,11 @@ ja:
private: フォロワー限定
private_long: フォロワーにのみ表示されます
public: 公開
- public_long: 誰でも見ることができ、かつ連合・ローカルタイムラインに表示されます
+ public_long: 誰でも見ることができ、かつ公開タイムラインに表示されます
public_unlisted: ローカル公開
- public_unlisted_long: 誰でも見ることができますが、連合タイムラインには表示されません
- unlisted: 未収載
- unlisted_long: 誰でも見ることができますが、連合・ローカルタイムラインには表示されません
+ public_unlisted_long: 誰でも見ることができますが、他のサーバーの連合タイムラインには表示されません
+ unlisted: 非収載
+ unlisted_long: 誰でも見ることができますが、公開タイムラインには表示されません
unset: 設定なし
unset_long: デフォルトの挙動に従います
statuses_cleanup:
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index b6cbb46cb4..3a7d0c7f7a 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -878,9 +878,9 @@ ko:
only_allowed: 허용된 것만
pending_review: 심사 대기
preview_card_providers:
- allowed: 이 발행처의 링크는 유행록에 실릴 수 있음
+ allowed: 이 발행처의 링크는 유행 목록에 실릴 수 있음
description_html: 당신의 서버에서 많은 링크가 공유되고 있는 도메인들입니다. 링크의 도메인이 승인되기 전까지는 링크들은 공개적으로 트렌드에 게시되지 않습니다. 당신의 승인(또는 거절)은 서브도메인까지 확장됩니다.
- rejected: 이 발행처의 링크는 유행록에 실리지 않음
+ rejected: 이 발행처의 링크는 유행 목록에 실리지 않음
title: 발행처
rejected: 거부됨
statuses:
@@ -903,15 +903,15 @@ ko:
tag_servers_measure: 다른 서버들
tag_uses_measure: 총 사용
description_html: 현재 서버에서 볼 수 있는 게시물에서 많이 공유되고 있는 해시태그들입니다. 현재 사람들이 무슨 이야기를 하고 있는지 사용자들이 파악할 수 있도록 도움이 됩니다. 승인하지 않는 한 해시태그는 공개적으로 게시되지 않습니다.
- listable: 추천될 수 있습니다
+ listable: 추천될 수 있음
no_tag_selected: 아무 것도 선택 되지 않아 어떤 태그도 바뀌지 않았습니다
- not_listable: 추천될 수 없습니다
- not_trendable: 유행 목록에 나타나지 않습니다
- not_usable: 사용불가
- peaked_on_and_decaying: '%{date}에 고점을 찍고, 떨어지고 있습니다'
+ not_listable: 추천하지 않음
+ not_trendable: 유행 목록에 나타내지 않음
+ not_usable: 이용할 수 없음
+ peaked_on_and_decaying: "%{date}에 고점을 찍고, 떨어지고 있습니다"
title: 유행하는 해시태그
- trendable: 유행 목록에 나타날 수 있습니다
- trending_rank: '#%{rank}위로 유행 중'
+ trendable: 유행 목록에 나타날 수 있음
+ trending_rank: "#%{rank}위로 유행 중"
usable: 사용 가능
usage_comparison: 오늘은 %{today}회 쓰였고, 어제는 %{yesterday}회 쓰임
used_by_over_week:
diff --git a/config/locales/si.yml b/config/locales/si.yml
index e9393e5c9a..7dd900f509 100644
--- a/config/locales/si.yml
+++ b/config/locales/si.yml
@@ -298,7 +298,7 @@ si:
updated_msg: ඉමොජි සාර්ථකව යාවත්කාලීන කරන ලදී!
upload: උඩුගත කරන්න
dashboard:
- active_users: ක්රියාකාරී පරිශීලකයන්
+ active_users: සක්රිය පරිශ්රීලකයින්
interactions: අන්තර්ක්රියා
media_storage: මාධ්ය ආචයනය
new_users: නව පරිශ්රීලකයින්
diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml
index e69527c64e..f31c22282d 100644
--- a/config/locales/simple_form.fi.yml
+++ b/config/locales/simple_form.fi.yml
@@ -42,7 +42,7 @@ fi:
bot: Tämä tili suorittaa enimmäkseen automaattisia toimintoja eikä sitä ehkä valvota
context: Ainakin yksi konteksti, jossa suodattimen pitäisi olla voimassa
current_password: Turvallisuussyistä kirjoita nykyisen tilin salasana
- current_username: Vahvista kirjoittamalla nykyisen tilin käyttäjätunnus
+ current_username: Vahvista kirjoittamalla nykyisen tilin käyttäjänimi
digest: Lähetetään vain pitkän poissaolon jälkeen ja vain, jos olet saanut suoria viestejä poissaolosi aikana
email: Sinulle lähetetään vahvistussähköposti
header: PNG, GIF tai JPG. Enintään %{size}. Skaalataan kokoon %{dimensions} px
@@ -77,11 +77,11 @@ fi:
form_admin_settings:
activity_api_enabled: Paikallisesti julkaistujen julkaisujen, aktiivisten käyttäjien ja rekisteröitymisten viikoittainen määrä
backups_retention_period: Säilytä luodut arkistot määritetyn määrän päiviä.
- bootstrap_timeline_accounts: Nämä tilit kiinnitetään uusien käyttäjien suositusten yläpuolelle.
+ bootstrap_timeline_accounts: Nämä tilit kiinnitetään uusien käyttäjien seuraamissuositusten yläpuolelle.
closed_registrations_message: Näkyy, kun ilmoittautuminen on suljettu
content_cache_retention_period: Viestit muilta palvelimilta poistetaan määritetyn määrän päiviä jälkeen, kun arvo on asetettu positiiviseksi. Tämä voi olla peruuttamatonta.
custom_css: Voit käyttää mukautettuja tyylejä Mastodonin verkkoversiossa.
- mascot: Ohittaa kuvituksen edistyneessä käyttöliittymässä.
+ mascot: Ohittaa kuvituksen edistyneessä selainkäyttöliittymässä.
media_cache_retention_period: Ladatut mediatiedostot poistetaan määritetyn määrän päiviä jälkeen, kun arvo on positiivinen ja ladataan uudelleen pyynnöstä.
peers_api_enabled: Luettelo verkkotunnuksista, jotka tämä palvelin on kohdannut fediversumissa. Se ei kerro, oletko liitossa tietyn palvelimen kanssa, vaan että palvelimesi on ylipäätään tietoinen siitä. Tätä tietoa käytetään palveluissa, jotka keräävät tilastoja liittoutumisesta yleisellä tasolla.
profile_directory: Profiilihakemisto lueteloi kaikki käyttäjät, jotka ovat ilmoittaneet olevansa löydettävissä.
@@ -108,7 +108,7 @@ fi:
ip_block:
comment: Valinnainen. Muista miksi lisäsit tämän säännön.
expires_in: IP-osoitteet ovat rajallinen resurssi, joskus niitä jaetaan ja vaihtavat usein omistajaa. Tästä syystä epämääräisiä IP-lohkoja ei suositella.
- ip: Kirjoita IPv4- tai IPv6-osoite. Voit estää kokonaisia alueita käyttämällä CIDR-syntaksia. Varo, että et lukitse itseäsi!
+ ip: Kirjoita IPv4- tai IPv6-osoite. Voit estää kokonaisia alueita käyttämällä CIDR-syntaksia. Varo, että et lukitse itseäsi ulos!
severities:
no_access: Estä pääsy kaikkiin resursseihin
sign_up_block: Uudet kirjautumiset eivät ole mahdollisia
@@ -139,7 +139,7 @@ fi:
url: Mihin tapahtumat lähetetään
labels:
account:
- discoverable: Nosta profiili ja julkaisut esille löytämisalgoritmeissa
+ discoverable: Pidä profiiliasi ja julkaisujasi esillä löytämisalgoritmeissa
fields:
name: Nimike
value: Sisältö
@@ -147,9 +147,9 @@ fi:
show_collections: Näytä seuratut ja seuraajat profiilissa
unlocked: Hyväksy uudet seuraajat automaattisesti
account_alias:
- acct: Vanhan tilin käyttäjätunnus
+ acct: Vanhan tilin käyttäjänimi
account_migration:
- acct: Uuden tilin käyttäjätunnus
+ acct: Uuden tilin käyttäjänimi
account_warning_preset:
text: Esiasetettu teksti
title: Nimi
@@ -162,8 +162,8 @@ fi:
disable: Poista kirjautuminen käytöstä
none: Älä tee mitään
sensitive: Arkaluonteinen
- silence: Hiljennä
- suspend: Poista käytöstä ja tuhoa käyttäjätunnuksen tiedot peruuttamattomasti
+ silence: Rajoita
+ suspend: Jäädytä
warning_preset_id: Käytä varoitusmallia
announcement:
all_day: Koko päivän kestävä tapahtuma
@@ -224,9 +224,9 @@ fi:
severity: Vakavuus
sign_in_token_attempt: Turvakoodi
title: Nimi
- type: Tuontilaji
+ type: Tuontityyppi
username: Käyttäjänimi
- username_or_email: Käyttäjänimi tai sähköposti
+ username_or_email: Käyttäjänimi tai sähköpostiosoite
whole_word: Koko sana
email_domain_block:
with_dns_records: Sisällytä toimialueen MX tietueet ja IP-osoite
@@ -249,10 +249,10 @@ fi:
profile_directory: Ota profiilihakemisto käyttöön
registrations_mode: Kuka voi rekisteröityä
require_invite_text: Vaadi syy liittyä
- show_domain_blocks: Näytä domainestot
+ show_domain_blocks: Näytä verkkotunnusten estot
show_domain_blocks_rationale: Näytä miksi verkkotunnukset on estetty
site_contact_email: Ota yhteyttä sähköpostilla
- site_contact_username: Kontaktin käyttäjänimi
+ site_contact_username: Yhteyshenkilön käyttäjänimi
site_extended_description: Laajennettu kuvaus
site_short_description: Palvelimen kuvaus
site_terms: Tietosuojakäytäntö
@@ -277,7 +277,7 @@ fi:
ip: IP-osoite
severities:
no_access: Estä pääsy
- sign_up_block: Estä kirjautumiset
+ sign_up_block: Estä rekisteröitymiset
sign_up_requires_approval: Rajoita rekisteröitymisiä
severity: Sääntö
notification_emails:
diff --git a/spec/config/initializers/rack_attack_spec.rb b/spec/config/initializers/rack_attack_spec.rb
index 7cd4ac76bb..c9ce9e27d0 100644
--- a/spec/config/initializers/rack_attack_spec.rb
+++ b/spec/config/initializers/rack_attack_spec.rb
@@ -16,37 +16,63 @@ describe Rack::Attack, type: :request do
# https://github.com/rack/rack-attack/blob/v6.6.1/lib/rack/attack/cache.rb#L64-L66
# So we want to minimize `Time.now.to_i % period`
- travel_to Time.zone.at((Time.now.to_i / period.seconds).to_i * period.seconds)
+ travel_to Time.zone.at(counter_prefix * period.seconds)
end
context 'when the number of requests is lower than the limit' do
+ before do
+ below_limit.times { increment_counter }
+ end
+
it 'does not change the request status' do
- limit.times do
- request.call
- expect(response).to_not have_http_status(429)
- end
+ expect { request.call }.to change { throttle_count }.by(1)
+
+ expect(response).to_not have_http_status(429)
end
end
context 'when the number of requests is higher than the limit' do
+ before do
+ above_limit.times { increment_counter }
+ end
+
it 'returns http too many requests after limit and returns to normal status after period' do
- (limit * 2).times do |i|
- request.call
- expect(response).to have_http_status(429) if i > limit
- end
+ expect { request.call }.to change { throttle_count }.by(1)
+ expect(response).to have_http_status(429)
travel period
- request.call
+ expect { request.call }.to change { throttle_count }.by(1)
expect(response).to_not have_http_status(429)
end
end
+
+ def below_limit
+ limit - 1
+ end
+
+ def above_limit
+ limit * 2
+ end
+
+ def throttle_count
+ described_class.cache.read("#{counter_prefix}:#{throttle}:#{remote_ip}") || 0
+ end
+
+ def counter_prefix
+ (Time.now.to_i / period.seconds).to_i
+ end
+
+ def increment_counter
+ described_class.cache.count("#{throttle}:#{remote_ip}", period)
+ end
end
let(:remote_ip) { '1.2.3.5' }
describe 'throttle excessive sign-up requests by IP address' do
context 'when accessed through the website' do
+ let(:throttle) { 'throttle_sign_up_attempts/ip' }
let(:limit) { 25 }
let(:period) { 5.minutes }
let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } }
@@ -65,6 +91,7 @@ describe Rack::Attack, type: :request do
end
context 'when accessed through the API' do
+ let(:throttle) { 'throttle_api_sign_up' }
let(:limit) { 5 }
let(:period) { 30.minutes }
let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } }
@@ -87,6 +114,7 @@ describe Rack::Attack, type: :request do
end
describe 'throttle excessive sign-in requests by IP address' do
+ let(:throttle) { 'throttle_login_attempts/ip' }
let(:limit) { 25 }
let(:period) { 5.minutes }
let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } }
diff --git a/spec/controllers/api/oembed_controller_spec.rb b/spec/controllers/api/oembed_controller_spec.rb
index 70248c3982..5f0ca560d2 100644
--- a/spec/controllers/api/oembed_controller_spec.rb
+++ b/spec/controllers/api/oembed_controller_spec.rb
@@ -14,11 +14,8 @@ RSpec.describe Api::OEmbedController do
get :show, params: { url: short_account_status_url(alice, status) }, format: :json
end
- it 'returns http success' do
+ it 'returns private cache control headers', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'returns private cache control headers' do
expect(response.headers['Cache-Control']).to include('private, no-store')
end
end
diff --git a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb
index b5d5c37a9c..a62fa54e60 100644
--- a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb
@@ -41,11 +41,9 @@ describe Api::V1::Accounts::CredentialsController do
}
end
- it 'returns http success' do
+ it 'updates account info', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'updates account info' do
user.reload
user.account.reload
@@ -55,9 +53,7 @@ describe Api::V1::Accounts::CredentialsController do
expect(user.account.header).to exist
expect(user.setting_default_privacy).to eq('unlisted')
expect(user.setting_default_sensitive).to be(true)
- end
- it 'queues up an account update distribution' do
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(user.account_id)
end
end
diff --git a/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb b/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb
index 7a387f326f..510a47566b 100644
--- a/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb
@@ -18,23 +18,19 @@ describe Api::V1::Accounts::FollowerAccountsController do
end
describe 'GET #index' do
- it 'returns http success' do
+ it 'returns accounts following the given account', :aggregate_failures do
get :index, params: { account_id: account.id, limit: 2 }
expect(response).to have_http_status(200)
- end
-
- it 'returns accounts following the given account' do
- get :index, params: { account_id: account.id, limit: 2 }
-
expect(body_as_json.size).to eq 2
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
end
- it 'does not return blocked users' do
+ it 'does not return blocked users', :aggregate_failures do
user.account.block!(bob)
get :index, params: { account_id: account.id, limit: 2 }
+ expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1
expect(body_as_json[0][:id]).to eq alice.id.to_s
end
diff --git a/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb b/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb
index b69b0bd395..a7d07a6bec 100644
--- a/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb
@@ -18,23 +18,19 @@ describe Api::V1::Accounts::FollowingAccountsController do
end
describe 'GET #index' do
- it 'returns http success' do
+ it 'returns accounts followed by the given account', :aggregate_failures do
get :index, params: { account_id: account.id, limit: 2 }
expect(response).to have_http_status(200)
- end
-
- it 'returns accounts followed by the given account' do
- get :index, params: { account_id: account.id, limit: 2 }
-
expect(body_as_json.size).to eq 2
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
end
- it 'does not return blocked users' do
+ it 'does not return blocked users', :aggregate_failures do
user.account.block!(bob)
get :index, params: { account_id: account.id, limit: 2 }
+ expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1
expect(body_as_json[0][:id]).to eq alice.id.to_s
end
diff --git a/spec/controllers/api/v1/accounts/notes_controller_spec.rb b/spec/controllers/api/v1/accounts/notes_controller_spec.rb
index 4107105afd..75599b32b2 100644
--- a/spec/controllers/api/v1/accounts/notes_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/notes_controller_spec.rb
@@ -19,30 +19,24 @@ describe Api::V1::Accounts::NotesController do
post :create, params: { account_id: account.id, comment: comment }
end
- context 'when account note has reasonable length' do
+ context 'when account note has reasonable length', :aggregate_failures do
let(:comment) { 'foo' }
- it 'returns http success' do
- subject
- expect(response).to have_http_status(200)
- end
-
it 'updates account note' do
subject
+
+ expect(response).to have_http_status(200)
expect(AccountNote.find_by(account_id: user.account.id, target_account_id: account.id).comment).to eq comment
end
end
- context 'when account note exceeds allowed length' do
+ context 'when account note exceeds allowed length', :aggregate_failures do
let(:comment) { 'a' * 2_001 }
- it 'returns 422' do
- subject
- expect(response).to have_http_status(422)
- end
-
it 'does not create account note' do
subject
+
+ expect(response).to have_http_status(422)
expect(AccountNote.where(account_id: user.account.id, target_account_id: account.id)).to_not exist
end
end
diff --git a/spec/controllers/api/v1/accounts/pins_controller_spec.rb b/spec/controllers/api/v1/accounts/pins_controller_spec.rb
index b4aa9b7116..36f525e756 100644
--- a/spec/controllers/api/v1/accounts/pins_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/pins_controller_spec.rb
@@ -15,14 +15,11 @@ RSpec.describe Api::V1::Accounts::PinsController do
describe 'POST #create' do
subject { post :create, params: { account_id: kevin.account.id } }
- it 'returns 200' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates account_pin' do
+ 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
@@ -33,14 +30,11 @@ RSpec.describe Api::V1::Accounts::PinsController do
Fabricate(:account_pin, account: john.account, target_account: kevin.account)
end
- it 'returns 200' do
- expect(response).to have_http_status(200)
- end
-
- it 'destroys account_pin' do
+ 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/relationships_controller_spec.rb b/spec/controllers/api/v1/accounts/relationships_controller_spec.rb
index 993ead636a..5ba6f2a1f8 100644
--- a/spec/controllers/api/v1/accounts/relationships_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/relationships_controller_spec.rb
@@ -26,13 +26,10 @@ describe Api::V1::Accounts::RelationshipsController do
get :index, params: { id: simon.id }
end
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns JSON with correct data' do
+ it 'returns JSON with correct data', :aggregate_failures do
json = body_as_json
+ expect(response).to have_http_status(200)
expect(json).to be_a Enumerable
expect(json.first[:following]).to be true
expect(json.first[:followed_by]).to be false
@@ -51,11 +48,14 @@ describe Api::V1::Accounts::RelationshipsController do
context 'when there is returned JSON data' do
let(:json) { body_as_json }
- it 'returns an enumerable json' do
+ it 'returns an enumerable json with correct elements', :aggregate_failures do
expect(json).to be_a Enumerable
+
+ expect_simon_item_one
+ expect_lewis_item_two
end
- it 'returns a correct first element' do
+ def expect_simon_item_one
expect(json.first[:id]).to eq simon.id.to_s
expect(json.first[:following]).to be true
expect(json.first[:showing_reblogs]).to be true
@@ -65,7 +65,7 @@ describe Api::V1::Accounts::RelationshipsController do
expect(json.first[:domain_blocking]).to be false
end
- it 'returns a correct second element' do
+ def expect_lewis_item_two
expect(json.second[:id]).to eq lewis.id.to_s
expect(json.second[:following]).to be false
expect(json.second[:showing_reblogs]).to be false
diff --git a/spec/controllers/api/v1/accounts/statuses_controller_spec.rb b/spec/controllers/api/v1/accounts/statuses_controller_spec.rb
index cb62afcf93..0e4fa93017 100644
--- a/spec/controllers/api/v1/accounts/statuses_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/statuses_controller_spec.rb
@@ -14,15 +14,10 @@ describe Api::V1::Accounts::StatusesController do
end
describe 'GET #index' do
- it 'returns http success' do
+ it 'returns expected headers', :aggregate_failures do
get :index, params: { account_id: user.account.id, limit: 1 }
expect(response).to have_http_status(200)
- end
-
- it 'returns expected headers' do
- get :index, params: { account_id: user.account.id, limit: 1 }
-
expect(response.headers['Link'].links.size).to eq(2)
end
@@ -44,14 +39,11 @@ describe Api::V1::Accounts::StatusesController do
get :index, params: { account_id: user.account.id, exclude_replies: true }
end
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns posts along with self replies' do
+ it 'returns posts along with self replies', :aggregate_failures do
json = body_as_json
post_ids = json.map { |item| item[:id].to_i }.sort
+ expect(response).to have_http_status(200)
expect(post_ids).to eq [status.id, status_self_reply.id]
end
end
diff --git a/spec/controllers/api/v1/accounts_controller_spec.rb b/spec/controllers/api/v1/accounts_controller_spec.rb
index 985e2b947b..0d9b4c8cc2 100644
--- a/spec/controllers/api/v1/accounts_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts_controller_spec.rb
@@ -25,15 +25,10 @@ RSpec.describe Api::V1::AccountsController do
context 'when given truthy agreement' do
let(:agreement) { 'true' }
- it 'returns http success' do
+ it 'creates a user', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'returns a new access token as JSON' do
expect(body_as_json[:access_token]).to_not be_blank
- end
- it 'creates a user' do
user = User.find_by(email: 'hello@world.tld')
expect(user).to_not be_nil
expect(user.created_by_application_id).to eq app.id
@@ -65,18 +60,14 @@ RSpec.describe Api::V1::AccountsController do
context 'with unlocked account' do
let(:locked) { false }
- it 'returns http success' do
+ it 'creates a following relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'returns JSON with following=true and requested=false' do
json = body_as_json
expect(json[:following]).to be true
expect(json[:requested]).to be false
- end
- it 'creates a following relation between user and target user' do
expect(user.account.following?(other_account)).to be true
end
@@ -86,18 +77,14 @@ RSpec.describe Api::V1::AccountsController do
context 'with locked account' do
let(:locked) { true }
- it 'returns http success' do
+ it 'creates a follow request relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'returns JSON with following=false and requested=true' do
json = body_as_json
expect(json[:following]).to be false
expect(json[:requested]).to be true
- end
- it 'creates a follow request relation between user and target user' do
expect(user.account.requested?(other_account)).to be true
end
@@ -177,11 +164,8 @@ RSpec.describe Api::V1::AccountsController do
post :unfollow, params: { id: other_account.id }
end
- it 'returns http success' do
+ it 'removes the following relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'removes the following relation between user and target user' do
expect(user.account.following?(other_account)).to be false
end
@@ -197,11 +181,8 @@ RSpec.describe Api::V1::AccountsController do
post :remove_from_followers, params: { id: other_account.id }
end
- it 'returns http success' do
+ it 'removes the followed relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'removes the followed relation between user and target user' do
expect(user.account.followed_by?(other_account)).to be false
end
@@ -217,15 +198,9 @@ RSpec.describe Api::V1::AccountsController do
post :block, params: { id: other_account.id }
end
- it 'returns http success' do
+ it 'creates a blocking relation', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'removes the following relation between user and target user' do
expect(user.account.following?(other_account)).to be false
- end
-
- it 'creates a blocking relation' do
expect(user.account.blocking?(other_account)).to be true
end
@@ -241,11 +216,8 @@ RSpec.describe Api::V1::AccountsController do
post :unblock, params: { id: other_account.id }
end
- it 'returns http success' do
+ it 'removes the blocking relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'removes the blocking relation between user and target user' do
expect(user.account.blocking?(other_account)).to be false
end
@@ -261,19 +233,10 @@ RSpec.describe Api::V1::AccountsController do
post :mute, params: { id: other_account.id }
end
- it 'returns http success' do
+ it 'mutes notifications', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'does not remove the following relation between user and target user' do
expect(user.account.following?(other_account)).to be true
- end
-
- it 'creates a muting relation' do
expect(user.account.muting?(other_account)).to be true
- end
-
- it 'mutes notifications' do
expect(user.account.muting_notifications?(other_account)).to be true
end
@@ -289,19 +252,10 @@ RSpec.describe Api::V1::AccountsController do
post :mute, params: { id: other_account.id, notifications: false }
end
- it 'returns http success' do
+ it 'does not mute notifications', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'does not remove the following relation between user and target user' do
expect(user.account.following?(other_account)).to be true
- end
-
- it 'creates a muting relation' do
expect(user.account.muting?(other_account)).to be true
- end
-
- it 'does not mute notifications' do
expect(user.account.muting_notifications?(other_account)).to be false
end
@@ -317,19 +271,10 @@ RSpec.describe Api::V1::AccountsController do
post :mute, params: { id: other_account.id, duration: 300 }
end
- it 'returns http success' do
+ it 'mutes notifications', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'does not remove the following relation between user and target user' do
expect(user.account.following?(other_account)).to be true
- end
-
- it 'creates a muting relation' do
expect(user.account.muting?(other_account)).to be true
- end
-
- it 'mutes notifications' do
expect(user.account.muting_notifications?(other_account)).to be true
end
@@ -345,11 +290,8 @@ RSpec.describe Api::V1::AccountsController do
post :unmute, params: { id: other_account.id }
end
- it 'returns http success' do
+ it 'removes the muting relation between user and target user', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'removes the muting relation between user and target user' do
expect(user.account.muting?(other_account)).to be false
end
diff --git a/spec/controllers/api/v1/admin/accounts_controller_spec.rb b/spec/controllers/api/v1/admin/accounts_controller_spec.rb
index 36f6e398cb..4b56b25479 100644
--- a/spec/controllers/api/v1/admin/accounts_controller_spec.rb
+++ b/spec/controllers/api/v1/admin/accounts_controller_spec.rb
@@ -44,11 +44,9 @@ RSpec.describe Api::V1::Admin::AccountsController do
context "when called with #{params.inspect}" do
let(:params) { params }
- it 'returns http success' do
+ it "returns the correct accounts (#{expected_results.inspect})", :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it "returns the correct accounts (#{expected_results.inspect})" do
json = body_as_json
expect(json.map { |a| a[:id].to_i }).to eq(expected_results.map { |symbol| send(symbol).id })
@@ -79,15 +77,10 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
+ it 'approves user', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'approves user' do
expect(account.reload.user_approved?).to be true
- end
- it 'logs action' do
log_item = Admin::ActionLog.last
expect(log_item).to_not be_nil
@@ -106,15 +99,10 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
+ it 'removes user', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'removes user' do
expect(User.where(id: account.user.id).count).to eq 0
- end
- it 'logs action' do
log_item = Admin::ActionLog.last
expect(log_item).to_not be_nil
@@ -133,11 +121,8 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
+ it 'enables user', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'enables user' do
expect(account.reload.user_disabled?).to be false
end
end
@@ -151,11 +136,8 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
+ it 'unsuspends account', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'unsuspends account' do
expect(account.reload.suspended?).to be false
end
end
@@ -169,11 +151,8 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
+ it 'unsensitizes account', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'unsensitizes account' do
expect(account.reload.sensitized?).to be false
end
end
@@ -187,11 +166,8 @@ RSpec.describe Api::V1::Admin::AccountsController do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
+ it 'unsilences account', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'unsilences account' do
expect(account.reload.silenced?).to be false
end
end
diff --git a/spec/controllers/api/v1/admin/trends/links_controller_spec.rb b/spec/controllers/api/v1/admin/trends/links_controller_spec.rb
deleted file mode 100644
index d9aa06824d..0000000000
--- a/spec/controllers/api/v1/admin/trends/links_controller_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Admin::Trends::LinksController do
- render_views
-
- let(:role) { UserRole.find_by(name: 'Admin') }
- let(:user) { Fabricate(:user, role: role) }
- let(:scopes) { 'admin:read admin:write' }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
- let(:account) { Fabricate(:account) }
- let(:preview_card) { Fabricate(:preview_card) }
-
- 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
-
- describe 'POST #approve' do
- before do
- post :approve, params: { id: preview_card.id }
- end
-
- it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', ''
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #reject' do
- before do
- post :reject, params: { id: preview_card.id }
- end
-
- it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', ''
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/announcements/reactions_controller_spec.rb b/spec/controllers/api/v1/announcements/reactions_controller_spec.rb
index 10aaa553f5..c1debc33fe 100644
--- a/spec/controllers/api/v1/announcements/reactions_controller_spec.rb
+++ b/spec/controllers/api/v1/announcements/reactions_controller_spec.rb
@@ -25,11 +25,8 @@ RSpec.describe Api::V1::Announcements::ReactionsController do
put :update, params: { announcement_id: announcement.id, id: '😂' }
end
- it 'returns http success' do
+ it 'creates reaction', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'creates reaction' do
expect(announcement.announcement_reactions.find_by(name: '😂', account: user.account)).to_not be_nil
end
end
@@ -53,11 +50,8 @@ RSpec.describe Api::V1::Announcements::ReactionsController do
delete :destroy, params: { announcement_id: announcement.id, id: '😂' }
end
- it 'returns http success' do
+ it 'creates reaction', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'creates reaction' do
expect(announcement.announcement_reactions.find_by(name: '😂', account: user.account)).to be_nil
end
end
diff --git a/spec/controllers/api/v1/announcements_controller_spec.rb b/spec/controllers/api/v1/announcements_controller_spec.rb
index 15d94b4512..95ce8fd9fc 100644
--- a/spec/controllers/api/v1/announcements_controller_spec.rb
+++ b/spec/controllers/api/v1/announcements_controller_spec.rb
@@ -47,11 +47,8 @@ RSpec.describe Api::V1::AnnouncementsController do
post :dismiss, params: { id: announcement.id }
end
- it 'returns http success' do
+ it 'dismisses announcement', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'dismisses announcement' do
expect(announcement.announcement_mutes.find_by(account: user.account)).to_not be_nil
end
end
diff --git a/spec/controllers/api/v1/blocks_controller_spec.rb b/spec/controllers/api/v1/blocks_controller_spec.rb
index eaafc1b4fa..ba63560a96 100644
--- a/spec/controllers/api/v1/blocks_controller_spec.rb
+++ b/spec/controllers/api/v1/blocks_controller_spec.rb
@@ -12,45 +12,48 @@ RSpec.describe Api::V1::BlocksController do
before { allow(controller).to receive(:doorkeeper_token) { token } }
describe 'GET #index' do
- it 'limits according to limit parameter' do
+ it 'limits according to limit parameter', :aggregate_failures do
Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { limit: 1 }
+
+ expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1
end
- it 'queries blocks in range according to max_id' do
+ it 'queries blocks in range according to max_id', :aggregate_failures do
blocks = Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { max_id: blocks[1] }
+ expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1
expect(body_as_json[0][:id]).to eq blocks[0].target_account_id.to_s
end
- it 'queries blocks in range according to since_id' do
+ it 'queries blocks in range according to since_id', :aggregate_failures do
blocks = Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { since_id: blocks[0] }
+ expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1
expect(body_as_json[0][:id]).to eq blocks[1].target_account_id.to_s
end
- it 'sets pagination header for next path' do
+ it 'sets pagination header for next path', :aggregate_failures do
blocks = Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { limit: 1, since_id: blocks[0] }
+
+ expect(response).to have_http_status(200)
expect(response.headers['Link'].find_link(%w(rel next)).href).to eq api_v1_blocks_url(limit: 1, max_id: blocks[1])
end
- it 'sets pagination header for previous path' do
+ it 'sets pagination header for previous path', :aggregate_failures do
block = Fabricate(:block, account: user.account)
get :index
- expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq api_v1_blocks_url(since_id: block)
- end
- it 'returns http success' do
- get :index
expect(response).to have_http_status(200)
+ expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq api_v1_blocks_url(since_id: block)
end
context 'with wrong scopes' do
diff --git a/spec/controllers/api/v1/conversations_controller_spec.rb b/spec/controllers/api/v1/conversations_controller_spec.rb
index 28d7c7f3ae..50e2a62efd 100644
--- a/spec/controllers/api/v1/conversations_controller_spec.rb
+++ b/spec/controllers/api/v1/conversations_controller_spec.rb
@@ -21,17 +21,14 @@ RSpec.describe Api::V1::ConversationsController do
PostStatusService.new.call(user.account, text: 'Hey, nobody here', visibility: 'direct')
end
- it 'returns http success' do
- get :index
- expect(response).to have_http_status(200)
- end
-
- it 'returns pagination headers' do
+ it 'returns pagination headers', :aggregate_failures do
get :index, params: { limit: 1 }
+
+ expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
end
- it 'returns conversations' do
+ it 'returns conversations', :aggregate_failures do
get :index
json = body_as_json
expect(json.size).to eq 2
diff --git a/spec/controllers/api/v1/favourites_controller_spec.rb b/spec/controllers/api/v1/favourites_controller_spec.rb
deleted file mode 100644
index c9ca046be0..0000000000
--- a/spec/controllers/api/v1/favourites_controller_spec.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::FavouritesController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') }
-
- describe 'GET #index' do
- context 'without token' do
- it 'returns http unauthorized' do
- get :index
- expect(response).to have_http_status 401
- end
- end
-
- context 'with token' do
- context 'without read scope' do
- before do
- allow(controller).to receive(:doorkeeper_token) do
- Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: '')
- end
- end
-
- it 'returns http forbidden' do
- get :index
- expect(response).to have_http_status 403
- end
- end
-
- context 'without valid resource owner' do
- before do
- token = Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read')
- user.destroy!
-
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- it 'returns http unprocessable entity' do
- get :index
- expect(response).to have_http_status 422
- end
- end
-
- context 'with read scope and valid resource owner' do
- before do
- allow(controller).to receive(:doorkeeper_token) do
- Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:favourites')
- end
- end
-
- it 'shows favourites owned by the user' do
- favourite_by_user = Fabricate(:favourite, account: user.account)
- favourite_by_others = Fabricate(:favourite)
-
- get :index
-
- expect(assigns(:statuses)).to contain_exactly(favourite_by_user.status)
- end
-
- it 'adds pagination headers if necessary' do
- favourite = Fabricate(:favourite, account: user.account)
-
- get :index, params: { limit: 1 }
-
- expect(response.headers['Link'].find_link(%w(rel next)).href).to eq "http://test.host/api/v1/favourites?limit=1&max_id=#{favourite.id}"
- expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq "http://test.host/api/v1/favourites?limit=1&min_id=#{favourite.id}"
- end
-
- it 'does not add pagination headers if not necessary' do
- get :index
-
- expect(response.headers['Link']).to be_nil
- end
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/filters_controller_spec.rb b/spec/controllers/api/v1/filters_controller_spec.rb
index 8ccd2f4d66..8d5408cf54 100644
--- a/spec/controllers/api/v1/filters_controller_spec.rb
+++ b/spec/controllers/api/v1/filters_controller_spec.rb
@@ -31,12 +31,10 @@ RSpec.describe Api::V1::FiltersController do
post :create, params: { phrase: 'magic', context: %w(home), irreversible: irreversible, whole_word: whole_word }
end
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates a filter' do
+ it 'creates a filter', :aggregate_failures do
filter = user.account.custom_filters.first
+
+ expect(response).to have_http_status(200)
expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]]
expect(filter.context).to eq %w(home)
@@ -48,12 +46,10 @@ RSpec.describe Api::V1::FiltersController do
let(:irreversible) { false }
let(:whole_word) { true }
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates a filter' do
+ it 'creates a filter', :aggregate_failures do
filter = user.account.custom_filters.first
+
+ expect(response).to have_http_status(200)
expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]]
expect(filter.context).to eq %w(home)
@@ -83,11 +79,8 @@ RSpec.describe Api::V1::FiltersController do
put :update, params: { id: keyword.id, phrase: 'updated' }
end
- it 'returns http success' do
+ it 'updates the filter', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'updates the filter' do
expect(keyword.reload.phrase).to eq 'updated'
end
end
@@ -101,11 +94,8 @@ RSpec.describe Api::V1::FiltersController do
delete :destroy, params: { id: keyword.id }
end
- it 'returns http success' do
+ it 'removes the filter', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'removes the filter' do
expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound
end
end
diff --git a/spec/controllers/api/v1/followed_tags_controller_spec.rb b/spec/controllers/api/v1/followed_tags_controller_spec.rb
deleted file mode 100644
index c1a366d4e3..0000000000
--- a/spec/controllers/api/v1/followed_tags_controller_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::FollowedTagsController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:scopes) { 'read:follows' }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- before { allow(controller).to receive(:doorkeeper_token) { token } }
-
- describe 'GET #index' do
- let!(:tag_follows) { Fabricate.times(5, :tag_follow, account: user.account) }
-
- before do
- get :index, params: { limit: 1 }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(:success)
- end
- end
-end
diff --git a/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb b/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb
index 88bcc40341..f79687df66 100644
--- a/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb
+++ b/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb
@@ -5,7 +5,7 @@ require 'rails_helper'
describe Api::V1::Instances::TranslationLanguagesController do
describe 'GET #show' do
context 'when no translation service is configured' do
- it 'returns empty language matrix' do
+ it 'returns empty language matrix', :aggregate_failures do
get :show
expect(response).to have_http_status(200)
@@ -19,7 +19,7 @@ describe Api::V1::Instances::TranslationLanguagesController do
allow(TranslationService).to receive_messages(configured?: true, configured: service)
end
- it 'returns language matrix' do
+ it 'returns language matrix', :aggregate_failures do
get :show
expect(response).to have_http_status(200)
diff --git a/spec/controllers/api/v1/lists/accounts_controller_spec.rb b/spec/controllers/api/v1/lists/accounts_controller_spec.rb
index d4550dd769..21e155a508 100644
--- a/spec/controllers/api/v1/lists/accounts_controller_spec.rb
+++ b/spec/controllers/api/v1/lists/accounts_controller_spec.rb
@@ -35,11 +35,8 @@ describe Api::V1::Lists::AccountsController do
post :create, params: { list_id: list.id, account_ids: [bob.id] }
end
- it 'returns http success' do
+ it 'adds account to the list', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'adds account to the list' do
expect(list.accounts.include?(bob)).to be true
end
end
@@ -50,11 +47,8 @@ describe Api::V1::Lists::AccountsController do
post :create, params: { list_id: list.id, account_ids: [bob.id] }
end
- it 'returns http success' do
+ it 'adds account to the list', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'adds account to the list' do
expect(list.accounts.include?(bob)).to be true
end
end
@@ -64,11 +58,8 @@ describe Api::V1::Lists::AccountsController do
post :create, params: { list_id: list.id, account_ids: [bob.id] }
end
- it 'returns http not found' do
+ it 'does not add the account to the list', :aggregate_failures do
expect(response).to have_http_status(404)
- end
-
- it 'does not add the account to the list' do
expect(list.accounts.include?(bob)).to be false
end
end
@@ -81,11 +72,8 @@ describe Api::V1::Lists::AccountsController do
delete :destroy, params: { list_id: list.id, account_ids: [list.accounts.first.id] }
end
- it 'returns http success' do
+ it 'removes account from the list', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'removes account from the list' do
expect(list.accounts.count).to eq 0
end
end
diff --git a/spec/controllers/api/v1/markers_controller_spec.rb b/spec/controllers/api/v1/markers_controller_spec.rb
index 64e9dcafb6..e954bbd1b6 100644
--- a/spec/controllers/api/v1/markers_controller_spec.rb
+++ b/spec/controllers/api/v1/markers_controller_spec.rb
@@ -18,13 +18,10 @@ RSpec.describe Api::V1::MarkersController do
get :index, params: { timeline: %w(home notifications) }
end
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns markers' do
+ it 'returns markers', :aggregate_failures do
json = body_as_json
+ expect(response).to have_http_status(200)
expect(json.key?(:home)).to be true
expect(json[:home][:last_read_id]).to eq '123'
expect(json.key?(:notifications)).to be true
@@ -38,11 +35,8 @@ RSpec.describe Api::V1::MarkersController do
post :create, params: { home: { last_read_id: '69420' } }
end
- it 'returns http success' do
+ it 'creates a marker', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'creates a marker' do
expect(user.markers.first.timeline).to eq 'home'
expect(user.markers.first.last_read_id).to eq 69_420
end
@@ -54,11 +48,8 @@ RSpec.describe Api::V1::MarkersController do
post :create, params: { home: { last_read_id: '70120' } }
end
- it 'returns http success' do
+ it 'updates a marker', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'updates a marker' do
expect(user.markers.first.timeline).to eq 'home'
expect(user.markers.first.last_read_id).to eq 70_120
end
diff --git a/spec/controllers/api/v1/media_controller_spec.rb b/spec/controllers/api/v1/media_controller_spec.rb
index 94b2a0a98f..b574381f90 100644
--- a/spec/controllers/api/v1/media_controller_spec.rb
+++ b/spec/controllers/api/v1/media_controller_spec.rb
@@ -38,19 +38,10 @@ RSpec.describe Api::V1::MediaController do
post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
end
- it 'returns http success' do
+ it 'creates a media attachment', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'creates a media attachment' do
expect(MediaAttachment.first).to_not be_nil
- end
-
- it 'uploads a file' do
expect(MediaAttachment.first).to have_attached_file(:file)
- end
-
- it 'returns media ID in JSON' do
expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
end
end
@@ -60,19 +51,10 @@ RSpec.describe Api::V1::MediaController do
post :create, params: { file: fixture_file_upload('attachment.gif', 'image/gif') }
end
- it 'returns http success' do
+ it 'creates a media attachment', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'creates a media attachment' do
expect(MediaAttachment.first).to_not be_nil
- end
-
- it 'uploads a file' do
expect(MediaAttachment.first).to have_attached_file(:file)
- end
-
- it 'returns media ID in JSON' do
expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
end
end
@@ -82,17 +64,10 @@ RSpec.describe Api::V1::MediaController do
post :create, params: { file: fixture_file_upload('attachment.webm', 'video/webm') }
end
- it do
- # returns http success
+ it 'creates a media attachment', :aggregate_failures do
expect(response).to have_http_status(200)
-
- # creates a media attachment
expect(MediaAttachment.first).to_not be_nil
-
- # uploads a file
expect(MediaAttachment.first).to have_attached_file(:file)
-
- # returns media ID in JSON
expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
end
end
diff --git a/spec/controllers/api/v1/polls/votes_controller_spec.rb b/spec/controllers/api/v1/polls/votes_controller_spec.rb
index 7abd2a1b17..5de225a487 100644
--- a/spec/controllers/api/v1/polls/votes_controller_spec.rb
+++ b/spec/controllers/api/v1/polls/votes_controller_spec.rb
@@ -18,18 +18,13 @@ RSpec.describe Api::V1::Polls::VotesController do
post :create, params: { poll_id: poll.id, choices: %w(1) }
end
- it 'returns http success' do
+ it 'creates a vote', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'creates a vote' do
vote = poll.votes.where(account: user.account).first
expect(vote).to_not be_nil
expect(vote.choice).to eq 1
- end
- it 'updates poll tallies' do
expect(poll.reload.cached_tallies).to eq [0, 1]
end
end
diff --git a/spec/controllers/api/v1/reports_controller_spec.rb b/spec/controllers/api/v1/reports_controller_spec.rb
deleted file mode 100644
index f923ff0794..0000000000
--- a/spec/controllers/api/v1/reports_controller_spec.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::ReportsController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
- let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
-
- let(:scopes) { 'write:reports' }
- let(:status) { Fabricate(:status) }
- let(:target_account) { status.account }
- let(:category) { nil }
- let(:forward) { nil }
- let(:rule_ids) { nil }
-
- before do
- post :create, params: { status_ids: [status.id], account_id: target_account.id, comment: 'reasons', category: category, rule_ids: rule_ids, forward: forward }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates a report' do
- expect(target_account.targeted_reports).to_not be_empty
- end
-
- it 'saves comment' do
- expect(target_account.targeted_reports.first.comment).to eq 'reasons'
- end
-
- it 'sends e-mails to admins' do
- expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email])
- end
-
- context 'when a status does not belong to the reported account' do
- let(:target_account) { Fabricate(:account) }
-
- it 'returns http not found' do
- expect(response).to have_http_status(404)
- end
- end
-
- context 'when a category is chosen' do
- let(:category) { 'spam' }
-
- it 'saves category' do
- expect(target_account.targeted_reports.first.spam?).to be true
- end
- end
-
- context 'when violated rules are chosen' do
- let(:rule) { Fabricate(:rule) }
- let(:category) { 'violation' }
- let(:rule_ids) { [rule.id] }
-
- it 'saves category' do
- expect(target_account.targeted_reports.first.violation?).to be true
- end
-
- it 'saves rule_ids' do
- expect(target_account.targeted_reports.first.rule_ids).to contain_exactly(rule.id)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/statuses/mutes_controller_spec.rb b/spec/controllers/api/v1/statuses/mutes_controller_spec.rb
index bffa9fe0d9..03274fe1cd 100644
--- a/spec/controllers/api/v1/statuses/mutes_controller_spec.rb
+++ b/spec/controllers/api/v1/statuses/mutes_controller_spec.rb
@@ -21,11 +21,8 @@ describe Api::V1::Statuses::MutesController do
post :create, params: { status_id: status.id }
end
- it 'returns http success' do
+ it 'creates a conversation mute', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'creates a conversation mute' do
expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to_not be_nil
end
end
@@ -38,11 +35,8 @@ describe Api::V1::Statuses::MutesController do
post :destroy, params: { status_id: status.id }
end
- it 'returns http success' do
+ it 'destroys the conversation mute', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'destroys the conversation mute' do
expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to be_nil
end
end
diff --git a/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb b/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb
index 756010af87..0d15cca75c 100644
--- a/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb
+++ b/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb
@@ -24,14 +24,12 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController do
Fabricate(:status, account: bob, reblog_of_id: status.id)
end
- it 'returns http success' do
+ it 'returns accounts who reblogged the status', :aggregate_failures do
get :index, params: { status_id: status.id, limit: 2 }
+
expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
- end
- it 'returns accounts who reblogged the status' do
- get :index, params: { status_id: status.id, limit: 2 }
expect(body_as_json.size).to eq 2
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
end
diff --git a/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb b/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb
index 16ce95dc22..2f2b30b07d 100644
--- a/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb
+++ b/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb
@@ -28,19 +28,13 @@ describe Api::V1::Statuses::ReblogsController do
end
context 'with public status' do
- it 'returns http success' do
+ it 'reblogs the status', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 1
- end
- it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be true
- end
- it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:reblog][:id]).to eq status.id.to_s
@@ -67,19 +61,13 @@ describe Api::V1::Statuses::ReblogsController do
post :destroy, params: { status_id: status.id }
end
- it 'returns http success' do
+ it 'destroys the reblog', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 0
- end
- it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be false
- end
- it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s
@@ -97,19 +85,13 @@ describe Api::V1::Statuses::ReblogsController do
post :destroy, params: { status_id: status.id }
end
- it 'returns http success' do
+ it 'destroys the reblog', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 0
- end
- it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be false
- end
- it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s
diff --git a/spec/controllers/api/v1/statuses/sources_controller_spec.rb b/spec/controllers/api/v1/statuses/sources_controller_spec.rb
deleted file mode 100644
index fbe6fa0be6..0000000000
--- a/spec/controllers/api/v1/statuses/sources_controller_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Statuses::SourcesController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses', application: app) }
-
- context 'with an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #show' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- get :show, params: { status_id: status.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/statuses_controller_spec.rb b/spec/controllers/api/v1/statuses_controller_spec.rb
index c2bdba9ace..30bafe19ac 100644
--- a/spec/controllers/api/v1/statuses_controller_spec.rb
+++ b/spec/controllers/api/v1/statuses_controller_spec.rb
@@ -30,14 +30,11 @@ RSpec.describe Api::V1::StatusesController do
user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide, keywords_attributes: [{ keyword: 'banned' }, { keyword: 'irrelevant' }])
end
- it 'returns http success' do
- get :show, params: { id: status.id }
- expect(response).to have_http_status(200)
- end
-
- it 'returns filter information' do
+ it 'returns filter information', :aggregate_failures do
get :show, params: { id: status.id }
json = body_as_json
+
+ expect(response).to have_http_status(200)
expect(json[:filtered][0]).to include({
filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s,
@@ -57,14 +54,11 @@ RSpec.describe Api::V1::StatusesController do
filter.statuses.create!(status_id: status.id)
end
- it 'returns http success' do
- get :show, params: { id: status.id }
- expect(response).to have_http_status(200)
- end
-
- it 'returns filter information' do
+ it 'returns filter information', :aggregate_failures do
get :show, params: { id: status.id }
json = body_as_json
+
+ expect(response).to have_http_status(200)
expect(json[:filtered][0]).to include({
filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s,
@@ -83,14 +77,11 @@ RSpec.describe Api::V1::StatusesController do
user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide, keywords_attributes: [{ keyword: 'banned' }, { keyword: 'irrelevant' }])
end
- it 'returns http success' do
- get :show, params: { id: status.id }
- expect(response).to have_http_status(200)
- end
-
- it 'returns filter information' do
+ it 'returns filter information', :aggregate_failures do
get :show, params: { id: status.id }
json = body_as_json
+
+ expect(response).to have_http_status(200)
expect(json[:reblog][:filtered][0]).to include({
filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s,
@@ -125,11 +116,8 @@ RSpec.describe Api::V1::StatusesController do
post :create, params: { status: 'Hello world' }
end
- it 'returns http success' do
+ it 'returns rate limit headers', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'returns rate limit headers' do
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
expect(response.headers['X-RateLimit-Remaining']).to eq (RateLimiter::FAMILIES[:statuses][:limit] - 1).to_s
end
@@ -143,11 +131,8 @@ RSpec.describe Api::V1::StatusesController do
post :create, params: { status: '@alice hm, @bob is really annoying lately', allowed_mentions: [alice.id] }
end
- it 'returns http unprocessable entity' do
+ it 'returns serialized extra accounts in body', :aggregate_failures do
expect(response).to have_http_status(422)
- end
-
- it 'returns serialized extra accounts in body' do
expect(body_as_json[:unexpected_accounts].map { |a| a.slice(:id, :acct) }).to eq [{ id: bob.id.to_s, acct: bob.acct }]
end
end
@@ -157,11 +142,8 @@ RSpec.describe Api::V1::StatusesController do
post :create, params: {}
end
- it 'returns http unprocessable entity' do
+ it 'returns rate limit headers', :aggregate_failures do
expect(response).to have_http_status(422)
- end
-
- it 'returns rate limit headers' do
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
end
end
@@ -173,11 +155,8 @@ RSpec.describe Api::V1::StatusesController do
post :create, params: { status: 'Hello world' }
end
- it 'returns http too many requests' do
+ it 'returns rate limit headers', :aggregate_failures do
expect(response).to have_http_status(429)
- end
-
- it 'returns rate limit headers' do
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
expect(response.headers['X-RateLimit-Remaining']).to eq '0'
end
@@ -192,11 +171,8 @@ RSpec.describe Api::V1::StatusesController do
post :destroy, params: { id: status.id }
end
- it 'returns http success' do
+ it 'removes the status', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'removes the status' do
expect(Status.find_by(id: status.id)).to be_nil
end
end
@@ -209,11 +185,8 @@ RSpec.describe Api::V1::StatusesController do
put :update, params: { id: status.id, status: 'I am updated' }
end
- it 'returns http success' do
+ it 'updates the status', :aggregate_failures do
expect(response).to have_http_status(200)
- end
-
- it 'updates the status' do
expect(status.reload.text).to eq 'I am updated'
end
end
diff --git a/spec/controllers/api/v1/timelines/tag_controller_spec.rb b/spec/controllers/api/v1/timelines/tag_controller_spec.rb
deleted file mode 100644
index 1c60798fcf..0000000000
--- a/spec/controllers/api/v1/timelines/tag_controller_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Timelines::TagController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #show' do
- subject do
- get :show, params: { id: 'test' }
- end
-
- before do
- PostStatusService.new.call(user.account, text: 'It is a #test')
- end
-
- context 'when the instance allows public preview' do
- context 'when the user is not authenticated' do
- let(:token) { nil }
-
- it 'returns http success', :aggregate_failures do
- subject
-
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].links.size).to eq(2)
- end
- end
-
- context 'when the user is authenticated' do
- it 'returns http success', :aggregate_failures do
- subject
-
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].links.size).to eq(2)
- end
- end
- end
-
- context 'when the instance does not allow public preview' do
- before do
- Form::AdminSettings.new(timeline_preview: false).save
- end
-
- context 'when the user is not authenticated' do
- let(:token) { nil }
-
- it 'returns http unauthorized' do
- subject
-
- expect(response).to have_http_status(401)
- end
- end
-
- context 'when the user is authenticated' do
- it 'returns http success', :aggregate_failures do
- subject
-
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].links.size).to eq(2)
- end
- end
- end
- end
-end
diff --git a/spec/controllers/api/v2/admin/accounts_controller_spec.rb b/spec/controllers/api/v2/admin/accounts_controller_spec.rb
index 635f645915..18b3950140 100644
--- a/spec/controllers/api/v2/admin/accounts_controller_spec.rb
+++ b/spec/controllers/api/v2/admin/accounts_controller_spec.rb
@@ -44,14 +44,14 @@ RSpec.describe Api::V2::Admin::AccountsController do
context "when called with #{params.inspect}" do
let(:params) { params }
- it 'returns http success' do
+ it "returns the correct accounts (#{expected_results.inspect})" do
expect(response).to have_http_status(200)
+
+ expect(body_json_ids).to eq(expected_results.map { |symbol| send(symbol).id })
end
- it "returns the correct accounts (#{expected_results.inspect})" do
- json = body_as_json
-
- expect(json.map { |a| a[:id].to_i }).to eq(expected_results.map { |symbol| send(symbol).id })
+ def body_json_ids
+ body_as_json.map { |a| a[:id].to_i }
end
end
end
diff --git a/spec/controllers/api/v2/filters/keywords_controller_spec.rb b/spec/controllers/api/v2/filters/keywords_controller_spec.rb
index 057a9c3d00..5321f787a1 100644
--- a/spec/controllers/api/v2/filters/keywords_controller_spec.rb
+++ b/spec/controllers/api/v2/filters/keywords_controller_spec.rb
@@ -40,17 +40,13 @@ RSpec.describe Api::V2::Filters::KeywordsController do
post :create, params: { filter_id: filter_id, keyword: 'magic', whole_word: false }
end
- it 'returns http success' do
+ it 'creates a filter', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'returns a keyword' do
json = body_as_json
expect(json[:keyword]).to eq 'magic'
expect(json[:whole_word]).to be false
- end
- it 'creates a keyword' do
filter = user.account.custom_filters.first
expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword)).to eq ['magic']
@@ -73,11 +69,9 @@ RSpec.describe Api::V2::Filters::KeywordsController do
get :show, params: { id: keyword.id }
end
- it 'returns http success' do
+ it 'responds with the keyword', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'returns expected data' do
json = body_as_json
expect(json[:keyword]).to eq 'foo'
expect(json[:whole_word]).to be false
@@ -100,11 +94,9 @@ RSpec.describe Api::V2::Filters::KeywordsController do
get :update, params: { id: keyword.id, keyword: 'updated' }
end
- it 'returns http success' do
+ it 'updates the keyword', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'updates the keyword' do
expect(keyword.reload.keyword).to eq 'updated'
end
@@ -125,11 +117,9 @@ RSpec.describe Api::V2::Filters::KeywordsController do
delete :destroy, params: { id: keyword.id }
end
- it 'returns http success' do
+ it 'destroys the keyword', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'removes the filter' do
expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound
end
diff --git a/spec/controllers/api/v2/filters/statuses_controller_spec.rb b/spec/controllers/api/v2/filters/statuses_controller_spec.rb
index 588532ffd2..5c2a623954 100644
--- a/spec/controllers/api/v2/filters/statuses_controller_spec.rb
+++ b/spec/controllers/api/v2/filters/statuses_controller_spec.rb
@@ -41,16 +41,12 @@ RSpec.describe Api::V2::Filters::StatusesController do
post :create, params: { filter_id: filter_id, status_id: status.id }
end
- it 'returns http success' do
+ it 'creates a filter', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'returns a status filter' do
json = body_as_json
expect(json[:status_id]).to eq status.id.to_s
- end
- it 'creates a status filter' do
filter = user.account.custom_filters.first
expect(filter).to_not be_nil
expect(filter.statuses.pluck(:status_id)).to eq [status.id]
@@ -73,11 +69,9 @@ RSpec.describe Api::V2::Filters::StatusesController do
get :show, params: { id: status_filter.id }
end
- it 'returns http success' do
+ it 'responds with the filter', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'returns expected data' do
json = body_as_json
expect(json[:status_id]).to eq status_filter.status_id.to_s
end
@@ -99,11 +93,9 @@ RSpec.describe Api::V2::Filters::StatusesController do
delete :destroy, params: { id: status_filter.id }
end
- it 'returns http success' do
+ it 'destroys the filter', :aggregate_failures do
expect(response).to have_http_status(200)
- end
- it 'removes the filter' do
expect { status_filter.reload }.to raise_error ActiveRecord::RecordNotFound
end
diff --git a/spec/features/admin/accounts_spec.rb b/spec/features/admin/accounts_spec.rb
new file mode 100644
index 0000000000..6d7bab1844
--- /dev/null
+++ b/spec/features/admin/accounts_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Admin::Accounts' do
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+
+ before do
+ sign_in current_user
+ end
+
+ describe 'Performing batch updates' do
+ let(:unapproved_user_account) { Fabricate(:account) }
+ let(:approved_user_account) { Fabricate(:account) }
+
+ before do
+ unapproved_user_account.user.update(approved: false)
+ approved_user_account.user.update(approved: true)
+
+ visit admin_accounts_path
+ end
+
+ context 'without selecting any accounts' do
+ it 'displays a notice about account selection' do
+ click_on button_for_suspend
+
+ expect(page).to have_content(selection_error_text)
+ end
+ end
+
+ context 'with action of `suspend`' do
+ it 'suspends the account' do
+ batch_checkbox_for(approved_user_account).check
+
+ click_on button_for_suspend
+
+ expect(approved_user_account.reload).to be_suspended
+ end
+ end
+
+ context 'with action of `approve`' do
+ it 'approves the account user' do
+ batch_checkbox_for(unapproved_user_account).check
+
+ click_on button_for_approve
+
+ expect(unapproved_user_account.reload.user).to be_approved
+ end
+ end
+
+ context 'with action of `reject`' do
+ it 'rejects and removes the account' do
+ batch_checkbox_for(unapproved_user_account).check
+
+ click_on button_for_reject
+
+ expect { unapproved_user_account.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ def button_for_suspend
+ I18n.t('admin.accounts.perform_full_suspension')
+ end
+
+ def button_for_approve
+ I18n.t('admin.accounts.approve')
+ end
+
+ def button_for_reject
+ I18n.t('admin.accounts.reject')
+ end
+
+ def selection_error_text
+ I18n.t('admin.accounts.no_account_selected')
+ end
+
+ def batch_checkbox_for(account)
+ find("#form_account_batch_account_ids_#{account.id}")
+ end
+ end
+end
diff --git a/spec/features/admin/custom_emojis_spec.rb b/spec/features/admin/custom_emojis_spec.rb
new file mode 100644
index 0000000000..8a8b6efcd1
--- /dev/null
+++ b/spec/features/admin/custom_emojis_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Admin::CustomEmojis' do
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+
+ before do
+ sign_in current_user
+ end
+
+ describe 'Performing batch updates' do
+ before do
+ visit admin_custom_emojis_path
+ end
+
+ context 'without selecting any records' do
+ it 'displays a notice about selection' do
+ click_on button_for_enable
+
+ expect(page).to have_content(selection_error_text)
+ end
+ end
+
+ def button_for_enable
+ I18n.t('admin.custom_emojis.enable')
+ end
+
+ def selection_error_text
+ I18n.t('admin.custom_emojis.no_emoji_selected')
+ end
+ end
+end
diff --git a/spec/features/admin/email_domain_blocks_spec.rb b/spec/features/admin/email_domain_blocks_spec.rb
new file mode 100644
index 0000000000..14959cbe74
--- /dev/null
+++ b/spec/features/admin/email_domain_blocks_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Admin::EmailDomainBlocks' do
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+
+ before do
+ sign_in current_user
+ end
+
+ describe 'Performing batch updates' do
+ before do
+ visit admin_email_domain_blocks_path
+ end
+
+ context 'without selecting any records' do
+ it 'displays a notice about selection' do
+ click_on button_for_delete
+
+ expect(page).to have_content(selection_error_text)
+ end
+ end
+
+ def button_for_delete
+ I18n.t('admin.email_domain_blocks.delete')
+ end
+
+ def selection_error_text
+ I18n.t('admin.email_domain_blocks.no_email_domain_block_selected')
+ end
+ end
+end
diff --git a/spec/features/admin/ip_blocks_spec.rb b/spec/features/admin/ip_blocks_spec.rb
new file mode 100644
index 0000000000..c9b16f6f78
--- /dev/null
+++ b/spec/features/admin/ip_blocks_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Admin::IpBlocks' do
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+
+ before do
+ sign_in current_user
+ end
+
+ describe 'Performing batch updates' do
+ before do
+ visit admin_ip_blocks_path
+ end
+
+ context 'without selecting any records' do
+ it 'displays a notice about selection' do
+ click_on button_for_delete
+
+ expect(page).to have_content(selection_error_text)
+ end
+ end
+
+ def button_for_delete
+ I18n.t('admin.ip_blocks.delete')
+ end
+
+ def selection_error_text
+ I18n.t('admin.ip_blocks.no_ip_block_selected')
+ end
+ end
+end
diff --git a/spec/features/admin/statuses_spec.rb b/spec/features/admin/statuses_spec.rb
new file mode 100644
index 0000000000..531d0de953
--- /dev/null
+++ b/spec/features/admin/statuses_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Admin::Statuses' do
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+
+ before do
+ sign_in current_user
+ end
+
+ describe 'Performing batch updates' do
+ before do
+ _status = Fabricate(:status, account: current_user.account)
+ visit admin_account_statuses_path(account_id: current_user.account_id)
+ end
+
+ context 'without selecting any records' do
+ it 'displays a notice about selection' do
+ click_on button_for_report
+
+ expect(page).to have_content(selection_error_text)
+ end
+ end
+
+ def button_for_report
+ I18n.t('admin.statuses.batch.report')
+ end
+
+ def selection_error_text
+ I18n.t('admin.statuses.no_status_selected')
+ end
+ end
+end
diff --git a/spec/features/admin/trends/links/preview_card_providers_spec.rb b/spec/features/admin/trends/links/preview_card_providers_spec.rb
new file mode 100644
index 0000000000..dca89117b1
--- /dev/null
+++ b/spec/features/admin/trends/links/preview_card_providers_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Admin::Trends::Links::PreviewCardProviders' do
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+
+ before do
+ sign_in current_user
+ end
+
+ describe 'Performing batch updates' do
+ before do
+ visit admin_trends_links_preview_card_providers_path
+ end
+
+ context 'without selecting any records' do
+ it 'displays a notice about selection' do
+ click_on button_for_allow
+
+ expect(page).to have_content(selection_error_text)
+ end
+ end
+
+ def button_for_allow
+ I18n.t('admin.trends.allow')
+ end
+
+ def selection_error_text
+ I18n.t('admin.trends.links.publishers.no_publisher_selected')
+ end
+ end
+end
diff --git a/spec/features/admin/trends/links_spec.rb b/spec/features/admin/trends/links_spec.rb
new file mode 100644
index 0000000000..99638bc069
--- /dev/null
+++ b/spec/features/admin/trends/links_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Admin::Trends::Links' do
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+
+ before do
+ sign_in current_user
+ end
+
+ describe 'Performing batch updates' do
+ before do
+ visit admin_trends_links_path
+ end
+
+ context 'without selecting any records' do
+ it 'displays a notice about selection' do
+ click_on button_for_allow
+
+ expect(page).to have_content(selection_error_text)
+ end
+ end
+
+ def button_for_allow
+ I18n.t('admin.trends.links.allow')
+ end
+
+ def selection_error_text
+ I18n.t('admin.trends.links.no_link_selected')
+ end
+ end
+end
diff --git a/spec/features/admin/trends/statuses_spec.rb b/spec/features/admin/trends/statuses_spec.rb
new file mode 100644
index 0000000000..779a15d38f
--- /dev/null
+++ b/spec/features/admin/trends/statuses_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Admin::Trends::Statuses' do
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+
+ before do
+ sign_in current_user
+ end
+
+ describe 'Performing batch updates' do
+ before do
+ visit admin_trends_statuses_path
+ end
+
+ context 'without selecting any records' do
+ it 'displays a notice about selection' do
+ click_on button_for_allow
+
+ expect(page).to have_content(selection_error_text)
+ end
+ end
+
+ def button_for_allow
+ I18n.t('admin.trends.statuses.allow')
+ end
+
+ def selection_error_text
+ I18n.t('admin.trends.statuses.no_status_selected')
+ end
+ end
+end
diff --git a/spec/features/admin/trends/tags_spec.rb b/spec/features/admin/trends/tags_spec.rb
new file mode 100644
index 0000000000..52e49c3a5d
--- /dev/null
+++ b/spec/features/admin/trends/tags_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Admin::Trends::Tags' do
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+
+ before do
+ sign_in current_user
+ end
+
+ describe 'Performing batch updates' do
+ before do
+ visit admin_trends_tags_path
+ end
+
+ context 'without selecting any records' do
+ it 'displays a notice about selection' do
+ click_on button_for_allow
+
+ expect(page).to have_content(selection_error_text)
+ end
+ end
+
+ def button_for_allow
+ I18n.t('admin.trends.allow')
+ end
+
+ def selection_error_text
+ I18n.t('admin.trends.tags.no_tag_selected')
+ end
+ end
+end
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
index 7b8dccb6a0..06e8418a0e 100644
--- a/spec/rails_helper.rb
+++ b/spec/rails_helper.rb
@@ -54,26 +54,6 @@ Devise::Test::ControllerHelpers.module_eval do
end
end
-module SignedRequestHelpers
- def get(path, headers: nil, sign_with: nil, **args)
- return super path, headers: headers, **args if sign_with.nil?
-
- headers ||= {}
- headers['Date'] = Time.now.utc.httpdate
- headers['Host'] = ENV.fetch('LOCAL_DOMAIN')
- signed_headers = headers.merge('(request-target)' => "get #{path}").slice('(request-target)', 'Host', 'Date')
-
- key_id = ActivityPub::TagManager.instance.key_uri_for(sign_with)
- keypair = sign_with.keypair
- signed_string = signed_headers.map { |key, value| "#{key.downcase}: #{value}" }.join("\n")
- signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string))
-
- headers['Signature'] = "keyId=\"#{key_id}\",algorithm=\"rsa-sha256\",headers=\"#{signed_headers.keys.join(' ').downcase}\",signature=\"#{signature}\""
-
- super path, headers: headers, **args
- end
-end
-
RSpec.configure do |config|
# This is set before running spec:system, see lib/tasks/tests.rake
config.filter_run_excluding type: lambda { |type|
diff --git a/spec/requests/api/v1/admin/account_actions_spec.rb b/spec/requests/api/v1/admin/account_actions_spec.rb
index 9295d262d6..bdf1f08e43 100644
--- a/spec/requests/api/v1/admin/account_actions_spec.rb
+++ b/spec/requests/api/v1/admin/account_actions_spec.rb
@@ -51,14 +51,9 @@ RSpec.describe 'Account actions' do
it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :disable, :user
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
it 'disables the target account' do
expect { subject }.to change { target_account.reload.user_disabled? }.from(false).to(true)
+ expect(response).to have_http_status(200)
end
end
@@ -70,14 +65,9 @@ RSpec.describe 'Account actions' do
it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :sensitive, :account
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
it 'marks the target account as sensitive' do
expect { subject }.to change { target_account.reload.sensitized? }.from(false).to(true)
+ expect(response).to have_http_status(200)
end
end
@@ -89,14 +79,9 @@ RSpec.describe 'Account actions' do
it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :silence, :account
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
it 'marks the target account as silenced' do
expect { subject }.to change { target_account.reload.silenced? }.from(false).to(true)
+ expect(response).to have_http_status(200)
end
end
@@ -108,14 +93,9 @@ RSpec.describe 'Account actions' do
it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :suspend, :account
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
it 'marks the target account as suspended' do
expect { subject }.to change { target_account.reload.suspended? }.from(false).to(true)
+ expect(response).to have_http_status(200)
end
end
diff --git a/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb b/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb
index 4382cb84e5..3f33b50f39 100644
--- a/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb
+++ b/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb
@@ -92,15 +92,10 @@ RSpec.describe 'Canonical Email Blocks' do
it_behaves_like 'forbidden for wrong role', 'Moderator'
context 'when the requested canonical email block exists' do
- it 'returns http success' do
+ it 'returns the requested canonical email block data correctly', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the requested canonical email block data correctly' do
- subject
-
json = body_as_json
expect(json[:id]).to eq(canonical_email_block.id.to_s)
@@ -142,29 +137,19 @@ RSpec.describe 'Canonical Email Blocks' do
context 'when there is a matching canonical email block' do
let!(:canonical_email_block) { CanonicalEmailBlock.create(params) }
- it 'returns http success' do
+ it 'returns the expected canonical email hash', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the expected canonical email hash' do
- subject
-
expect(body_as_json[0][:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
end
end
context 'when there is no matching canonical email block' do
- it 'returns http success' do
+ it 'returns an empty list', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns an empty list' do
- subject
-
expect(body_as_json).to be_empty
end
end
@@ -183,15 +168,10 @@ RSpec.describe 'Canonical Email Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'returns the canonical_email_hash correctly', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the canonical_email_hash correctly' do
- subject
-
expect(body_as_json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
end
@@ -208,15 +188,10 @@ RSpec.describe 'Canonical Email Blocks' do
context 'when the canonical_email_hash param is provided instead of email' do
let(:params) { { canonical_email_hash: 'dd501ce4e6b08698f19df96f2f15737e48a75660b1fa79b6ff58ea25ee4851a4' } }
- it 'returns http success' do
+ it 'returns the correct canonical_email_hash', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the correct canonical_email_hash' do
- subject
-
expect(body_as_json[:canonical_email_hash]).to eq(params[:canonical_email_hash])
end
end
@@ -224,15 +199,10 @@ RSpec.describe 'Canonical Email Blocks' do
context 'when both email and canonical_email_hash params are provided' do
let(:params) { { email: 'example@email.com', canonical_email_hash: 'dd501ce4e6b08698f19df96f2f15737e48a75660b1fa79b6ff58ea25ee4851a4' } }
- it 'returns http success' do
+ it 'ignores the canonical_email_hash param', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'ignores the canonical_email_hash param' do
- subject
-
expect(body_as_json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
end
end
@@ -262,15 +232,10 @@ RSpec.describe 'Canonical Email Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'deletes the canonical email block', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'deletes the canonical email block' do
- subject
-
expect(CanonicalEmailBlock.find_by(id: canonical_email_block.id)).to be_nil
end
diff --git a/spec/requests/api/v1/admin/domain_allows_spec.rb b/spec/requests/api/v1/admin/domain_allows_spec.rb
index 96000e3ef4..6db1ab6e30 100644
--- a/spec/requests/api/v1/admin/domain_allows_spec.rb
+++ b/spec/requests/api/v1/admin/domain_allows_spec.rb
@@ -75,15 +75,10 @@ RSpec.describe 'Domain Allows' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'returns the expected allowed domain name', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the expected allowed domain name' do
- subject
-
expect(body_as_json[:domain]).to eq domain_allow.domain
end
@@ -108,21 +103,11 @@ RSpec.describe 'Domain Allows' do
it_behaves_like 'forbidden for wrong role', 'Moderator'
context 'with a valid domain name' do
- it 'returns http success' do
+ it 'returns the expected domain name', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the expected domain name' do
- subject
-
expect(body_as_json[:domain]).to eq 'foo.bar.com'
- end
-
- it 'creates a domain allow' do
- subject
-
expect(DomainAllow.find_by(domain: 'foo.bar.com')).to be_present
end
end
@@ -171,15 +156,10 @@ RSpec.describe 'Domain Allows' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'deletes the allowed domain', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'deletes the allowed domain' do
- subject
-
expect(DomainAllow.find_by(id: domain_allow.id)).to be_nil
end
diff --git a/spec/requests/api/v1/admin/domain_blocks_spec.rb b/spec/requests/api/v1/admin/domain_blocks_spec.rb
index 1432e52623..1041fdb713 100644
--- a/spec/requests/api/v1/admin/domain_blocks_spec.rb
+++ b/spec/requests/api/v1/admin/domain_blocks_spec.rb
@@ -45,22 +45,6 @@ RSpec.describe 'Domain Blocks' do
]
end
let(:expected_responde) do
- domain_blocks.map do |domain_block|
- {
- id: domain_block.id.to_s,
- domain: domain_block.domain,
- created_at: domain_block.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ'),
- severity: domain_block.severity.to_s,
- reject_media: domain_block.reject_media,
- reject_reports: domain_block.reject_reports,
- private_comment: domain_block.private_comment,
- public_comment: domain_block.public_comment,
- obfuscate: domain_block.obfuscate,
- }
- end
- end
-
- let(:expected_responde_with_kb_custom) do
domain_blocks.map do |domain_block|
{
id: domain_block.id.to_s,
@@ -84,6 +68,7 @@ RSpec.describe 'Domain Blocks' do
reject_send_public_unlisted: domain_block.reject_send_public_unlisted,
reject_send_sensitive: domain_block.reject_send_sensitive,
reject_straight_follow: domain_block.reject_straight_follow,
+ reject_friend: domain_block.reject_friend,
}
end
end
@@ -91,7 +76,7 @@ RSpec.describe 'Domain Blocks' do
it 'returns the expected domain blocks' do
subject
- expect(body_as_json).to match_array(expected_responde_with_kb_custom)
+ expect(body_as_json).to match_array(expected_responde)
end
context 'with limit param' do
@@ -136,6 +121,7 @@ RSpec.describe 'Domain Blocks' do
reject_send_public_unlisted: domain_block.reject_send_public_unlisted,
reject_send_sensitive: domain_block.reject_send_sensitive,
reject_straight_follow: domain_block.reject_straight_follow,
+ reject_friend: domain_block.reject_friend,
}
end
@@ -143,16 +129,36 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'returns the expected domain block content', :aggregate_failures do # rubocop:disable RSpec/ExampleLength
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the expected domain block content' do
- subject
-
- expect(body_as_json).to eq(expected_response)
+ expect(body_as_json).to eq(
+ {
+ id: domain_block.id.to_s,
+ domain: domain_block.domain,
+ created_at: domain_block.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ'),
+ severity: domain_block.severity.to_s,
+ reject_media: domain_block.reject_media,
+ reject_reports: domain_block.reject_reports,
+ private_comment: domain_block.private_comment,
+ public_comment: domain_block.public_comment,
+ obfuscate: domain_block.obfuscate,
+ reject_favourite: domain_block.reject_favourite,
+ reject_hashtag: domain_block.reject_hashtag,
+ detect_invalid_subscription: domain_block.detect_invalid_subscription,
+ reject_new_follow: domain_block.reject_new_follow,
+ reject_reply: domain_block.reject_reply,
+ reject_reply_exclude_followers: domain_block.reject_reply_exclude_followers,
+ reject_send_dissubscribable: domain_block.reject_send_dissubscribable,
+ reject_send_media: domain_block.reject_send_media,
+ reject_send_not_public_searchability: domain_block.reject_send_not_public_searchability,
+ reject_send_public_unlisted: domain_block.reject_send_public_unlisted,
+ reject_send_sensitive: domain_block.reject_send_sensitive,
+ reject_straight_follow: domain_block.reject_straight_follow,
+ reject_friend: domain_block.reject_friend,
+ }
+ )
end
context 'when the requested domain block does not exist' do
@@ -175,27 +181,18 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
- it 'returns expected domain name and severity' do
+ it 'returns expected domain name and severity', :aggregate_failures do
subject
body = body_as_json
+ expect(response).to have_http_status(200)
expect(body).to match a_hash_including(
{
domain: 'foo.bar.com',
severity: 'silence',
}
)
- end
-
- it 'creates a domain block' do
- subject
expect(DomainBlock.find_by(domain: 'foo.bar.com')).to be_present
end
@@ -205,15 +202,10 @@ RSpec.describe 'Domain Blocks' do
Fabricate(:domain_block, domain: 'bar.com', severity: :suspend)
end
- it 'returns http unprocessable entity' do
+ it 'returns existing domain block in error', :aggregate_failures do
subject
expect(response).to have_http_status(422)
- end
-
- it 'returns existing domain block in error' do
- subject
-
expect(body_as_json[:existing_domain_block][:domain]).to eq('bar.com')
end
end
@@ -241,15 +233,10 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'returns the updated domain block', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the updated domain block' do
- subject
-
expect(body_as_json).to match a_hash_including(
{
id: domain_block.id.to_s,
@@ -283,15 +270,10 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'deletes the domain block', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'deletes the domain block' do
- subject
-
expect(DomainBlock.find_by(id: domain_block.id)).to be_nil
end
diff --git a/spec/requests/api/v1/admin/email_domain_blocks_spec.rb b/spec/requests/api/v1/admin/email_domain_blocks_spec.rb
index d512def866..16656e0202 100644
--- a/spec/requests/api/v1/admin/email_domain_blocks_spec.rb
+++ b/spec/requests/api/v1/admin/email_domain_blocks_spec.rb
@@ -93,15 +93,10 @@ RSpec.describe 'Email Domain Blocks' do
it_behaves_like 'forbidden for wrong role', 'Moderator'
context 'when email domain block exists' do
- it 'returns http success' do
+ it 'returns the correct blocked domain', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the correct blocked domain' do
- subject
-
expect(body_as_json[:domain]).to eq(email_domain_block.domain)
end
end
@@ -126,15 +121,10 @@ RSpec.describe 'Email Domain Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'returns the correct blocked email domain', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the correct blocked email domain' do
- subject
-
expect(body_as_json[:domain]).to eq(params[:domain])
end
@@ -182,21 +172,11 @@ RSpec.describe 'Email Domain Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'deletes email domain block', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns an empty body' do
- subject
-
expect(body_as_json).to be_empty
- end
-
- it 'deletes email domain block' do
- subject
-
expect(EmailDomainBlock.find_by(id: email_domain_block.id)).to be_nil
end
diff --git a/spec/requests/api/v1/admin/ip_blocks_spec.rb b/spec/requests/api/v1/admin/ip_blocks_spec.rb
index d03886c51b..fbcb39e3be 100644
--- a/spec/requests/api/v1/admin/ip_blocks_spec.rb
+++ b/spec/requests/api/v1/admin/ip_blocks_spec.rb
@@ -84,15 +84,10 @@ RSpec.describe 'IP Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'returns the correct ip block', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the correct ip block' do
- subject
-
json = body_as_json
expect(json[:ip]).to eq("#{ip_block.ip}/#{ip_block.ip.prefix}")
@@ -119,15 +114,10 @@ RSpec.describe 'IP Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
- it 'returns http success' do
+ it 'returns the correct ip block', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the correct ip block' do
- subject
-
json = body_as_json
expect(json[:ip]).to eq("#{params[:ip]}/32")
@@ -186,15 +176,10 @@ RSpec.describe 'IP Blocks' do
let!(:ip_block) { IpBlock.create(ip: '185.200.13.3', severity: 'no_access', comment: 'Spam', expires_in: 48.hours) }
let(:params) { { severity: 'sign_up_requires_approval', comment: 'Decreasing severity' } }
- it 'returns http success' do
+ it 'returns the correct ip block', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the correct ip block' do
- subject
-
expect(body_as_json).to match(hash_including({
ip: "#{ip_block.ip}/#{ip_block.ip.prefix}",
severity: 'sign_up_requires_approval',
@@ -226,21 +211,11 @@ RSpec.describe 'IP Blocks' do
let!(:ip_block) { IpBlock.create(ip: '185.200.13.3', severity: 'no_access') }
- it 'returns http success' do
+ it 'deletes the ip block', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns an empty body' do
- subject
-
expect(body_as_json).to be_empty
- end
-
- it 'deletes the ip block' do
- subject
-
expect(IpBlock.find_by(id: ip_block.id)).to be_nil
end
diff --git a/spec/requests/api/v1/admin/reports_spec.rb b/spec/requests/api/v1/admin/reports_spec.rb
index 91c3c11f5d..5403457db0 100644
--- a/spec/requests/api/v1/admin/reports_spec.rb
+++ b/spec/requests/api/v1/admin/reports_spec.rb
@@ -122,15 +122,10 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
+ it 'returns the requested report content', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the requested report content' do
- subject
-
expect(body_as_json).to include(
{
id: report.id.to_s,
@@ -155,18 +150,10 @@ RSpec.describe 'Reports' do
let!(:report) { Fabricate(:report, category: :other) }
let(:params) { { category: 'spam' } }
- it 'returns http success' do
- subject
+ it 'updates the report category', :aggregate_failures do
+ expect { subject }.to change { report.reload.category }.from('other').to('spam')
expect(response).to have_http_status(200)
- end
-
- it 'updates the report category' do
- expect { subject }.to change { report.reload.category }.from('other').to('spam')
- end
-
- it 'returns the updated report content' do
- subject
report.reload
@@ -196,14 +183,9 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
- it 'marks report as resolved' do
+ it 'marks report as resolved', :aggregate_failures do
expect { subject }.to change { report.reload.unresolved? }.from(true).to(false)
+ expect(response).to have_http_status(200)
end
end
@@ -217,14 +199,9 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
- it 'marks report as unresolved' do
+ it 'marks report as unresolved', :aggregate_failures do
expect { subject }.to change { report.reload.unresolved? }.from(false).to(true)
+ expect(response).to have_http_status(200)
end
end
@@ -238,14 +215,9 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
- it 'assigns report to the requesting user' do
+ it 'assigns report to the requesting user', :aggregate_failures do
expect { subject }.to change { report.reload.assigned_account_id }.from(nil).to(user.account.id)
+ expect(response).to have_http_status(200)
end
end
@@ -259,14 +231,9 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
- it 'unassigns report from assignee' do
+ it 'unassigns report from assignee', :aggregate_failures do
expect { subject }.to change { report.reload.assigned_account_id }.from(user.account.id).to(nil)
+ expect(response).to have_http_status(200)
end
end
end
diff --git a/spec/requests/api/v1/admin/trends/links/links_spec.rb b/spec/requests/api/v1/admin/trends/links/links_spec.rb
new file mode 100644
index 0000000000..05020b0fd0
--- /dev/null
+++ b/spec/requests/api/v1/admin/trends/links/links_spec.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Links' do
+ let(:role) { UserRole.find_by(name: 'Admin') }
+ let(:user) { Fabricate(:user, role: role) }
+ let(:scopes) { 'admin:read admin:write' }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+
+ describe 'GET /api/v1/admin/trends/links' do
+ subject do
+ get '/api/v1/admin/trends/links', headers: headers
+ end
+
+ it 'returns http success' do
+ subject
+
+ expect(response).to have_http_status(200)
+ end
+ end
+
+ describe 'POST /api/v1/admin/trends/links/:id/approve' do
+ subject do
+ post "/api/v1/admin/trends/links/#{preview_card.id}/approve", headers: headers
+ end
+
+ let(:preview_card) { Fabricate(:preview_card, trendable: false) }
+
+ it_behaves_like 'forbidden for wrong scope', 'read write'
+ it_behaves_like 'forbidden for wrong role', ''
+
+ it 'returns http success' do
+ subject
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'sets the link as trendable' do
+ expect { subject }.to change { preview_card.reload.trendable }.from(false).to(true)
+ end
+
+ it 'returns the link data' do
+ subject
+
+ expect(body_as_json).to match(
+ a_hash_including(
+ url: preview_card.url,
+ title: preview_card.title,
+ description: preview_card.description,
+ type: 'link',
+ requires_review: false
+ )
+ )
+ end
+
+ context 'when the link does not exist' do
+ it 'returns http not found' do
+ post '/api/v1/admin/trends/links/-1/approve', headers: headers
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'without an authorization header' do
+ let(:headers) { {} }
+
+ it 'returns http forbidden' do
+ subject
+
+ expect(response).to have_http_status(403)
+ end
+ end
+ end
+
+ describe 'POST /api/v1/admin/trends/links/:id/reject' do
+ subject do
+ post "/api/v1/admin/trends/links/#{preview_card.id}/reject", headers: headers
+ end
+
+ let(:preview_card) { Fabricate(:preview_card, trendable: false) }
+
+ it_behaves_like 'forbidden for wrong scope', 'read write'
+ it_behaves_like 'forbidden for wrong role', ''
+
+ it 'returns http success' do
+ subject
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'does not set the link as trendable' do
+ expect { subject }.to_not(change { preview_card.reload.trendable })
+ end
+
+ it 'returns the link data' do
+ subject
+
+ expect(body_as_json).to match(
+ a_hash_including(
+ url: preview_card.url,
+ title: preview_card.title,
+ description: preview_card.description,
+ type: 'link',
+ requires_review: false
+ )
+ )
+ end
+
+ context 'when the link does not exist' do
+ it 'returns http not found' do
+ post '/api/v1/admin/trends/links/-1/reject', headers: headers
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'without an authorization header' do
+ let(:headers) { {} }
+
+ it 'returns http forbidden' do
+ subject
+
+ expect(response).to have_http_status(403)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/v1/apps/credentials_spec.rb b/spec/requests/api/v1/apps/credentials_spec.rb
index dafe168c56..1268b36f8a 100644
--- a/spec/requests/api/v1/apps/credentials_spec.rb
+++ b/spec/requests/api/v1/apps/credentials_spec.rb
@@ -12,14 +12,10 @@ describe 'Credentials' do
let(:token) { Fabricate(:accessible_access_token, scopes: 'read', application: Fabricate(:application)) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
- it 'returns http success' do
+ it 'returns the app information correctly', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the app information correctly' do
- subject
expect(body_as_json).to match(
a_hash_including(
diff --git a/spec/requests/api/v1/apps_spec.rb b/spec/requests/api/v1/apps_spec.rb
index 88f9eee360..acabbc93f0 100644
--- a/spec/requests/api/v1/apps_spec.rb
+++ b/spec/requests/api/v1/apps_spec.rb
@@ -23,20 +23,11 @@ RSpec.describe 'Apps' do
end
context 'with valid params' do
- it 'returns http success' do
+ it 'creates an OAuth app', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'creates an OAuth app' do
- subject
-
expect(Doorkeeper::Application.find_by(name: client_name)).to be_present
- end
-
- it 'returns client ID and client secret' do
- subject
body = body_as_json
@@ -58,15 +49,10 @@ RSpec.describe 'Apps' do
context 'with many duplicate scopes' do
let(:scopes) { (%w(read) * 40).join(' ') }
- it 'returns http success' do
+ it 'only saves the scope once', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'only saves the scope once' do
- subject
-
expect(Doorkeeper::Application.find_by(name: client_name).scopes.to_s).to eq 'read'
end
end
diff --git a/spec/requests/api/v1/domain_blocks_spec.rb b/spec/requests/api/v1/domain_blocks_spec.rb
index 0f4fd4e90e..954497ebe1 100644
--- a/spec/requests/api/v1/domain_blocks_spec.rb
+++ b/spec/requests/api/v1/domain_blocks_spec.rb
@@ -22,15 +22,10 @@ RSpec.describe 'Domain blocks' do
it_behaves_like 'forbidden for wrong scope', 'write:blocks'
- it 'returns http success' do
+ it 'returns the domains blocked by the requesting user', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the domains blocked by the requesting user' do
- subject
-
expect(body_as_json).to match_array(blocked_domains)
end
@@ -54,15 +49,10 @@ RSpec.describe 'Domain blocks' do
it_behaves_like 'forbidden for wrong scope', 'read read:blocks'
- it 'returns http success' do
+ it 'creates a domain block', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'creates a domain block' do
- subject
-
expect(user.account.domain_blocking?(params[:domain])).to be(true)
end
@@ -100,15 +90,10 @@ RSpec.describe 'Domain blocks' do
it_behaves_like 'forbidden for wrong scope', 'read read:blocks'
- it 'returns http success' do
+ it 'deletes the specified domain block', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'deletes the specified domain block' do
- subject
-
expect(user.account.domain_blocking?('example.com')).to be(false)
end
diff --git a/spec/requests/api/v1/favourites_spec.rb b/spec/requests/api/v1/favourites_spec.rb
new file mode 100644
index 0000000000..713990592c
--- /dev/null
+++ b/spec/requests/api/v1/favourites_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Favourites' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'read:favourites' }
+ let(:headers) { { Authorization: "Bearer #{token.token}" } }
+
+ describe 'GET /api/v1/favourites' do
+ subject do
+ get '/api/v1/favourites', headers: headers, params: params
+ end
+
+ let(:params) { {} }
+ let!(:favourites) { Fabricate.times(3, :favourite, account: user.account) }
+
+ let(:expected_response) do
+ favourites.map do |favourite|
+ a_hash_including(id: favourite.status.id.to_s, account: a_hash_including(id: favourite.status.account.id.to_s))
+ end
+ end
+
+ it_behaves_like 'forbidden for wrong scope', 'write'
+
+ it 'returns http success' do
+ subject
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'returns the favourites' do
+ subject
+
+ expect(body_as_json).to match_array(expected_response)
+ end
+
+ context 'with limit param' do
+ let(:params) { { limit: 2 } }
+
+ it 'returns only the requested number of favourites' do
+ subject
+
+ expect(body_as_json.size).to eq(params[:limit])
+ end
+
+ it 'sets the correct pagination header for the prev path' do
+ subject
+
+ expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq(api_v1_favourites_url(limit: params[:limit], min_id: favourites.last.id))
+ end
+
+ it 'sets the correct pagination header for the next path' do
+ subject
+
+ expect(response.headers['Link'].find_link(%w(rel next)).href).to eq(api_v1_favourites_url(limit: params[:limit], max_id: favourites[1].id))
+ end
+ end
+
+ context 'without an authorization header' do
+ let(:headers) { {} }
+
+ it 'returns http unauthorized' do
+ subject
+
+ expect(response).to have_http_status(401)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/v1/follow_requests_spec.rb b/spec/requests/api/v1/follow_requests_spec.rb
index 9d4ef8cd55..1d78c9be19 100644
--- a/spec/requests/api/v1/follow_requests_spec.rb
+++ b/spec/requests/api/v1/follow_requests_spec.rb
@@ -32,15 +32,10 @@ RSpec.describe 'Follow requests' do
it_behaves_like 'forbidden for wrong scope', 'write write:follows'
- it 'returns http success' do
+ it 'returns the expected content from accounts requesting to follow', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the expected content from accounts requesting to follow' do
- subject
-
expect(body_as_json).to match_array(expected_response)
end
@@ -68,19 +63,9 @@ RSpec.describe 'Follow requests' do
it_behaves_like 'forbidden for wrong scope', 'read read:follows'
- it 'returns http success' do
- subject
-
- expect(response).to have_http_status(200)
- end
-
- it 'allows the requesting follower to follow' do
+ it 'allows the requesting follower to follow', :aggregate_failures do
expect { subject }.to change { follower.following?(user.account) }.from(false).to(true)
- end
-
- it 'returns JSON with followed_by set to true' do
- subject
-
+ expect(response).to have_http_status(200)
expect(body_as_json[:followed_by]).to be true
end
end
@@ -98,21 +83,11 @@ RSpec.describe 'Follow requests' do
it_behaves_like 'forbidden for wrong scope', 'read read:follows'
- it 'returns http success' do
+ it 'removes the follow request', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'removes the follow request' do
- subject
-
expect(FollowRequest.where(target_account: user.account, account: follower)).to_not exist
- end
-
- it 'returns JSON with followed_by set to false' do
- subject
-
expect(body_as_json[:followed_by]).to be false
end
end
diff --git a/spec/requests/api/v1/followed_tags_spec.rb b/spec/requests/api/v1/followed_tags_spec.rb
new file mode 100644
index 0000000000..9391c7bdc8
--- /dev/null
+++ b/spec/requests/api/v1/followed_tags_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Followed tags' do
+ let(:user) { Fabricate(:user) }
+ let(:scopes) { 'read:follows' }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+
+ describe 'GET /api/v1/followed_tags' do
+ subject do
+ get '/api/v1/followed_tags', headers: headers, params: params
+ end
+
+ let!(:tag_follows) { Fabricate.times(5, :tag_follow, account: user.account) }
+ let(:params) { {} }
+
+ let(:expected_response) do
+ tag_follows.map do |tag_follow|
+ a_hash_including(name: tag_follow.tag.name, following: true)
+ end
+ end
+
+ before do
+ Fabricate(:tag_follow)
+ end
+
+ it_behaves_like 'forbidden for wrong scope', 'write write:follows'
+
+ it 'returns http success' do
+ subject
+
+ expect(response).to have_http_status(:success)
+ end
+
+ it 'returns the followed tags correctly' do
+ subject
+
+ expect(body_as_json).to match_array(expected_response)
+ end
+
+ context 'with limit param' do
+ let(:params) { { limit: 3 } }
+
+ it 'returns only the requested number of follow tags' do
+ subject
+
+ expect(body_as_json.size).to eq(params[:limit])
+ end
+
+ it 'sets the correct pagination header for the prev path' do
+ subject
+
+ expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq(api_v1_followed_tags_url(limit: params[:limit], since_id: tag_follows.last.id))
+ end
+
+ it 'sets the correct pagination header for the next path' do
+ subject
+
+ expect(response.headers['Link'].find_link(%w(rel next)).href).to eq(api_v1_followed_tags_url(limit: params[:limit], max_id: tag_follows[2].id))
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/v1/lists_spec.rb b/spec/requests/api/v1/lists_spec.rb
index a970ddcd2f..a2466060c0 100644
--- a/spec/requests/api/v1/lists_spec.rb
+++ b/spec/requests/api/v1/lists_spec.rb
@@ -23,17 +23,6 @@ RSpec.describe 'Lists' do
end
let(:expected_response) do
- lists.map do |list|
- {
- id: list.id.to_s,
- title: list.title,
- replies_policy: list.replies_policy,
- exclusive: list.exclusive,
- }
- end
- end
-
- let(:expected_response_with_antennas) do
lists.map do |list|
{
id: list.id.to_s,
@@ -51,16 +40,11 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'write write:lists'
- it 'returns http success' do
+ it 'returns the expected lists', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the expected lists' do
- subject
-
- expect(body_as_json).to match_array(expected_response_with_antennas)
+ expect(body_as_json).to match_array(expected_response)
end
end
@@ -73,15 +57,10 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'write write:lists'
- it 'returns http success' do
+ it 'returns the requested list correctly', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the requested list correctly' do
- subject
-
expect(body_as_json).to eq({
id: list.id.to_s,
title: list.title,
@@ -119,21 +98,11 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'read read:lists'
- it 'returns http success' do
+ it 'returns the new list', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the new list' do
- subject
-
expect(body_as_json).to match(a_hash_including(title: 'my list', replies_policy: 'none', exclusive: true))
- end
-
- it 'creates a list' do
- subject
-
expect(List.where(account: user.account).count).to eq(1)
end
@@ -168,15 +137,10 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'read read:lists'
- it 'returns http success' do
+ it 'returns the updated list', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the updated list' do
- subject
-
list.reload
expect(body_as_json).to eq({
@@ -228,15 +192,10 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'read read:lists'
- it 'returns http success' do
+ it 'deletes the list', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'deletes the list' do
- subject
-
expect(List.where(id: list.id)).to_not exist
end
diff --git a/spec/requests/api/v1/reports_spec.rb b/spec/requests/api/v1/reports_spec.rb
new file mode 100644
index 0000000000..ba3d2b3060
--- /dev/null
+++ b/spec/requests/api/v1/reports_spec.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Reports' do
+ let(:user) { Fabricate(:user) }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:scopes) { 'write:reports' }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+
+ describe 'POST /api/v1/reports' do
+ subject do
+ post '/api/v1/reports', headers: headers, params: params
+ end
+
+ let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
+ let(:status) { Fabricate(:status) }
+ let(:target_account) { status.account }
+ let(:category) { 'other' }
+ let(:forward) { nil }
+ let(:rule_ids) { nil }
+
+ let(:params) do
+ {
+ status_ids: [status.id],
+ account_id: target_account.id,
+ comment: 'reasons',
+ category: category,
+ rule_ids: rule_ids,
+ forward: forward,
+ }
+ end
+
+ it_behaves_like 'forbidden for wrong scope', 'read read:reports'
+
+ it 'creates a report', :aggregate_failures do
+ perform_enqueued_jobs do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(body_as_json).to match(
+ a_hash_including(
+ status_ids: [status.id.to_s],
+ category: category,
+ comment: 'reasons'
+ )
+ )
+
+ expect(target_account.targeted_reports).to_not be_empty
+ expect(target_account.targeted_reports.first.comment).to eq 'reasons'
+
+ expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email])
+ end
+ end
+
+ context 'when a status does not belong to the reported account' do
+ let(:target_account) { Fabricate(:account) }
+
+ it 'returns http not found' do
+ subject
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when a category is chosen' do
+ let(:category) { 'spam' }
+
+ it 'saves category' do
+ subject
+
+ expect(target_account.targeted_reports.first.spam?).to be true
+ end
+ end
+
+ context 'when violated rules are chosen' do
+ let(:rule) { Fabricate(:rule) }
+ let(:category) { 'violation' }
+ let(:rule_ids) { [rule.id] }
+
+ it 'saves category and rule_ids' do
+ subject
+
+ expect(target_account.targeted_reports.first.violation?).to be true
+ expect(target_account.targeted_reports.first.rule_ids).to contain_exactly(rule.id)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/v1/statuses/sources_spec.rb b/spec/requests/api/v1/statuses/sources_spec.rb
new file mode 100644
index 0000000000..723b81905e
--- /dev/null
+++ b/spec/requests/api/v1/statuses/sources_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Sources' do
+ let(:user) { Fabricate(:user) }
+ let(:scopes) { 'read:statuses' }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+
+ describe 'GET /api/v1/statuses/:status_id/source' do
+ subject do
+ get "/api/v1/statuses/#{status.id}/source", headers: headers
+ end
+
+ let(:status) { Fabricate(:status) }
+
+ it_behaves_like 'forbidden for wrong scope', 'write write:statuses'
+
+ context 'with public status' do
+ it 'returns the source properties of the status', :aggregate_failures do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(body_as_json).to eq({
+ id: status.id.to_s,
+ text: status.text,
+ spoiler_text: status.spoiler_text,
+ })
+ end
+ end
+
+ context 'with private status of non-followed account' do
+ let(:status) { Fabricate(:status, visibility: :private) }
+
+ it 'returns http not found' do
+ subject
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'with private status of followed account' do
+ let(:status) { Fabricate(:status, visibility: :private) }
+
+ before do
+ user.account.follow!(status.account)
+ end
+
+ it 'returns the source properties of the status', :aggregate_failures do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(body_as_json).to eq({
+ id: status.id.to_s,
+ text: status.text,
+ spoiler_text: status.spoiler_text,
+ })
+ end
+ end
+
+ context 'without an authorization header' do
+ let(:headers) { {} }
+
+ it 'returns http unauthorized' do
+ subject
+
+ expect(response).to have_http_status(401)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/v1/tags_spec.rb b/spec/requests/api/v1/tags_spec.rb
index 300ddf805c..db74a6f037 100644
--- a/spec/requests/api/v1/tags_spec.rb
+++ b/spec/requests/api/v1/tags_spec.rb
@@ -17,15 +17,10 @@ RSpec.describe 'Tags' do
let!(:tag) { Fabricate(:tag) }
let(:name) { tag.name }
- it 'returns http success' do
+ it 'returns the tag', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'returns the tag' do
- subject
-
expect(body_as_json[:name]).to eq(name)
end
end
@@ -62,15 +57,10 @@ RSpec.describe 'Tags' do
it_behaves_like 'forbidden for wrong scope', 'read read:follows'
context 'when the tag exists' do
- it 'returns http success' do
+ it 'creates follow', :aggregate_failures do
subject
expect(response).to have_http_status(:success)
- end
-
- it 'creates follow' do
- subject
-
expect(TagFollow.where(tag: tag, account: user.account)).to exist
end
end
@@ -78,21 +68,11 @@ RSpec.describe 'Tags' do
context 'when the tag does not exist' do
let(:name) { 'hoge' }
- it 'returns http success' do
+ it 'creates a new tag with the specified name', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'creates a new tag with the specified name' do
- subject
-
expect(Tag.where(name: name)).to exist
- end
-
- it 'creates follow' do
- subject
-
expect(TagFollow.where(tag: Tag.find_by(name: name), account: user.account)).to exist
end
end
@@ -133,15 +113,10 @@ RSpec.describe 'Tags' do
it_behaves_like 'forbidden for wrong scope', 'read read:follows'
- it 'returns http success' do
+ it 'removes the follow', :aggregate_failures do
subject
expect(response).to have_http_status(200)
- end
-
- it 'removes the follow' do
- subject
-
expect(TagFollow.where(tag: tag, account: user.account)).to_not exist
end
diff --git a/spec/requests/api/v1/timelines/tag_spec.rb b/spec/requests/api/v1/timelines/tag_spec.rb
new file mode 100644
index 0000000000..a118af13e2
--- /dev/null
+++ b/spec/requests/api/v1/timelines/tag_spec.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Tag' do
+ let(:user) { Fabricate(:user) }
+ let(:scopes) { 'read:statuses' }
+ let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
+ let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
+
+ shared_examples 'a successful request to the tag timeline' do
+ it 'returns the expected statuses', :aggregate_failures do
+ subject
+
+ expect(response).to have_http_status(200)
+ expect(body_as_json.pluck(:id)).to match_array(expected_statuses.map { |status| status.id.to_s })
+ end
+ end
+
+ describe 'GET /api/v1/timelines/tag/:hashtag' do
+ subject do
+ get "/api/v1/timelines/tag/#{hashtag}", headers: headers, params: params
+ end
+
+ let(:account) { Fabricate(:account) }
+ let!(:private_status) { PostStatusService.new.call(account, visibility: :private, text: '#life could be a dream') } # rubocop:disable RSpec/LetSetup
+ let!(:life_status) { PostStatusService.new.call(account, text: 'tell me what is my #life without your #love') }
+ let!(:war_status) { PostStatusService.new.call(user.account, text: '#war, war never changes') }
+ let!(:love_status) { PostStatusService.new.call(account, text: 'what is #love?') }
+ let(:params) { {} }
+ let(:hashtag) { 'life' }
+
+ context 'when given only one hashtag' do
+ let(:expected_statuses) { [life_status] }
+
+ it_behaves_like 'a successful request to the tag timeline'
+ end
+
+ context 'with any param' do
+ let(:expected_statuses) { [life_status, love_status] }
+ let(:params) { { any: %(love) } }
+
+ it_behaves_like 'a successful request to the tag timeline'
+ end
+
+ context 'with all param' do
+ let(:expected_statuses) { [life_status] }
+ let(:params) { { all: %w(love) } }
+
+ it_behaves_like 'a successful request to the tag timeline'
+ end
+
+ context 'with none param' do
+ let(:expected_statuses) { [war_status] }
+ let(:hashtag) { 'war' }
+ let(:params) { { none: %w(life love) } }
+
+ it_behaves_like 'a successful request to the tag timeline'
+ end
+
+ context 'with limit param' do
+ let(:hashtag) { 'love' }
+ let(:params) { { limit: 1 } }
+
+ it 'returns only the requested number of statuses' do
+ subject
+
+ expect(body_as_json.size).to eq(params[:limit])
+ end
+
+ it 'sets the correct pagination headers', :aggregate_failures do
+ subject
+
+ headers = response.headers['Link']
+
+ expect(headers.find_link(%w(rel prev)).href).to eq(api_v1_timelines_tag_url(limit: 1, min_id: love_status.id.to_s))
+ expect(headers.find_link(%w(rel next)).href).to eq(api_v1_timelines_tag_url(limit: 1, max_id: love_status.id.to_s))
+ end
+ end
+
+ context 'when the instance allows public preview' do
+ context 'when the user is not authenticated' do
+ let(:headers) { {} }
+ let(:expected_statuses) { [life_status] }
+
+ it_behaves_like 'a successful request to the tag timeline'
+ end
+ end
+
+ context 'when the instance does not allow public preview' do
+ before do
+ Form::AdminSettings.new(timeline_preview: false).save
+ end
+
+ context 'when the user is not authenticated' do
+ let(:headers) { {} }
+
+ it 'returns http unauthorized' do
+ subject
+
+ expect(response).to have_http_status(401)
+ end
+ end
+
+ context 'when the user is authenticated' do
+ let(:expected_statuses) { [life_status] }
+
+ it_behaves_like 'a successful request to the tag timeline'
+ end
+ end
+ end
+end
diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb
index 529ab09969..f63829f234 100644
--- a/spec/services/post_status_service_spec.rb
+++ b/spec/services/post_status_service_spec.rb
@@ -209,6 +209,17 @@ RSpec.describe PostStatusService, type: :service do
expect(status.mentioned_accounts.first.id).to eq mutual_account.id
end
+ it 'limited visibility and direct searchability' do
+ account = Fabricate(:account)
+ text = 'This is an English text.'
+
+ status = subject.call(account, text: text, visibility: 'mutual', searchability: 'public')
+
+ expect(status.visibility).to eq 'limited'
+ expect(status.limited_scope).to eq 'personal'
+ expect(status.searchability).to eq 'direct'
+ end
+
it 'personal visibility with mutual' do
account = Fabricate(:account)
text = 'This is an English text.'
diff --git a/spec/support/signed_request_helpers.rb b/spec/support/signed_request_helpers.rb
new file mode 100644
index 0000000000..33d7dba6b8
--- /dev/null
+++ b/spec/support/signed_request_helpers.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module SignedRequestHelpers
+ def get(path, headers: nil, sign_with: nil, **args)
+ return super path, headers: headers, **args if sign_with.nil?
+
+ headers ||= {}
+ headers['Date'] = Time.now.utc.httpdate
+ headers['Host'] = ENV.fetch('LOCAL_DOMAIN')
+ signed_headers = headers.merge('(request-target)' => "get #{path}").slice('(request-target)', 'Host', 'Date')
+
+ key_id = ActivityPub::TagManager.instance.key_uri_for(sign_with)
+ keypair = sign_with.keypair
+ signed_string = signed_headers.map { |key, value| "#{key.downcase}: #{value}" }.join("\n")
+ signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string))
+
+ headers['Signature'] = "keyId=\"#{key_id}\",algorithm=\"rsa-sha256\",headers=\"#{signed_headers.keys.join(' ').downcase}\",signature=\"#{signature}\""
+
+ super path, headers: headers, **args
+ end
+end
diff --git a/spec/workers/move_worker_spec.rb b/spec/workers/move_worker_spec.rb
index 7577f6e896..efad92c047 100644
--- a/spec/workers/move_worker_spec.rb
+++ b/spec/workers/move_worker_spec.rb
@@ -67,39 +67,31 @@ describe MoveWorker do
end
shared_examples 'block and mute handling' do
- it 'makes blocks carry over and add a note' do
+ it 'makes blocks and mutes carry over and adds a note' do
subject.perform(source_account.id, target_account.id)
+
expect(block_service).to have_received(:call).with(blocking_account, target_account)
expect(AccountNote.find_by(account: blocking_account, target_account: target_account).comment).to include(source_account.acct)
- end
- it 'makes mutes carry over and add a note' do
- subject.perform(source_account.id, target_account.id)
expect(muting_account.muting?(target_account)).to be true
expect(AccountNote.find_by(account: muting_account, target_account: target_account).comment).to include(source_account.acct)
end
end
shared_examples 'followers count handling' do
- it 'updates the source account followers count' do
+ it 'updates the source and target account followers counts' do
subject.perform(source_account.id, target_account.id)
- expect(source_account.reload.followers_count).to eq(source_account.passive_relationships.count)
- end
- it 'updates the target account followers count' do
- subject.perform(source_account.id, target_account.id)
+ expect(source_account.reload.followers_count).to eq(source_account.passive_relationships.count)
expect(target_account.reload.followers_count).to eq(target_account.passive_relationships.count)
end
end
shared_examples 'lists handling' do
- it 'puts the new account on the list' do
+ it 'puts the new account on the list and makes valid lists', sidekiq: :inline do
subject.perform(source_account.id, target_account.id)
- expect(list.accounts.include?(target_account)).to be true
- end
- it 'does not create invalid list memberships' do
- subject.perform(source_account.id, target_account.id)
+ expect(list.accounts.include?(target_account)).to be true
expect(ListAccount.all).to all be_valid
end
end
diff --git a/streaming/index.js b/streaming/index.js
index c1569b1fb7..b02fedfccc 100644
--- a/streaming/index.js
+++ b/streaming/index.js
@@ -256,7 +256,7 @@ const startServer = async () => {
CHANNEL_NAMES.forEach(( channel ) => {
connectedChannels.set({ type: 'websocket', channel }, 0);
connectedChannels.set({ type: 'eventsource', channel }, 0);
- })
+ });
// Prime the counters so that we don't loose metrics between restarts.
// Unfortunately counters don't support the set() API, so instead I'm using
@@ -1363,7 +1363,7 @@ const startServer = async () => {
log.verbose(request.requestId, 'Subscription error:', err.toString());
socket.send(JSON.stringify({ error: err.toString() }));
});
- }
+ };
const removeSubscription = (subscriptions, channelIds, request) => {
@@ -1383,7 +1383,7 @@ const startServer = async () => {
subscription.stopHeartbeat();
delete subscriptions[channelIds.join(';')];
- }
+ };
/**
* @param {WebSocketSession} session
@@ -1403,7 +1403,7 @@ const startServer = async () => {
socket.send(JSON.stringify({ error: "Error unsubscribing from channel" }));
}
});
- }
+ };
/**
* @param {WebSocketSession} session
@@ -1481,7 +1481,7 @@ const startServer = async () => {
const subscriptions = Object.keys(session.subscriptions);
subscriptions.forEach(channelIds => {
- removeSubscription(session.subscriptions, channelIds.split(';'), req)
+ removeSubscription(session.subscriptions, channelIds.split(';'), req);
});
// Decrement the metrics for connected clients:
diff --git a/yarn.lock b/yarn.lock
index 80f1d7b76e..71c06628c7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1305,15 +1305,10 @@
dependencies:
eslint-visitor-keys "^3.3.0"
-"@eslint-community/regexpp@^4.5.1":
- version "4.9.0"
- resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.0.tgz#7ccb5f58703fa61ffdcbf39e2c604a109e781162"
- integrity sha512-zJmuCWj2VLBt4c25CfBIbMZLGLyhkvs7LznyVX5HfpzeocThgIj5XQK4L+g3U36mMcx8bPMhGyPpwCATamC4jQ==
-
-"@eslint-community/regexpp@^4.6.1":
- version "4.8.1"
- resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.8.1.tgz#8c4bb756cc2aa7eaf13cfa5e69c83afb3260c20c"
- integrity sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==
+"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1":
+ version "4.9.1"
+ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4"
+ integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==
"@eslint/eslintrc@^2.1.2":
version "2.1.2"
@@ -1330,10 +1325,10 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
-"@eslint/js@8.50.0":
- version "8.50.0"
- resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.50.0.tgz#9e93b850f0f3fa35f5fa59adfd03adae8488e484"
- integrity sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==
+"@eslint/js@8.51.0":
+ version "8.51.0"
+ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.51.0.tgz#6d419c240cfb2b66da37df230f7e7eef801c32fa"
+ integrity sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==
"@floating-ui/core@^1.3.1":
version "1.3.1"
@@ -2399,9 +2394,9 @@
integrity sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==
"@types/react-dom@^18.0.0", "@types/react-dom@^18.2.4":
- version "18.2.8"
- resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.8.tgz#338f1b0a646c9f10e0a97208c1d26b9f473dffd6"
- integrity sha512-bAIvO5lN/U8sPGvs1Xm61rlRHHaq5rp5N3kp9C+NJ/Q41P8iqjkXSu0+/qu8POsjH9pNWb0OYabFez7taP7omw==
+ version "18.2.11"
+ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.11.tgz#4332c315544698a0875dfdb6e320dda59e1b3d58"
+ integrity sha512-zq6Dy0EiCuF9pWFW6I6k6W2LdpUixLE4P6XjXU1QHLfak3GPACQfLwEuHzY5pOYa4hzj1d0GxX/P141aFjZsyg==
dependencies:
"@types/react" "*"
@@ -2501,9 +2496,9 @@
"@types/react" "*"
"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@>=16.9.11", "@types/react@^18.0.26", "@types/react@^18.2.7":
- version "18.2.24"
- resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.24.tgz#3c7d68c02e0205a472f04abe4a0c1df35d995c05"
- integrity sha512-Ee0Jt4sbJxMu1iDcetZEIKQr99J1Zfb6D4F3qfUWoR1JpInkY1Wdg4WwCyBjL257D0+jGqSl1twBjV8iCaC0Aw==
+ version "18.2.25"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.25.tgz#99fa44154132979e870ff409dc5b6e67f06f0199"
+ integrity sha512-24xqse6+VByVLIr+xWaQ9muX1B4bXJKXBbjszbld/UEDslGLY53+ZucF44HCmLbMPejTzGG9XgR+3m2/Wqu1kw==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
@@ -2594,14 +2589,14 @@
integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
"@types/uuid@^9.0.0":
- version "9.0.4"
- resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.4.tgz#e884a59338da907bda8d2ed03e01c5c49d036f1c"
- integrity sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA==
+ version "9.0.5"
+ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.5.tgz#25a71eb73eba95ac0e559ff3dd018fc08294acf6"
+ integrity sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==
"@types/warning@^3.0.0":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52"
- integrity sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.1.tgz#a62d1d2b7f34376da84ee0afe0145152e62b9699"
+ integrity sha512-ywJmriP+nvjBKNBEMaNZgj2irZHoxcKeYcyMLbqhYKbDVn8yCIULy2Ol/tvIb37O3IBeZj3RU4tXqQTtGwoAMg==
"@types/webpack-sources@*":
version "3.2.1"
@@ -2630,22 +2625,22 @@
integrity sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==
"@types/yargs@^17.0.24", "@types/yargs@^17.0.8":
- version "17.0.26"
- resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.26.tgz#388e5002a8b284ad7b4599ba89920a6d74d8d79a"
- integrity sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==
+ version "17.0.28"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.28.tgz#d106e4301fbacde3d1796ab27374dd16588ec851"
+ integrity sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==
dependencies:
"@types/yargs-parser" "*"
"@typescript-eslint/eslint-plugin@^6.0.0":
- version "6.7.3"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.3.tgz#d98046e9f7102d49a93d944d413c6055c47fafd7"
- integrity sha512-vntq452UHNltxsaaN+L9WyuMch8bMd9CqJ3zhzTPXXidwbf5mqqKCVXEuvRZUqLJSTLeWE65lQwyXsRGnXkCTA==
+ version "6.7.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.4.tgz#057338df21b6062c2f2fc5999fbea8af9973ac6d"
+ integrity sha512-DAbgDXwtX+pDkAHwiGhqP3zWUGpW49B7eqmgpPtg+BKJXwdct79ut9+ifqOFPJGClGKSHXn2PTBatCnldJRUoA==
dependencies:
"@eslint-community/regexpp" "^4.5.1"
- "@typescript-eslint/scope-manager" "6.7.3"
- "@typescript-eslint/type-utils" "6.7.3"
- "@typescript-eslint/utils" "6.7.3"
- "@typescript-eslint/visitor-keys" "6.7.3"
+ "@typescript-eslint/scope-manager" "6.7.4"
+ "@typescript-eslint/type-utils" "6.7.4"
+ "@typescript-eslint/utils" "6.7.4"
+ "@typescript-eslint/visitor-keys" "6.7.4"
debug "^4.3.4"
graphemer "^1.4.0"
ignore "^5.2.4"
@@ -2654,31 +2649,31 @@
ts-api-utils "^1.0.1"
"@typescript-eslint/parser@^6.0.0":
- version "6.7.3"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.7.3.tgz#aaf40092a32877439e5957e18f2d6a91c82cc2fd"
- integrity sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ==
+ version "6.7.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.7.4.tgz#23d1dd4fe5d295c7fa2ab651f5406cd9ad0bd435"
+ integrity sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA==
dependencies:
- "@typescript-eslint/scope-manager" "6.7.3"
- "@typescript-eslint/types" "6.7.3"
- "@typescript-eslint/typescript-estree" "6.7.3"
- "@typescript-eslint/visitor-keys" "6.7.3"
+ "@typescript-eslint/scope-manager" "6.7.4"
+ "@typescript-eslint/types" "6.7.4"
+ "@typescript-eslint/typescript-estree" "6.7.4"
+ "@typescript-eslint/visitor-keys" "6.7.4"
debug "^4.3.4"
-"@typescript-eslint/scope-manager@6.7.3":
- version "6.7.3"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.7.3.tgz#07e5709c9bdae3eaf216947433ef97b3b8b7d755"
- integrity sha512-wOlo0QnEou9cHO2TdkJmzF7DFGvAKEnB82PuPNHpT8ZKKaZu6Bm63ugOTn9fXNJtvuDPanBc78lGUGGytJoVzQ==
+"@typescript-eslint/scope-manager@6.7.4":
+ version "6.7.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.7.4.tgz#a484a17aa219e96044db40813429eb7214d7b386"
+ integrity sha512-SdGqSLUPTXAXi7c3Ob7peAGVnmMoGzZ361VswK2Mqf8UOYcODiYvs8rs5ILqEdfvX1lE7wEZbLyELCW+Yrql1A==
dependencies:
- "@typescript-eslint/types" "6.7.3"
- "@typescript-eslint/visitor-keys" "6.7.3"
+ "@typescript-eslint/types" "6.7.4"
+ "@typescript-eslint/visitor-keys" "6.7.4"
-"@typescript-eslint/type-utils@6.7.3":
- version "6.7.3"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.7.3.tgz#c2c165c135dda68a5e70074ade183f5ad68f3400"
- integrity sha512-Fc68K0aTDrKIBvLnKTZ5Pf3MXK495YErrbHb1R6aTpfK5OdSFj0rVN7ib6Tx6ePrZ2gsjLqr0s98NG7l96KSQw==
+"@typescript-eslint/type-utils@6.7.4":
+ version "6.7.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.7.4.tgz#847cd3b59baf948984499be3e0a12ff07373e321"
+ integrity sha512-n+g3zi1QzpcAdHFP9KQF+rEFxMb2KxtnJGID3teA/nxKHOVi3ylKovaqEzGBbVY2pBttU6z85gp0D00ufLzViQ==
dependencies:
- "@typescript-eslint/typescript-estree" "6.7.3"
- "@typescript-eslint/utils" "6.7.3"
+ "@typescript-eslint/typescript-estree" "6.7.4"
+ "@typescript-eslint/utils" "6.7.4"
debug "^4.3.4"
ts-api-utils "^1.0.1"
@@ -2687,10 +2682,10 @@
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f"
integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==
-"@typescript-eslint/types@6.7.3":
- version "6.7.3"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.7.3.tgz#0402b5628a63f24f2dc9d4a678e9a92cc50ea3e9"
- integrity sha512-4g+de6roB2NFcfkZb439tigpAMnvEIg3rIjWQ+EM7IBaYt/CdJt6em9BJ4h4UpdgaBWdmx2iWsafHTrqmgIPNw==
+"@typescript-eslint/types@6.7.4":
+ version "6.7.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.7.4.tgz#5d358484d2be986980c039de68e9f1eb62ea7897"
+ integrity sha512-o9XWK2FLW6eSS/0r/tgjAGsYasLAnOWg7hvZ/dGYSSNjCh+49k5ocPN8OmG5aZcSJ8pclSOyVKP2x03Sj+RrCA==
"@typescript-eslint/typescript-estree@5.62.0":
version "5.62.0"
@@ -2705,30 +2700,30 @@
semver "^7.3.7"
tsutils "^3.21.0"
-"@typescript-eslint/typescript-estree@6.7.3":
- version "6.7.3"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.3.tgz#ec5bb7ab4d3566818abaf0e4a8fa1958561b7279"
- integrity sha512-YLQ3tJoS4VxLFYHTw21oe1/vIZPRqAO91z6Uv0Ss2BKm/Ag7/RVQBcXTGcXhgJMdA4U+HrKuY5gWlJlvoaKZ5g==
+"@typescript-eslint/typescript-estree@6.7.4":
+ version "6.7.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.4.tgz#f2baece09f7bb1df9296e32638b2e1130014ef1a"
+ integrity sha512-ty8b5qHKatlNYd9vmpHooQz3Vki3gG+3PchmtsA4TgrZBKWHNjWfkQid7K7xQogBqqc7/BhGazxMD5vr6Ha+iQ==
dependencies:
- "@typescript-eslint/types" "6.7.3"
- "@typescript-eslint/visitor-keys" "6.7.3"
+ "@typescript-eslint/types" "6.7.4"
+ "@typescript-eslint/visitor-keys" "6.7.4"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.5.4"
ts-api-utils "^1.0.1"
-"@typescript-eslint/utils@6.7.3":
- version "6.7.3"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.7.3.tgz#96c655816c373135b07282d67407cb577f62e143"
- integrity sha512-vzLkVder21GpWRrmSR9JxGZ5+ibIUSudXlW52qeKpzUEQhRSmyZiVDDj3crAth7+5tmN1ulvgKaCU2f/bPRCzg==
+"@typescript-eslint/utils@6.7.4":
+ version "6.7.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.7.4.tgz#2236f72b10e38277ee05ef06142522e1de470ff2"
+ integrity sha512-PRQAs+HUn85Qdk+khAxsVV+oULy3VkbH3hQ8hxLRJXWBEd7iI+GbQxH5SEUSH7kbEoTp6oT1bOwyga24ELALTA==
dependencies:
"@eslint-community/eslint-utils" "^4.4.0"
"@types/json-schema" "^7.0.12"
"@types/semver" "^7.5.0"
- "@typescript-eslint/scope-manager" "6.7.3"
- "@typescript-eslint/types" "6.7.3"
- "@typescript-eslint/typescript-estree" "6.7.3"
+ "@typescript-eslint/scope-manager" "6.7.4"
+ "@typescript-eslint/types" "6.7.4"
+ "@typescript-eslint/typescript-estree" "6.7.4"
semver "^7.5.4"
"@typescript-eslint/visitor-keys@5.62.0":
@@ -2739,12 +2734,12 @@
"@typescript-eslint/types" "5.62.0"
eslint-visitor-keys "^3.3.0"
-"@typescript-eslint/visitor-keys@6.7.3":
- version "6.7.3"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.3.tgz#83809631ca12909bd2083558d2f93f5747deebb2"
- integrity sha512-HEVXkU9IB+nk9o63CeICMHxFWbHWr3E1mpilIQBe9+7L/lH97rleFLVtYsfnWB+JVMaiFnEaxvknvmIzX+CqVg==
+"@typescript-eslint/visitor-keys@6.7.4":
+ version "6.7.4"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.4.tgz#80dfecf820fc67574012375859085f91a4dff043"
+ integrity sha512-pOW37DUhlTZbvph50x5zZCkFn3xzwkGtNoJHzIM3svpiSkJzwOYr/kVBaXmf+RAQiUDs1AHEZVNPg6UJCJpwRA==
dependencies:
- "@typescript-eslint/types" "6.7.3"
+ "@typescript-eslint/types" "6.7.4"
eslint-visitor-keys "^3.4.1"
"@webassemblyjs/ast@1.9.0":
@@ -5548,14 +5543,14 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
eslint@^8.41.0:
- version "8.50.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.50.0.tgz#2ae6015fee0240fcd3f83e1e25df0287f487d6b2"
- integrity sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==
+ version "8.51.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.51.0.tgz#4a82dae60d209ac89a5cff1604fea978ba4950f3"
+ integrity sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==
dependencies:
"@eslint-community/eslint-utils" "^4.2.0"
"@eslint-community/regexpp" "^4.6.1"
"@eslint/eslintrc" "^2.1.2"
- "@eslint/js" "8.50.0"
+ "@eslint/js" "8.51.0"
"@humanwhocodes/config-array" "^0.11.11"
"@humanwhocodes/module-importer" "^1.0.1"
"@nodelib/fs.walk" "^1.2.8"
@@ -6021,15 +6016,15 @@ findup-sync@^3.0.0:
resolve-dir "^1.0.1"
flat-cache@^3.0.4:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.0.tgz#0e54ab4a1a60fe87e2946b6b00657f1c99e1af3f"
- integrity sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.1.tgz#a02a15fdec25a8f844ff7cc658f03dd99eb4609b"
+ integrity sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==
dependencies:
- flatted "^3.2.7"
+ flatted "^3.2.9"
keyv "^4.5.3"
rimraf "^3.0.2"
-flatted@^3.2.7:
+flatted@^3.2.9:
version "3.2.9"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf"
integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
@@ -6328,9 +6323,9 @@ globals@^11.1.0:
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
globals@^13.19.0:
- version "13.22.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-13.22.0.tgz#0c9fcb9c48a2494fbb5edbfee644285543eba9d8"
- integrity sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==
+ version "13.23.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.23.0.tgz#ef31673c926a0976e1f61dab4dca57e0c0a8af02"
+ integrity sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==
dependencies:
type-fest "^0.20.2"
@@ -8039,9 +8034,9 @@ keycode@^2.1.7:
integrity sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==
keyv@^4.5.3:
- version "4.5.3"
- resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25"
- integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
+ integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
dependencies:
json-buffer "3.0.1"
@@ -11503,7 +11498,6 @@ stringz@^2.1.0:
char-regex "^1.0.2"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
- name strip-ansi-cjs
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==