Merge remote-tracking branch 'parent/main' into kb-upstream-20231014

This commit is contained in:
KMY 2023-10-14 08:18:57 +09:00
commit 60195928e1
76 changed files with 1282 additions and 1205 deletions

View file

@ -180,7 +180,6 @@ RSpec/LetSetup:
- 'spec/controllers/api/v1/accounts/statuses_controller_spec.rb' - 'spec/controllers/api/v1/accounts/statuses_controller_spec.rb'
- 'spec/controllers/api/v1/admin/accounts_controller_spec.rb' - 'spec/controllers/api/v1/admin/accounts_controller_spec.rb'
- 'spec/controllers/api/v1/filters_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/admin/accounts_controller_spec.rb'
- 'spec/controllers/api/v2/filters/keywords_controller_spec.rb' - 'spec/controllers/api/v2/filters/keywords_controller_spec.rb'
- 'spec/controllers/api/v2/filters/statuses_controller_spec.rb' - 'spec/controllers/api/v2/filters/statuses_controller_spec.rb'

View file

@ -216,11 +216,11 @@ GEM
railties (>= 4.1.0) railties (>= 4.1.0)
responders responders
warden (~> 1.2.3) warden (~> 1.2.3)
devise-two-factor (4.1.0) devise-two-factor (4.1.1)
activesupport (< 7.1) activesupport (~> 7.0)
attr_encrypted (>= 1.3, < 5, != 2) attr_encrypted (>= 1.3, < 5, != 2)
devise (~> 4.0) devise (~> 4.0)
railties (< 7.1) railties (~> 7.0)
rotp (~> 6.0) rotp (~> 6.0)
devise_pam_authenticatable2 (9.2.0) devise_pam_authenticatable2 (9.2.0)
devise (>= 4.0.0) devise (>= 4.0.0)
@ -622,7 +622,7 @@ GEM
sidekiq (>= 5, < 8) sidekiq (>= 5, < 8)
rspec-support (3.12.1) rspec-support (3.12.1)
rspec_chunked (0.6) rspec_chunked (0.6)
rubocop (1.57.0) rubocop (1.57.1)
base64 (~> 0.1.1) base64 (~> 0.1.1)
json (~> 2.3) json (~> 2.3)
language_server-protocol (>= 3.17.0) language_server-protocol (>= 3.17.0)

View file

@ -26,10 +26,10 @@
"account.domain_blocked": "Verkkotunnus estetty", "account.domain_blocked": "Verkkotunnus estetty",
"account.edit_profile": "Muokkaa profiilia", "account.edit_profile": "Muokkaa profiilia",
"account.enable_notifications": "Ilmoita minulle, kun @{name} julkaisee", "account.enable_notifications": "Ilmoita minulle, kun @{name} julkaisee",
"account.endorse": "Suosittele profiilissasi", "account.endorse": "Pidä esillä profiilissa",
"account.featured_tags.last_status_at": "Viimeisin julkaisu {date}", "account.featured_tags.last_status_at": "Viimeisin julkaisu {date}",
"account.featured_tags.last_status_never": "Ei julkaisuja", "account.featured_tags.last_status_never": "Ei julkaisuja",
"account.featured_tags.title": "Käyttäjän {name} esille nostetut aihetunnisteet", "account.featured_tags.title": "Käyttäjän {name} esillä pidettävät aihetunnisteet",
"account.follow": "Seuraa", "account.follow": "Seuraa",
"account.followers": "Seuraajat", "account.followers": "Seuraajat",
"account.followers.empty": "Kukaan ei seuraa tätä käyttäjää vielä.", "account.followers.empty": "Kukaan ei seuraa tätä käyttäjää vielä.",
@ -62,10 +62,10 @@
"account.share": "Jaa käyttäjän @{name} profiili", "account.share": "Jaa käyttäjän @{name} profiili",
"account.show_reblogs": "Näytä käyttäjän @{name} tehostukset", "account.show_reblogs": "Näytä käyttäjän @{name} tehostukset",
"account.statuses_counter": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}", "account.statuses_counter": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}",
"account.unblock": "Poista esto: @{name}", "account.unblock": "Poista käyttäjän @{name} esto",
"account.unblock_domain": "Salli palvelu {domain}", "account.unblock_domain": "Poista verkkotunnuksen {domain} esto",
"account.unblock_short": "Poista esto", "account.unblock_short": "Poista esto",
"account.unendorse": "Poista suosittelu profiilistasi", "account.unendorse": "Älä pidä esillä profiilissa",
"account.unfollow": "Lopeta seuraaminen", "account.unfollow": "Lopeta seuraaminen",
"account.unmute": "Poista käyttäjän @{name} mykistys", "account.unmute": "Poista käyttäjän @{name} mykistys",
"account.unmute_notifications_short": "Poista ilmoitusten mykistys", "account.unmute_notifications_short": "Poista ilmoitusten mykistys",
@ -225,12 +225,12 @@
"empty_column.account_suspended": "Tili jäädytetty", "empty_column.account_suspended": "Tili jäädytetty",
"empty_column.account_timeline": "Ei viestejä täällä.", "empty_column.account_timeline": "Ei viestejä täällä.",
"empty_column.account_unavailable": "Profiilia ei löydy", "empty_column.account_unavailable": "Profiilia ei löydy",
"empty_column.blocks": "Et ole estänyt käyttäjiä.", "empty_column.blocks": "Et ole vielä estänyt käyttäjiä.",
"empty_column.bookmarked_statuses": "Et ole vielä lisännyt julkaisuja kirjanmerkkeihisi. Kun lisäät yhden, se näkyy tässä.", "empty_column.bookmarked_statuses": "Et ole vielä lisännyt julkaisuja kirjanmerkkeihisi. Kun lisäät yhden, se näkyy tässä.",
"empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista, niin homma lähtee käyntiin!", "empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista, niin homma lähtee käyntiin!",
"empty_column.direct": "Yksityisiä mainintoja ei vielä ole. Jos lähetät tai sinulle lähetetään sellaisia, näet ne täällä.", "empty_column.direct": "Yksityisiä mainintoja ei vielä ole. Jos lähetät tai sinulle lähetetään sellaisia, näet ne täällä.",
"empty_column.domain_blocks": "Palveluita ei ole vielä estetty.", "empty_column.domain_blocks": "Verkkotunnuksia ei ole vielä estetty.",
"empty_column.explore_statuses": "Mikään ei trendaa nyt. Tarkista myöhemmin uudelleen!", "empty_column.explore_statuses": "Mikään ei ole nyt suosittua. Tarkista myöhemmin uudelleen!",
"empty_column.favourited_statuses": "Sinulla ei ole vielä yhtään suosikkijulkaisua. Kun lisäät sellaisen, näkyy se tässä.", "empty_column.favourited_statuses": "Sinulla ei ole vielä yhtään suosikkijulkaisua. Kun lisäät sellaisen, näkyy se tässä.",
"empty_column.favourites": "Kukaan ei ole vielä lisännyt tätä julkaisua suosikkeihinsa. Kun joku tekee niin, tulee hän tähän näkyviin.", "empty_column.favourites": "Kukaan ei ole vielä lisännyt tätä julkaisua suosikkeihinsa. Kun joku tekee niin, tulee hän tähän näkyviin.",
"empty_column.follow_requests": "Et ole vielä vastaanottanut seuraamispyyntöjä. Saamasi pyynnöt näkyvät täällä.", "empty_column.follow_requests": "Et ole vielä vastaanottanut seuraamispyyntöjä. Saamasi pyynnöt näkyvät täällä.",
@ -414,7 +414,7 @@
"navigation_bar.lists": "Listat", "navigation_bar.lists": "Listat",
"navigation_bar.logout": "Kirjaudu ulos", "navigation_bar.logout": "Kirjaudu ulos",
"navigation_bar.mutes": "Mykistetyt käyttäjät", "navigation_bar.mutes": "Mykistetyt käyttäjät",
"navigation_bar.opened_in_classic_interface": "Julkaisut, profiilit ja tietyt muut sivut avautuvat oletuksena perinteiseen web-käyttöliittymään.", "navigation_bar.opened_in_classic_interface": "Julkaisut, profiilit ja tietyt muut sivut avautuvat oletuksena perinteiseen selainkäyttöliittymään.",
"navigation_bar.personal": "Henkilökohtainen", "navigation_bar.personal": "Henkilökohtainen",
"navigation_bar.pins": "Kiinnitetyt julkaisut", "navigation_bar.pins": "Kiinnitetyt julkaisut",
"navigation_bar.preferences": "Asetukset", "navigation_bar.preferences": "Asetukset",
@ -472,7 +472,7 @@
"notifications_permission_banner.title": "Älä anna minkään mennä ohi", "notifications_permission_banner.title": "Älä anna minkään mennä ohi",
"onboarding.action.back": "Palaa takaisin", "onboarding.action.back": "Palaa takaisin",
"onboarding.actions.back": "Palaa takaisin", "onboarding.actions.back": "Palaa takaisin",
"onboarding.actions.go_to_explore": "Siirry suosituimpien aiheiden syötteeseen", "onboarding.actions.go_to_explore": "Siirry suosittujen aiheiden syötteeseen",
"onboarding.actions.go_to_home": "Siirry kotisyötteeseeni", "onboarding.actions.go_to_home": "Siirry kotisyötteeseeni",
"onboarding.compose.template": "Tervehdys #Mastodon!", "onboarding.compose.template": "Tervehdys #Mastodon!",
"onboarding.follows.empty": "Valitettavasti tuloksia ei voida näyttää juuri nyt. Voit kokeilla hakua tai selata tutustumissivua löytääksesi seurattavaa tai yrittää myöhemmin uudelleen.", "onboarding.follows.empty": "Valitettavasti tuloksia ei voida näyttää juuri nyt. Voit kokeilla hakua tai selata tutustumissivua löytääksesi seurattavaa tai yrittää myöhemmin uudelleen.",
@ -537,7 +537,7 @@
"relative_time.today": "tänään", "relative_time.today": "tänään",
"reply_indicator.cancel": "Peruuta", "reply_indicator.cancel": "Peruuta",
"report.block": "Estä", "report.block": "Estä",
"report.block_explanation": "Et näe hänen viestejään, eikä hän voi nähdä viestejäsi tai seurata sinua. Hän näkevät, että olet estänyt hänet.", "report.block_explanation": "Et näe hänen viestejään, eikä hän voi nähdä viestejäsi tai seurata sinua. Hän näkee, että olet estänyt hänet.",
"report.categories.legal": "Lakiasiat", "report.categories.legal": "Lakiasiat",
"report.categories.other": "Muu", "report.categories.other": "Muu",
"report.categories.spam": "Roskaposti", "report.categories.spam": "Roskaposti",
@ -694,7 +694,7 @@
"units.short.thousand": "{count} t.", "units.short.thousand": "{count} t.",
"upload_area.title": "Lataa raahaamalla ja pudottamalla tähän", "upload_area.title": "Lataa raahaamalla ja pudottamalla tähän",
"upload_button.label": "Lisää kuvia, video tai äänitiedosto", "upload_button.label": "Lisää kuvia, video tai äänitiedosto",
"upload_error.limit": "Tiedostolatauksien raja ylitetty.", "upload_error.limit": "Tiedostolatauksien rajoitus ylitetty.",
"upload_error.poll": "Tiedoston lataaminen ei ole sallittua äänestyksissä.", "upload_error.poll": "Tiedoston lataaminen ei ole sallittua äänestyksissä.",
"upload_form.audio_description": "Kuvaile sisältöä kuuroille ja kuulorajoitteisille", "upload_form.audio_description": "Kuvaile sisältöä kuuroille ja kuulorajoitteisille",
"upload_form.description": "Kuvaile sisältöä sokeille ja näkörajoitteisille", "upload_form.description": "Kuvaile sisältöä sokeille ja näkörajoitteisille",

View file

@ -207,6 +207,7 @@ class FeedManager
# also tagged with another followed hashtag or from a followed user # also tagged with another followed hashtag or from a followed user
scope = from_tag.statuses scope = from_tag.statuses
.where(id: timeline_status_ids) .where(id: timeline_status_ids)
.where.not(account: into_account)
.where.not(account: into_account.following) .where.not(account: into_account.following)
.tagged_with_none(TagFollow.where(account: into_account).pluck(:tag_id)) .tagged_with_none(TagFollow.where(account: into_account).pluck(:tag_id))

View file

@ -16,11 +16,18 @@ class ManifestSerializer < ActiveModel::Serializer
512 512
).freeze ).freeze
attributes :name, :short_name, attributes :id, :name, :short_name,
:icons, :theme_color, :background_color, :icons, :theme_color, :background_color,
:display, :start_url, :scope, :display, :start_url, :scope,
:share_target, :shortcuts :share_target, :shortcuts
def id
# This is set to `/home` because that was the old value of `start_url` and
# thus the fallback ID computed by Chrome:
# https://developer.chrome.com/blog/pwa-manifest-id/
'/home'
end
def name def name
object.title object.title
end end
@ -53,7 +60,7 @@ class ManifestSerializer < ActiveModel::Serializer
end end
def start_url def start_url
'/home' '/'
end end
def scope def scope

View file

@ -3,9 +3,9 @@
enabled = ENV['ES_ENABLED'] == 'true' enabled = ENV['ES_ENABLED'] == 'true'
host = ENV.fetch('ES_HOST') { 'localhost' } host = ENV.fetch('ES_HOST') { 'localhost' }
port = ENV.fetch('ES_PORT') { 9200 } port = ENV.fetch('ES_PORT') { 9200 }
user = ENV.fetch('ES_USER') { nil } user = ENV.fetch('ES_USER', nil).presence
password = ENV.fetch('ES_PASS') { nil } password = ENV.fetch('ES_PASS', nil).presence
fallback_prefix = ENV.fetch('REDIS_NAMESPACE') { nil } fallback_prefix = ENV.fetch('REDIS_NAMESPACE', nil).presence
prefix = ENV.fetch('ES_PREFIX') { fallback_prefix } prefix = ENV.fetch('ES_PREFIX') { fallback_prefix }
Chewy.settings = { Chewy.settings = {

View file

@ -394,7 +394,7 @@ Devise.setup do |config|
config.check_at_sign = true config.check_at_sign = true
config.pam_default_suffix = ENV.fetch('PAM_EMAIL_DOMAIN') { ENV['LOCAL_DOMAIN'] } config.pam_default_suffix = ENV.fetch('PAM_EMAIL_DOMAIN') { ENV['LOCAL_DOMAIN'] }
config.pam_default_service = ENV.fetch('PAM_DEFAULT_SERVICE') { 'rpam' } config.pam_default_service = ENV.fetch('PAM_DEFAULT_SERVICE') { 'rpam' }
config.pam_controlled_service = ENV.fetch('PAM_CONTROLLED_SERVICE') { nil } config.pam_controlled_service = ENV.fetch('PAM_CONTROLLED_SERVICE', nil).presence
end end
if ENV['LDAP_ENABLED'] == 'true' if ENV['LDAP_ENABLED'] == 'true'

View file

@ -118,11 +118,11 @@ fi:
write: Vain kirjoitusoikeus write: Vain kirjoitusoikeus
title: title:
accounts: Tilit accounts: Tilit
admin/accounts: Tilien hallinta admin/accounts: Tilien hallinnointi
admin/all: Kaikki hallinnolliset toiminnot admin/all: Kaikki hallinnolliset toiminnot
admin/reports: Raporttien hallinta admin/reports: Raporttien hallinnointi
all: Täysi pääsy Mastodon-tiliisi all: Täysi pääsy Mastodon-tiliisi
blocks: Torjutut blocks: Estot
bookmarks: Kirjanmerkit bookmarks: Kirjanmerkit
conversations: Keskustelut conversations: Keskustelut
crypto: Päästä päähän -salaus crypto: Päästä päähän -salaus

View file

@ -27,10 +27,10 @@ fi:
title: Suorita valvontatoimi käyttäjälle %{acct} title: Suorita valvontatoimi käyttäjälle %{acct}
account_moderation_notes: account_moderation_notes:
create: Jätä muistiinpano create: Jätä muistiinpano
created_msg: Valvontamerkinnän luonti onnistui! created_msg: Valvontamuistiinpanon luonti onnistui!
destroyed_msg: Valvontamerkinnän poisto onnistui! destroyed_msg: Valvontamuistiinpanon poisto onnistui!
accounts: accounts:
add_email_domain_block: Estä sähköpostidomain add_email_domain_block: Estä sähköpostiverkkotunnus
approve: Hyväksy approve: Hyväksy
approved_msg: Käyttäjän %{username} liittymishakemus hyväksyttiin approved_msg: Käyttäjän %{username} liittymishakemus hyväksyttiin
are_you_sure: Oletko varma? are_you_sure: Oletko varma?
@ -95,10 +95,10 @@ fi:
silenced: Rajoitettu silenced: Rajoitettu
suspended: Jäädytetty suspended: Jäädytetty
title: Valvonta title: Valvonta
moderation_notes: Valvontamerkinnät moderation_notes: Valvontamuistiinpanot
most_recent_activity: Viimeisin toiminta most_recent_activity: Viimeisin toiminta
most_recent_ip: Viimeisin IP most_recent_ip: Viimeisin IP
no_account_selected: Yhtään tiliä ei muutettu, koska mitään ei valittu no_account_selected: Tilejä ei muutettu, koska yhtään ei ollut valittuna
no_limits_imposed: Rajoituksia ei ole asetettu no_limits_imposed: Rajoituksia ei ole asetettu
no_role_assigned: Roolia ei ole määritetty no_role_assigned: Roolia ei ole määritetty
not_subscribed: Ei tilaaja not_subscribed: Ei tilaaja
@ -117,7 +117,7 @@ fi:
reject: Hylkää reject: Hylkää
rejected_msg: Käyttäjän %{username} rekisteröitymishakemus hylättiin rejected_msg: Käyttäjän %{username} rekisteröitymishakemus hylättiin
remote_suspension_irreversible: Tämän tilin tiedot on poistettu peruuttamattomasti. remote_suspension_irreversible: Tämän tilin tiedot on poistettu peruuttamattomasti.
remote_suspension_reversible_hint_html: Tili on jäädytetty heidän palvelimellaan, ja kaikki tiedot poistetaan %{date}. Sitä ennen etäpalvelin voi palauttaa tilin ongelmitta. Jos haluat poistaa kaikki tilin tiedot heti, onnistuu se alta. remote_suspension_reversible_hint_html: Tili on jäädytetty omalla palvelimellaan, ja kaikki tiedot poistetaan %{date}. Sitä ennen etäpalvelin voi palauttaa tilin ongelmitta. Jos haluat poistaa kaikki tilin tiedot heti, onnistuu se alta.
remove_avatar: Poista profiilikuva remove_avatar: Poista profiilikuva
remove_header: Poista otsakekuva remove_header: Poista otsakekuva
removed_avatar_msg: Käyttäjän %{username} avatar-kuva poistettu onnistuneesti removed_avatar_msg: Käyttäjän %{username} avatar-kuva poistettu onnistuneesti
@ -181,7 +181,7 @@ fi:
create_custom_emoji: Luo mukautettu emoji create_custom_emoji: Luo mukautettu emoji
create_domain_allow: Luo verkkotunnuksen salliminen create_domain_allow: Luo verkkotunnuksen salliminen
create_domain_block: Luo verkkotunnuksen esto create_domain_block: Luo verkkotunnuksen esto
create_email_domain_block: Luo sähköpostin verkkotunnuksen esto create_email_domain_block: Luo sähköpostiverkkotunnuksen esto
create_ip_block: Luo IP-sääntö create_ip_block: Luo IP-sääntö
create_unavailable_domain: Luo ei-saatavilla oleva verkkotunnus create_unavailable_domain: Luo ei-saatavilla oleva verkkotunnus
create_user_role: Luo rooli create_user_role: Luo rooli
@ -191,7 +191,7 @@ fi:
destroy_custom_emoji: Poista mukautettu emoji destroy_custom_emoji: Poista mukautettu emoji
destroy_domain_allow: Poista verkkotunnuksen salliminen destroy_domain_allow: Poista verkkotunnuksen salliminen
destroy_domain_block: Poista verkkotunnuksen esto destroy_domain_block: Poista verkkotunnuksen esto
destroy_email_domain_block: Poista sähköpostin verkkotunnuksen esto destroy_email_domain_block: Poista sähköpostiverkkotunnuksen esto
destroy_instance: Tyhjennä verkkotunnus destroy_instance: Tyhjennä verkkotunnus
destroy_ip_block: Poista IP-sääntö destroy_ip_block: Poista IP-sääntö
destroy_status: Poista julkaisu destroy_status: Poista julkaisu
@ -236,21 +236,21 @@ fi:
confirm_user_html: "%{name} vahvisti käyttäjän %{target} sähköpostiosoitteen" confirm_user_html: "%{name} vahvisti käyttäjän %{target} sähköpostiosoitteen"
create_account_warning_html: "%{name} lähetti varoituksen käyttäjälle %{target}" create_account_warning_html: "%{name} lähetti varoituksen käyttäjälle %{target}"
create_announcement_html: "%{name} loi uuden tiedotteen %{target}" create_announcement_html: "%{name} loi uuden tiedotteen %{target}"
create_canonical_email_block_html: "%{name} esti sähköpostin hashilla %{target}" create_canonical_email_block_html: "%{name} esti sähköpostin tiivisteellä %{target}"
create_custom_emoji_html: "%{name} lähetti uuden emojin %{target}" create_custom_emoji_html: "%{name} lähetti uuden emojin %{target}"
create_domain_allow_html: "%{name} salli federoinnin verkkotunnuksen %{target} kanssa" create_domain_allow_html: "%{name} salli federoinnin verkkotunnuksen %{target} kanssa"
create_domain_block_html: "%{name} esti verkkotunnuksen %{target}" create_domain_block_html: "%{name} esti verkkotunnuksen %{target}"
create_email_domain_block_html: "%{name} esti sähköpostin %{target}" create_email_domain_block_html: "%{name} esti sähköpostiverkkotunnuksen %{target}"
create_ip_block_html: "%{name} loi IP-säännön %{target}" create_ip_block_html: "%{name} loi IP-säännön %{target}"
create_unavailable_domain_html: "%{name} pysäytti toimituksen verkkotunnukseen %{target}" create_unavailable_domain_html: "%{name} pysäytti toimituksen verkkotunnukseen %{target}"
create_user_role_html: "%{name} loi roolin %{target}" create_user_role_html: "%{name} loi roolin %{target}"
demote_user_html: "%{name} alensi käyttäjän %{target}" demote_user_html: "%{name} alensi käyttäjän %{target}"
destroy_announcement_html: "%{name} poisti tiedotteen %{target}" destroy_announcement_html: "%{name} poisti tiedotteen %{target}"
destroy_canonical_email_block_html: "%{name} poisti sähköpostieston hashilla %{target}" destroy_canonical_email_block_html: "%{name} poisti sähköpostin eston tiivisteellä %{target}"
destroy_custom_emoji_html: "%{name} poisti emojin %{target}" destroy_custom_emoji_html: "%{name} poisti emojin %{target}"
destroy_domain_allow_html: "%{name} kielsi federoinnin verkkotunnuksen %{target} kanssa" destroy_domain_allow_html: "%{name} kielsi federoinnin verkkotunnuksen %{target} kanssa"
destroy_domain_block_html: "%{name} poisti verkkotunnuksen %{target} eston" destroy_domain_block_html: "%{name} poisti verkkotunnuksen %{target} eston"
destroy_email_domain_block_html: "%{name} poisti sähköpostin verkkotunnuksen %{target} eston" destroy_email_domain_block_html: "%{name} poisti sähköpostiverkkotunnuksen %{target} eston"
destroy_instance_html: "%{name} tyhjensi verkkotunnuksen %{target}" destroy_instance_html: "%{name} tyhjensi verkkotunnuksen %{target}"
destroy_ip_block_html: "%{name} poisti IP-säännön %{target}" destroy_ip_block_html: "%{name} poisti IP-säännön %{target}"
destroy_status_html: "%{name} poisti käyttäjän %{target} julkaisun" destroy_status_html: "%{name} poisti käyttäjän %{target} julkaisun"
@ -331,7 +331,7 @@ fi:
listed: Listalla listed: Listalla
new: new:
title: Lisää uusi mukautettu emoji title: Lisää uusi mukautettu emoji
no_emoji_selected: Emojeita ei muutettu, koska yhtään ei valittu no_emoji_selected: Emojeita ei muutettu, koska yhtään ei ollut valittuna
not_permitted: Sinulla ei ole oikeutta suorittaa tätä toimintoa not_permitted: Sinulla ei ole oikeutta suorittaa tätä toimintoa
overwrite: Korvaa overwrite: Korvaa
shortcode: Lyhennekoodi shortcode: Lyhennekoodi
@ -381,7 +381,7 @@ fi:
import: Tuo import: Tuo
undo: Estä liitto verkkotunnukselle undo: Estä liitto verkkotunnukselle
domain_blocks: domain_blocks:
add_new: Lisää uusi add_new: Lisää uusi verkkotunnuksen esto
confirm_suspension: confirm_suspension:
cancel: Peruuta cancel: Peruuta
confirm: Jäädytä confirm: Jäädytä
@ -408,7 +408,7 @@ fi:
silence: Rajoita silence: Rajoita
suspend: Jäädytä suspend: Jäädytä
title: Uusi verkkotunnuksen esto title: Uusi verkkotunnuksen esto
no_domain_block_selected: Verkkoalue-estoihin ei tehty muutoksia, koska valintoja ei tehty no_domain_block_selected: Verkkotunnusten estoja ei muutettu, koska yhtään ei ollut valittuna
not_permitted: Nykyiset käyttöoikeutesi eivät kata tätä toimintoa not_permitted: Nykyiset käyttöoikeutesi eivät kata tätä toimintoa
obfuscate: Peitä verkkotunnuksen nimi obfuscate: Peitä verkkotunnuksen nimi
obfuscate_hint: Peitä verkkotunnus osittain luettelossa, jos julkinen verkkotunnusten rajoitusluettelo on käytössä obfuscate_hint: Peitä verkkotunnus osittain luettelossa, jos julkinen verkkotunnusten rajoitusluettelo on käytössä
@ -420,14 +420,14 @@ fi:
reject_media_hint: Poistaa paikallisesti tallennetut mediatiedostot eikä lataa niitä enää jatkossa. Ei merkitystä jäähyn kohdalla reject_media_hint: Poistaa paikallisesti tallennetut mediatiedostot eikä lataa niitä enää jatkossa. Ei merkitystä jäähyn kohdalla
reject_reports: Hylkää raportit reject_reports: Hylkää raportit
reject_reports_hint: Ohita kaikki tästä verkkotunnuksesta tulevat raportit. Erottamisen kannalta ei merkitystä reject_reports_hint: Ohita kaikki tästä verkkotunnuksesta tulevat raportit. Erottamisen kannalta ei merkitystä
undo: Peru undo: Peru verkkotunnuksen esto
view: Näytä verkkotunnuksen esto view: Näytä verkkotunnuksen esto
email_domain_blocks: email_domain_blocks:
add_new: Lisää uusi add_new: Lisää uusi
attempts_over_week: attempts_over_week:
one: "%{count} yritystä viimeisen viikon aikana" one: "%{count} yritystä viimeisen viikon aikana"
other: "%{count} rekisteröitymisyritystä viimeisen viikon aikana" other: "%{count} rekisteröitymisyritystä viimeisen viikon aikana"
created_msg: Sähköpostiverkkotunnuksen lisäys estolistalle onnistui created_msg: Sähköpostiverkkotunnus estetty onnistuneesti
delete: Poista delete: Poista
dns: dns:
types: types:
@ -436,26 +436,26 @@ fi:
new: new:
create: Lisää verkkotunnus create: Lisää verkkotunnus
resolve: Ratkaise verkkotunnus resolve: Ratkaise verkkotunnus
title: Uusi sähköpostiestolistan merkintä title: Estä uusi sähköpostiverkkotunnus
no_email_domain_block_selected: Sähköpostin verkkotunnuksia ei muutettu, koska yhtään ei valittu no_email_domain_block_selected: Sähköpostin verkkotunnuksia ei muutettu, koska yhtään ei ollut valittuna
not_permitted: Ei sallittu not_permitted: Ei sallittu
resolved_dns_records_hint_html: Verkkotunnuksen nimi määräytyy seuraaviin MX-verkkotunnuksiin, jotka ovat viime kädessä vastuussa sähköpostin vastaanottamisesta. MX-verkkotunnuksen estäminen estää kirjautumisen mistä tahansa sähköpostiosoitteesta, joka käyttää samaa MX-verkkotunnusta, vaikka näkyvä verkkotunnuksen nimi olisikin erilainen. <strong>Varo estämästä suuria sähköpostin palveluntarjoajia.</strong> resolved_dns_records_hint_html: Verkkotunnuksen nimi määräytyy seuraaviin MX-verkkotunnuksiin, jotka ovat viime kädessä vastuussa sähköpostin vastaanottamisesta. MX-verkkotunnuksen estäminen estää kirjautumisen mistä tahansa sähköpostiosoitteesta, joka käyttää samaa MX-verkkotunnusta, vaikka näkyvä verkkotunnuksen nimi olisikin erilainen. <strong>Varo estämästä suuria sähköpostin palveluntarjoajia.</strong>
resolved_through_html: Ratkaistu %{domain} kautta resolved_through_html: Ratkaistu %{domain} kautta
title: Sähköpostiestolista title: Estetyt sähköpostiverkkotunnukset
export_domain_allows: export_domain_allows:
new: new:
title: Tuo sallitut verkkoalueet title: Tuo sallittuja verkkotunnuksia
no_file: Yhtäkään tiedostoa ei ole valittu no_file: Yhtäkään tiedostoa ei ole valittu
export_domain_blocks: export_domain_blocks:
import: import:
description_html: Olet tuomassa verkkotunnusten estoluetteloa. Tarkista luettelo huolella etenkin, jos et ole laatinut sitä itse. description_html: Olet tuomassa verkkotunnusten estoluetteloa. Tarkista luettelo huolella etenkin, jos et ole laatinut sitä itse.
existing_relationships_warning: Olemassa olevat seuraussuhteet existing_relationships_warning: Olemassa olevat seuraussuhteet
private_comment_description_html: 'Tuodun estolistan alkuperän selvillä pitämiseksi, lisätään tietojen yhteyteen seuraava yksityinen kommentti: <q>%{comment}</q>' private_comment_description_html: 'Seurataksesi tuotujen estojen alkuperää lisätään estojen yhteyteen seuraava yksityinen kommentti: <q>%{comment}</q>'
private_comment_template: Tuotu lähteestä %{source}, pvm %{date} private_comment_template: Tuotu lähteestä %{source} %{date}
title: Tuo luettelo verkkoalue-estoista title: Tuo verkkotunnusten estoja
invalid_domain_block: 'Yksi tai useampi verkkotunnuksen lohko ohitettiin seuraavien virheiden vuoksi: %{error}' invalid_domain_block: 'Yksi tai useampi verkkotunnuksen esto ohitettiin seuraavien virheiden vuoksi: %{error}'
new: new:
title: Tuo luettelo verkkoalue-estoista title: Tuo verkkotunnusten estoja
no_file: Yhtäkään tiedostoa ei ole valittu no_file: Yhtäkään tiedostoa ei ole valittu
follow_recommendations: follow_recommendations:
description_html: "<strong>Seuraamissuositukset auttavat uusia käyttäjiä löytämään nopeasti kiinnostavaa sisältöä</strong>. 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ä." description_html: "<strong>Seuraamissuositukset auttavat uusia käyttäjiä löytämään nopeasti kiinnostavaa sisältöä</strong>. 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_limited: Rajoitettu
back_to_warning: Varoitus back_to_warning: Varoitus
by_domain: Verkkotunnus 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: 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. 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. limited_federation_mode_description_html: Voit valita sallitaanko federointi tällä verkkotunnuksella.
policies: policies:
@ -527,7 +527,7 @@ fi:
purge: Tyhjennä 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. 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 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_them: Heidän seuraama
total_followed_by_us: Meidän seuraama total_followed_by_us: Meidän seuraama
total_reported: Niitä koskevat raportit total_reported: Niitä koskevat raportit
@ -554,7 +554,7 @@ fi:
'94670856': 3 vuotta '94670856': 3 vuotta
new: new:
title: Luo uusi IP-sääntö 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 title: IP-säännöt
relationships: relationships:
title: "%{acct}n suhteet" title: "%{acct}n suhteet"
@ -575,13 +575,13 @@ fi:
status: Tila status: Tila
title: Välittäjät title: Välittäjät
report_notes: report_notes:
created_msg: Muistiinpano onnistuneesti lisätty raporttiin! created_msg: Muistiinpano lisätty raporttiin onnistuneesti!
destroyed_msg: Muistiinpano onnistuneesti poistettu raportista! destroyed_msg: Muistiinpano poistettu raportista onnistuneesti!
reports: reports:
account: account:
notes: notes:
one: "%{count} ilmoitus" one: "%{count} muistiinpano"
other: "%{count} ilmoitusta" other: "%{count} muistiinpanoa"
action_log: Tarkastusloki action_log: Tarkastusloki
action_taken_by: Toimen tehnyt action_taken_by: Toimen tehnyt
actions: actions:
@ -620,8 +620,8 @@ fi:
create_and_unresolve: Avaa uudelleen ja lisää muistiinpano create_and_unresolve: Avaa uudelleen ja lisää muistiinpano
delete: Poista delete: Poista
placeholder: Kuvaile mitä toimia on tehty tai muita päivityksiä tähän raporttiin… placeholder: Kuvaile mitä toimia on tehty tai muita päivityksiä tähän raporttiin…
title: Merkinnät title: Muistiinpanot
notes_description_html: Tarkastele ja jätä merkintöjä muille valvojille ja itsellesi tulevaisuuteen notes_description_html: Tarkastele ja jätä muistiinpanoja muille valvojille ja itsellesi tulevaisuuteen
processed_msg: 'Raportti #%{id} käsitelty' processed_msg: 'Raportti #%{id} käsitelty'
quick_actions_description_html: 'Suorita nopea toiminto tai vieritä alas nähdäksesi raportoitu sisältö:' 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} remote_user_placeholder: etäkäyttäjä instanssista %{instance}
@ -707,7 +707,7 @@ fi:
manage_settings: Hallitse asetuksia manage_settings: Hallitse asetuksia
manage_settings_description: Sallii käyttäjien muuttaa sivuston asetuksia manage_settings_description: Sallii käyttäjien muuttaa sivuston asetuksia
manage_taxonomies: Hallitse luokittelua 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: 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_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ä 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. rules_hint: On olemassa erityinen alue sääntöjä, joita käyttäjien odotetaan noudattavan.
title: Tietoja title: Tietoja
appearance: appearance:
preamble: Mukauta Mastodonin verkkokäyttöliittymää. preamble: Mukauta Mastodonin selainkäyttöliittymää.
title: Ulkoasu title: Ulkoasu
branding: 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 title: Brändäys
captcha_enabled: captcha_enabled:
desc_html: Tämä perustuu ulkoisiin skripteihin hCaptchasta, mikä voi olla turvallisuus- ja yksityisyysongelma. Lisäksi <strong>tämä voi tehdä rekisteröinnin ihmisille huomattavasti (erityisesti vammaisten) helpommaksi</strong>. Harkitse vaihtoehtoisia toimenpiteitä, kuten hyväksymisperusteista tai kutsupohjaista rekisteröintiä. desc_html: Tämä perustuu ulkoisiin skripteihin hCaptchasta, mikä voi olla turvallisuus- ja yksityisyysongelma. Lisäksi <strong>tämä voi tehdä rekisteröinnin ihmisille huomattavasti (erityisesti vammaisten) helpommaksi</strong>. Harkitse vaihtoehtoisia toimenpiteitä, kuten hyväksymisperusteista tai kutsupohjaista rekisteröintiä.
@ -807,13 +807,13 @@ fi:
media: media:
title: Media title: Media
metadata: Metadata 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 open: Avaa julkaisu
original_status: Alkuperäinen julkaisu original_status: Alkuperäinen julkaisu
reblogs: Edelleen jako reblogs: Edelleen jako
status_changed: Julkaisua muutettu status_changed: Julkaisua muutettu
title: Tilin tilat title: Tilin tilat
trending: Nousussa trending: Suosituttua
visibility: Näkyvyys visibility: Näkyvyys
with_media: Sisältää mediaa with_media: Sisältää mediaa
strikes: strikes:
@ -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. 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: Hylkää linkki
disallow_provider: Estä julkaisija 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: 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: shared_by_over_week:
one: Yksi henkilö jakanut viimeisen viikon aikana one: Yksi henkilö jakanut viimeisen viikon aikana
other: Jakanut %{count} henkilöä 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. 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: Kiellä julkaisu
disallow_account: Estä tekijä 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ä not_discoverable: Tekijä ei ole ilmoittanut olevansa löydettävissä
shared_by: shared_by:
one: Jaettu tai lisätty suosikkeihin kerran one: Jaettu tai lisätty suosikkeihin kerran
@ -920,21 +920,21 @@ fi:
tag_uses_measure: käyttökerrat 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. 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 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_listable: Ei tulla ehdottamaan
not_trendable: Ei näy trendien alla not_trendable: Ei näy trendien alla
not_usable: Ei voida käyttää not_usable: Ei voida käyttää
peaked_on_and_decaying: Saavutti huipun %{date}, nyt hiipuu peaked_on_and_decaying: Saavutti huipun %{date}, nyt hiipuu
title: Suositut aihetunnisteet title: Suositut aihetunnisteet
trendable: Voi näkyä trendien alla trendable: Voi näkyä trendien alla
trending_rank: 'Nousussa #%{rank}' trending_rank: 'Suosittua #%{rank}'
usable: Voidaan käyttää usable: Voidaan käyttää
usage_comparison: Käytetty %{today} kertaa tänään, verrattuna %{yesterday} eiliseen usage_comparison: Käytetty %{today} kertaa tänään, verrattuna %{yesterday} eiliseen
used_by_over_week: used_by_over_week:
one: Yhden henkilön käyttämä viime viikon aikana one: Yhden henkilön käyttämä viime viikon aikana
other: Käyttänyt %{count} henkilöä viimeisen viikon aikana other: Käyttänyt %{count} henkilöä viimeisen viikon aikana
title: Trendit title: Trendit
trending: Nousussa trending: Suosittua
warning_presets: warning_presets:
add_new: Lisää uusi add_new: Lisää uusi
delete: Poista delete: Poista
@ -994,8 +994,8 @@ fi:
new_trending_statuses: new_trending_statuses:
title: Suositut julkaisut title: Suositut julkaisut
new_trending_tags: new_trending_tags:
no_approved_tags: Tällä hetkellä ei ole hyväksyttyjä trendikkäitä aihetunnisteita. no_approved_tags: Tällä hetkellä ei ole hyväksyttyjä suosittuja 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}.' 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 title: Suositut aihetunnisteet
subject: Uusia trendejä tarkistettavaksi instanssissa %{instance} subject: Uusia trendejä tarkistettavaksi instanssissa %{instance}
aliases: aliases:
@ -1007,7 +1007,7 @@ fi:
remove: Poista aliaksen linkitys remove: Poista aliaksen linkitys
appearance: appearance:
advanced_web_interface: Edistynyt selainkäyttöliittymä 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 animations_and_accessibility: Animaatiot ja saavutettavuus
confirmation_dialogs: Vahvistusvalinnat confirmation_dialogs: Vahvistusvalinnat
discovery: Löytäminen discovery: Löytäminen
@ -1219,8 +1219,8 @@ fi:
featured_tags: featured_tags:
add_new: Lisää uusi add_new: Lisää uusi
errors: errors:
limit: Olet jo nostanut esille enimmäismäärän aihetunnisteita limit: Pidät jo esillä aihetunnisteiden enimmäismäärää
hint_html: "<strong>Mitä ovat näkyvillä olevat hashtagit eli aihetunnisteet?</strong> 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." hint_html: "<strong>Pidä tärkeimpiä aihetunnisteitasi esillä profiilissasi.</strong> 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: filters:
contexts: contexts:
account: Profiilit 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. <a href="%{path}">Tarkista tai poista julkaisut suodattimesta</a>. statuses_hint_html: Tämä suodatin koskee yksittäisten julkaisujen valintaa riippumatta siitä, vastaavatko ne alla olevia avainsanoja. <a href="%{path}">Tarkista tai poista julkaisut suodattimesta</a>.
title: Muokkaa suodatinta title: Muokkaa suodatinta
errors: 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 invalid_context: Ei sisältöä tai se on virheellinen
index: index:
contexts: Suodattimet %{contexts} contexts: Suodattimet %{contexts}
@ -1261,7 +1261,7 @@ fi:
batch: batch:
remove: Poista suodattimista remove: Poista suodattimista
index: 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 title: Suodatetut julkaisut
generic: generic:
all: Kaikki all: Kaikki
@ -1290,7 +1290,7 @@ fi:
imports: imports:
errors: errors:
empty: Tyhjä CSV-tiedosto 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}' invalid_csv_file: 'Epäkelpo CSV-tiedosto. Virhe: %{error}'
over_rows_processing_limit: sisältää yli %{count} riviä over_rows_processing_limit: sisältää yli %{count} riviä
too_large: Tiedosto on liian suuri too_large: Tiedosto on liian suuri
@ -1331,8 +1331,8 @@ fi:
bookmarks: Tuodaan kirjanmerkkejä bookmarks: Tuodaan kirjanmerkkejä
domain_blocking: Tuodaan estettyjä verkkotunnuksia domain_blocking: Tuodaan estettyjä verkkotunnuksia
following: Tuodaan seurattuja tilejä following: Tuodaan seurattuja tilejä
lists: Listojen tuonti lists: Tuodaan listoja
muting: Tuodaan hiljennettyjä tilejä muting: Tuodaan mykistettyjä tilejä
type: Tuonnin tyyppi type: Tuonnin tyyppi
type_groups: type_groups:
constructive: Seuratut ja kirjanmerkit constructive: Seuratut ja kirjanmerkit
@ -1340,7 +1340,7 @@ fi:
types: types:
blocking: Estoluettelo blocking: Estoluettelo
bookmarks: Kirjanmerkit bookmarks: Kirjanmerkit
domain_blocking: Verkkotunnuksen estoluettelo domain_blocking: Verkkotunnusten estoluettelo
following: Seurattujen luettelo following: Seurattujen luettelo
lists: Listat lists: Listat
muting: Mykistettyjen luettelo muting: Mykistettyjen luettelo
@ -1436,7 +1436,7 @@ fi:
title: Valvonta title: Valvonta
move_handler: move_handler:
carry_blocks_over_text: Tämä käyttäjä siirtyi paikasta %{acct}, jonka olit estänyt. 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ä:' copy_account_note_text: 'Tämä käyttäjä siirtyi paikasta %{acct}, tässä olivat aiemmat muistiinpanosi niistä:'
navigation: navigation:
toggle_menu: Avaa/sulje valikko toggle_menu: Avaa/sulje valikko
@ -1625,7 +1625,7 @@ fi:
development: Kehitys development: Kehitys
edit_profile: Muokkaa profiilia edit_profile: Muokkaa profiilia
export: Vie tietoja export: Vie tietoja
featured_tags: Esiteltävät aihetunnisteet featured_tags: Esillä pidettävät aihetunnisteet
import: Tuo import: Tuo
import_and_export: Tuonti ja vienti import_and_export: Tuonti ja vienti
migrate: Tilin muutto muualle migrate: Tilin muutto muualle

View file

@ -77,11 +77,11 @@ fi:
form_admin_settings: form_admin_settings:
activity_api_enabled: Paikallisesti julkaistujen julkaisujen, aktiivisten käyttäjien ja rekisteröitymisten viikoittainen määrä 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ä. 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 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. 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. 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ä. 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. 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ä. profile_directory: Profiilihakemisto lueteloi kaikki käyttäjät, jotka ovat ilmoittaneet olevansa löydettävissä.
@ -108,7 +108,7 @@ fi:
ip_block: ip_block:
comment: Valinnainen. Muista miksi lisäsit tämän säännön. 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. 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: severities:
no_access: Estä pääsy kaikkiin resursseihin no_access: Estä pääsy kaikkiin resursseihin
sign_up_block: Uudet kirjautumiset eivät ole mahdollisia sign_up_block: Uudet kirjautumiset eivät ole mahdollisia
@ -139,7 +139,7 @@ fi:
url: Mihin tapahtumat lähetetään url: Mihin tapahtumat lähetetään
labels: labels:
account: account:
discoverable: Nosta profiili ja julkaisut esille löytämisalgoritmeissa discoverable: Pidä profiiliasi ja julkaisujasi esillä löytämisalgoritmeissa
fields: fields:
name: Nimike name: Nimike
value: Sisältö value: Sisältö
@ -162,8 +162,8 @@ fi:
disable: Poista kirjautuminen käytöstä disable: Poista kirjautuminen käytöstä
none: Älä tee mitään none: Älä tee mitään
sensitive: Arkaluonteinen sensitive: Arkaluonteinen
silence: Hiljennä silence: Rajoita
suspend: Poista käytöstä ja tuhoa käyttäjätunnuksen tiedot peruuttamattomasti suspend: Jäädytä
warning_preset_id: Käytä varoitusmallia warning_preset_id: Käytä varoitusmallia
announcement: announcement:
all_day: Koko päivän kestävä tapahtuma all_day: Koko päivän kestävä tapahtuma
@ -224,7 +224,7 @@ fi:
severity: Vakavuus severity: Vakavuus
sign_in_token_attempt: Turvakoodi sign_in_token_attempt: Turvakoodi
title: Nimi title: Nimi
type: Tuontilaji type: Tuontityyppi
username: Käyttäjänimi username: Käyttäjänimi
username_or_email: Käyttäjänimi tai sähköpostiosoite username_or_email: Käyttäjänimi tai sähköpostiosoite
whole_word: Koko sana whole_word: Koko sana
@ -249,7 +249,7 @@ fi:
profile_directory: Ota profiilihakemisto käyttöön profile_directory: Ota profiilihakemisto käyttöön
registrations_mode: Kuka voi rekisteröityä registrations_mode: Kuka voi rekisteröityä
require_invite_text: Vaadi syy liittyä 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 show_domain_blocks_rationale: Näytä miksi verkkotunnukset on estetty
site_contact_email: Ota yhteyttä sähköpostilla site_contact_email: Ota yhteyttä sähköpostilla
site_contact_username: Yhteyshenkilön käyttäjänimi site_contact_username: Yhteyshenkilön käyttäjänimi
@ -277,7 +277,7 @@ fi:
ip: IP-osoite ip: IP-osoite
severities: severities:
no_access: Estä pääsy no_access: Estä pääsy
sign_up_block: Estä kirjautumiset sign_up_block: Estä rekisteröitymiset
sign_up_requires_approval: Rajoita rekisteröitymisiä sign_up_requires_approval: Rajoita rekisteröitymisiä
severity: Sääntö severity: Sääntö
notification_emails: notification_emails:

View file

@ -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 # 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` # 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 end
context 'when the number of requests is lower than the limit' do 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 it 'does not change the request status' do
limit.times do expect { request.call }.to change { throttle_count }.by(1)
request.call
expect(response).to_not have_http_status(429) expect(response).to_not have_http_status(429)
end
end end
end end
context 'when the number of requests is higher than the limit' do 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 it 'returns http too many requests after limit and returns to normal status after period' do
(limit * 2).times do |i| expect { request.call }.to change { throttle_count }.by(1)
request.call expect(response).to have_http_status(429)
expect(response).to have_http_status(429) if i > limit
end
travel period travel period
request.call expect { request.call }.to change { throttle_count }.by(1)
expect(response).to_not have_http_status(429) expect(response).to_not have_http_status(429)
end end
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 end
let(:remote_ip) { '1.2.3.5' } let(:remote_ip) { '1.2.3.5' }
describe 'throttle excessive sign-up requests by IP address' do describe 'throttle excessive sign-up requests by IP address' do
context 'when accessed through the website' do context 'when accessed through the website' do
let(:throttle) { 'throttle_sign_up_attempts/ip' }
let(:limit) { 25 } let(:limit) { 25 }
let(:period) { 5.minutes } let(:period) { 5.minutes }
let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } } let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } }
@ -65,6 +91,7 @@ describe Rack::Attack, type: :request do
end end
context 'when accessed through the API' do context 'when accessed through the API' do
let(:throttle) { 'throttle_api_sign_up' }
let(:limit) { 5 } let(:limit) { 5 }
let(:period) { 30.minutes } let(:period) { 30.minutes }
let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } } let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } }
@ -87,6 +114,7 @@ describe Rack::Attack, type: :request do
end end
describe 'throttle excessive sign-in requests by IP address' do describe 'throttle excessive sign-in requests by IP address' do
let(:throttle) { 'throttle_login_attempts/ip' }
let(:limit) { 25 } let(:limit) { 25 }
let(:period) { 5.minutes } let(:period) { 5.minutes }
let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } } let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } }

View file

@ -14,11 +14,8 @@ RSpec.describe Api::OEmbedController do
get :show, params: { url: short_account_status_url(alice, status) }, format: :json get :show, params: { url: short_account_status_url(alice, status) }, format: :json
end end
it 'returns http success' do it 'returns private cache control headers', :aggregate_failures do
expect(response).to have_http_status(200) 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') expect(response.headers['Cache-Control']).to include('private, no-store')
end end
end end

View file

@ -41,11 +41,9 @@ describe Api::V1::Accounts::CredentialsController do
} }
end end
it 'returns http success' do it 'updates account info', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'updates account info' do
user.reload user.reload
user.account.reload user.account.reload
@ -55,9 +53,7 @@ describe Api::V1::Accounts::CredentialsController do
expect(user.account.header).to exist expect(user.account.header).to exist
expect(user.setting_default_privacy).to eq('unlisted') expect(user.setting_default_privacy).to eq('unlisted')
expect(user.setting_default_sensitive).to be(true) 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) expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(user.account_id)
end end
end end

View file

@ -18,23 +18,19 @@ describe Api::V1::Accounts::FollowerAccountsController do
end end
describe 'GET #index' do 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 } get :index, params: { account_id: account.id, limit: 2 }
expect(response).to have_http_status(200) 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.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) expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
end end
it 'does not return blocked users' do it 'does not return blocked users', :aggregate_failures do
user.account.block!(bob) user.account.block!(bob)
get :index, params: { account_id: account.id, limit: 2 } 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.size).to eq 1
expect(body_as_json[0][:id]).to eq alice.id.to_s expect(body_as_json[0][:id]).to eq alice.id.to_s
end end

View file

@ -18,23 +18,19 @@ describe Api::V1::Accounts::FollowingAccountsController do
end end
describe 'GET #index' do 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 } get :index, params: { account_id: account.id, limit: 2 }
expect(response).to have_http_status(200) 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.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) expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
end end
it 'does not return blocked users' do it 'does not return blocked users', :aggregate_failures do
user.account.block!(bob) user.account.block!(bob)
get :index, params: { account_id: account.id, limit: 2 } 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.size).to eq 1
expect(body_as_json[0][:id]).to eq alice.id.to_s expect(body_as_json[0][:id]).to eq alice.id.to_s
end end

View file

@ -19,30 +19,24 @@ describe Api::V1::Accounts::NotesController do
post :create, params: { account_id: account.id, comment: comment } post :create, params: { account_id: account.id, comment: comment }
end end
context 'when account note has reasonable length' do context 'when account note has reasonable length', :aggregate_failures do
let(:comment) { 'foo' } let(:comment) { 'foo' }
it 'returns http success' do
subject
expect(response).to have_http_status(200)
end
it 'updates account note' do it 'updates account note' do
subject 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 expect(AccountNote.find_by(account_id: user.account.id, target_account_id: account.id).comment).to eq comment
end end
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 } 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 it 'does not create account note' do
subject subject
expect(response).to have_http_status(422)
expect(AccountNote.where(account_id: user.account.id, target_account_id: account.id)).to_not exist expect(AccountNote.where(account_id: user.account.id, target_account_id: account.id)).to_not exist
end end
end end

View file

@ -15,14 +15,11 @@ RSpec.describe Api::V1::Accounts::PinsController do
describe 'POST #create' do describe 'POST #create' do
subject { post :create, params: { account_id: kevin.account.id } } subject { post :create, params: { account_id: kevin.account.id } }
it 'returns 200' do it 'creates account_pin', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'creates account_pin' do
expect do expect do
subject subject
end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(1) 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 end
@ -33,14 +30,11 @@ RSpec.describe Api::V1::Accounts::PinsController do
Fabricate(:account_pin, account: john.account, target_account: kevin.account) Fabricate(:account_pin, account: john.account, target_account: kevin.account)
end end
it 'returns 200' do it 'destroys account_pin', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'destroys account_pin' do
expect do expect do
subject subject
end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(-1) 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 end
end end

View file

@ -26,13 +26,10 @@ describe Api::V1::Accounts::RelationshipsController do
get :index, params: { id: simon.id } get :index, params: { id: simon.id }
end end
it 'returns http success' do it 'returns JSON with correct data', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns JSON with correct data' do
json = body_as_json json = body_as_json
expect(response).to have_http_status(200)
expect(json).to be_a Enumerable expect(json).to be_a Enumerable
expect(json.first[:following]).to be true expect(json.first[:following]).to be true
expect(json.first[:followed_by]).to be false 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 context 'when there is returned JSON data' do
let(:json) { body_as_json } 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(json).to be_a Enumerable
expect_simon_item_one
expect_lewis_item_two
end 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[:id]).to eq simon.id.to_s
expect(json.first[:following]).to be true expect(json.first[:following]).to be true
expect(json.first[:showing_reblogs]).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 expect(json.first[:domain_blocking]).to be false
end 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[:id]).to eq lewis.id.to_s
expect(json.second[:following]).to be false expect(json.second[:following]).to be false
expect(json.second[:showing_reblogs]).to be false expect(json.second[:showing_reblogs]).to be false

View file

@ -14,15 +14,10 @@ describe Api::V1::Accounts::StatusesController do
end end
describe 'GET #index' do 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 } get :index, params: { account_id: user.account.id, limit: 1 }
expect(response).to have_http_status(200) 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) expect(response.headers['Link'].links.size).to eq(2)
end end
@ -44,14 +39,11 @@ describe Api::V1::Accounts::StatusesController do
get :index, params: { account_id: user.account.id, exclude_replies: true } get :index, params: { account_id: user.account.id, exclude_replies: true }
end end
it 'returns http success' do it 'returns posts along with self replies', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns posts along with self replies' do
json = body_as_json json = body_as_json
post_ids = json.map { |item| item[:id].to_i }.sort 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] expect(post_ids).to eq [status.id, status_self_reply.id]
end end
end end

View file

@ -25,15 +25,10 @@ RSpec.describe Api::V1::AccountsController do
context 'when given truthy agreement' do context 'when given truthy agreement' do
let(:agreement) { 'true' } let(:agreement) { 'true' }
it 'returns http success' do it 'creates a user', :aggregate_failures do
expect(response).to have_http_status(200) 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 expect(body_as_json[:access_token]).to_not be_blank
end
it 'creates a user' do
user = User.find_by(email: 'hello@world.tld') user = User.find_by(email: 'hello@world.tld')
expect(user).to_not be_nil expect(user).to_not be_nil
expect(user.created_by_application_id).to eq app.id 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 context 'with unlocked account' do
let(:locked) { false } 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) expect(response).to have_http_status(200)
end
it 'returns JSON with following=true and requested=false' do
json = body_as_json json = body_as_json
expect(json[:following]).to be true expect(json[:following]).to be true
expect(json[:requested]).to be false 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 expect(user.account.following?(other_account)).to be true
end end
@ -86,18 +77,14 @@ RSpec.describe Api::V1::AccountsController do
context 'with locked account' do context 'with locked account' do
let(:locked) { true } 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) expect(response).to have_http_status(200)
end
it 'returns JSON with following=false and requested=true' do
json = body_as_json json = body_as_json
expect(json[:following]).to be false expect(json[:following]).to be false
expect(json[:requested]).to be true 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 expect(user.account.requested?(other_account)).to be true
end end
@ -177,11 +164,8 @@ RSpec.describe Api::V1::AccountsController do
post :unfollow, params: { id: other_account.id } post :unfollow, params: { id: other_account.id }
end 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) 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 expect(user.account.following?(other_account)).to be false
end end
@ -197,11 +181,8 @@ RSpec.describe Api::V1::AccountsController do
post :remove_from_followers, params: { id: other_account.id } post :remove_from_followers, params: { id: other_account.id }
end 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) 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 expect(user.account.followed_by?(other_account)).to be false
end end
@ -217,15 +198,9 @@ RSpec.describe Api::V1::AccountsController do
post :block, params: { id: other_account.id } post :block, params: { id: other_account.id }
end end
it 'returns http success' do it 'creates a blocking relation', :aggregate_failures do
expect(response).to have_http_status(200) 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 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 expect(user.account.blocking?(other_account)).to be true
end end
@ -241,11 +216,8 @@ RSpec.describe Api::V1::AccountsController do
post :unblock, params: { id: other_account.id } post :unblock, params: { id: other_account.id }
end 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) 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 expect(user.account.blocking?(other_account)).to be false
end end
@ -261,19 +233,10 @@ RSpec.describe Api::V1::AccountsController do
post :mute, params: { id: other_account.id } post :mute, params: { id: other_account.id }
end end
it 'returns http success' do it 'mutes notifications', :aggregate_failures do
expect(response).to have_http_status(200) 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 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 expect(user.account.muting?(other_account)).to be true
end
it 'mutes notifications' do
expect(user.account.muting_notifications?(other_account)).to be true expect(user.account.muting_notifications?(other_account)).to be true
end end
@ -289,19 +252,10 @@ RSpec.describe Api::V1::AccountsController do
post :mute, params: { id: other_account.id, notifications: false } post :mute, params: { id: other_account.id, notifications: false }
end end
it 'returns http success' do it 'does not mute notifications', :aggregate_failures do
expect(response).to have_http_status(200) 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 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 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 expect(user.account.muting_notifications?(other_account)).to be false
end end
@ -317,19 +271,10 @@ RSpec.describe Api::V1::AccountsController do
post :mute, params: { id: other_account.id, duration: 300 } post :mute, params: { id: other_account.id, duration: 300 }
end end
it 'returns http success' do it 'mutes notifications', :aggregate_failures do
expect(response).to have_http_status(200) 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 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 expect(user.account.muting?(other_account)).to be true
end
it 'mutes notifications' do
expect(user.account.muting_notifications?(other_account)).to be true expect(user.account.muting_notifications?(other_account)).to be true
end end
@ -345,11 +290,8 @@ RSpec.describe Api::V1::AccountsController do
post :unmute, params: { id: other_account.id } post :unmute, params: { id: other_account.id }
end 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) 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 expect(user.account.muting?(other_account)).to be false
end end

View file

@ -44,11 +44,9 @@ RSpec.describe Api::V1::Admin::AccountsController do
context "when called with #{params.inspect}" do context "when called with #{params.inspect}" do
let(:params) { params } 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) expect(response).to have_http_status(200)
end
it "returns the correct accounts (#{expected_results.inspect})" do
json = body_as_json json = body_as_json
expect(json.map { |a| a[:id].to_i }).to eq(expected_results.map { |symbol| send(symbol).id }) 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 scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' 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) expect(response).to have_http_status(200)
end
it 'approves user' do
expect(account.reload.user_approved?).to be true expect(account.reload.user_approved?).to be true
end
it 'logs action' do
log_item = Admin::ActionLog.last log_item = Admin::ActionLog.last
expect(log_item).to_not be_nil 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 scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' 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) expect(response).to have_http_status(200)
end
it 'removes user' do
expect(User.where(id: account.user.id).count).to eq 0 expect(User.where(id: account.user.id).count).to eq 0
end
it 'logs action' do
log_item = Admin::ActionLog.last log_item = Admin::ActionLog.last
expect(log_item).to_not be_nil 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 scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' 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) expect(response).to have_http_status(200)
end
it 'enables user' do
expect(account.reload.user_disabled?).to be false expect(account.reload.user_disabled?).to be false
end end
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 scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' 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) expect(response).to have_http_status(200)
end
it 'unsuspends account' do
expect(account.reload.suspended?).to be false expect(account.reload.suspended?).to be false
end end
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 scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' 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) expect(response).to have_http_status(200)
end
it 'unsensitizes account' do
expect(account.reload.sensitized?).to be false expect(account.reload.sensitized?).to be false
end end
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 scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' 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) expect(response).to have_http_status(200)
end
it 'unsilences account' do
expect(account.reload.silenced?).to be false expect(account.reload.silenced?).to be false
end end
end end

View file

@ -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

View file

@ -25,11 +25,8 @@ RSpec.describe Api::V1::Announcements::ReactionsController do
put :update, params: { announcement_id: announcement.id, id: '😂' } put :update, params: { announcement_id: announcement.id, id: '😂' }
end end
it 'returns http success' do it 'creates reaction', :aggregate_failures do
expect(response).to have_http_status(200) 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 expect(announcement.announcement_reactions.find_by(name: '😂', account: user.account)).to_not be_nil
end end
end end
@ -53,11 +50,8 @@ RSpec.describe Api::V1::Announcements::ReactionsController do
delete :destroy, params: { announcement_id: announcement.id, id: '😂' } delete :destroy, params: { announcement_id: announcement.id, id: '😂' }
end end
it 'returns http success' do it 'creates reaction', :aggregate_failures do
expect(response).to have_http_status(200) 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 expect(announcement.announcement_reactions.find_by(name: '😂', account: user.account)).to be_nil
end end
end end

View file

@ -47,11 +47,8 @@ RSpec.describe Api::V1::AnnouncementsController do
post :dismiss, params: { id: announcement.id } post :dismiss, params: { id: announcement.id }
end end
it 'returns http success' do it 'dismisses announcement', :aggregate_failures do
expect(response).to have_http_status(200) 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 expect(announcement.announcement_mutes.find_by(account: user.account)).to_not be_nil
end end
end end

View file

@ -12,45 +12,48 @@ RSpec.describe Api::V1::BlocksController do
before { allow(controller).to receive(:doorkeeper_token) { token } } before { allow(controller).to receive(:doorkeeper_token) { token } }
describe 'GET #index' do 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) } Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { limit: 1 } get :index, params: { limit: 1 }
expect(response).to have_http_status(200)
expect(body_as_json.size).to eq 1 expect(body_as_json.size).to eq 1
end 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) } blocks = Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { max_id: blocks[1] } 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.size).to eq 1
expect(body_as_json[0][:id]).to eq blocks[0].target_account_id.to_s expect(body_as_json[0][:id]).to eq blocks[0].target_account_id.to_s
end 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) } blocks = Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { since_id: blocks[0] } 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.size).to eq 1
expect(body_as_json[0][:id]).to eq blocks[1].target_account_id.to_s expect(body_as_json[0][:id]).to eq blocks[1].target_account_id.to_s
end 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) } blocks = Array.new(2) { Fabricate(:block, account: user.account) }
get :index, params: { limit: 1, since_id: blocks[0] } 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]) expect(response.headers['Link'].find_link(%w(rel next)).href).to eq api_v1_blocks_url(limit: 1, max_id: blocks[1])
end 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) block = Fabricate(:block, account: user.account)
get :index 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).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 end
context 'with wrong scopes' do context 'with wrong scopes' do

View file

@ -21,17 +21,14 @@ RSpec.describe Api::V1::ConversationsController do
PostStatusService.new.call(user.account, text: 'Hey, nobody here', visibility: 'direct') PostStatusService.new.call(user.account, text: 'Hey, nobody here', visibility: 'direct')
end end
it 'returns http success' do it 'returns pagination headers', :aggregate_failures do
get :index
expect(response).to have_http_status(200)
end
it 'returns pagination headers' do
get :index, params: { limit: 1 } get :index, params: { limit: 1 }
expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2) expect(response.headers['Link'].links.size).to eq(2)
end end
it 'returns conversations' do it 'returns conversations', :aggregate_failures do
get :index get :index
json = body_as_json json = body_as_json
expect(json.size).to eq 2 expect(json.size).to eq 2

View file

@ -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

View file

@ -31,12 +31,10 @@ RSpec.describe Api::V1::FiltersController do
post :create, params: { phrase: 'magic', context: %w(home), irreversible: irreversible, whole_word: whole_word } post :create, params: { phrase: 'magic', context: %w(home), irreversible: irreversible, whole_word: whole_word }
end end
it 'returns http success' do it 'creates a filter', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'creates a filter' do
filter = user.account.custom_filters.first filter = user.account.custom_filters.first
expect(response).to have_http_status(200)
expect(filter).to_not be_nil expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]] expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]]
expect(filter.context).to eq %w(home) expect(filter.context).to eq %w(home)
@ -48,12 +46,10 @@ RSpec.describe Api::V1::FiltersController do
let(:irreversible) { false } let(:irreversible) { false }
let(:whole_word) { true } let(:whole_word) { true }
it 'returns http success' do it 'creates a filter', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'creates a filter' do
filter = user.account.custom_filters.first filter = user.account.custom_filters.first
expect(response).to have_http_status(200)
expect(filter).to_not be_nil expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]] expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]]
expect(filter.context).to eq %w(home) 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' } put :update, params: { id: keyword.id, phrase: 'updated' }
end end
it 'returns http success' do it 'updates the filter', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'updates the filter' do
expect(keyword.reload.phrase).to eq 'updated' expect(keyword.reload.phrase).to eq 'updated'
end end
end end
@ -101,11 +94,8 @@ RSpec.describe Api::V1::FiltersController do
delete :destroy, params: { id: keyword.id } delete :destroy, params: { id: keyword.id }
end end
it 'returns http success' do it 'removes the filter', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'removes the filter' do
expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound
end end
end end

View file

@ -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

View file

@ -5,7 +5,7 @@ require 'rails_helper'
describe Api::V1::Instances::TranslationLanguagesController do describe Api::V1::Instances::TranslationLanguagesController do
describe 'GET #show' do describe 'GET #show' do
context 'when no translation service is configured' 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 get :show
expect(response).to have_http_status(200) 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) allow(TranslationService).to receive_messages(configured?: true, configured: service)
end end
it 'returns language matrix' do it 'returns language matrix', :aggregate_failures do
get :show get :show
expect(response).to have_http_status(200) expect(response).to have_http_status(200)

View file

@ -35,11 +35,8 @@ describe Api::V1::Lists::AccountsController do
post :create, params: { list_id: list.id, account_ids: [bob.id] } post :create, params: { list_id: list.id, account_ids: [bob.id] }
end end
it 'returns http success' do it 'adds account to the list', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'adds account to the list' do
expect(list.accounts.include?(bob)).to be true expect(list.accounts.include?(bob)).to be true
end end
end end
@ -50,11 +47,8 @@ describe Api::V1::Lists::AccountsController do
post :create, params: { list_id: list.id, account_ids: [bob.id] } post :create, params: { list_id: list.id, account_ids: [bob.id] }
end end
it 'returns http success' do it 'adds account to the list', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'adds account to the list' do
expect(list.accounts.include?(bob)).to be true expect(list.accounts.include?(bob)).to be true
end end
end end
@ -64,11 +58,8 @@ describe Api::V1::Lists::AccountsController do
post :create, params: { list_id: list.id, account_ids: [bob.id] } post :create, params: { list_id: list.id, account_ids: [bob.id] }
end 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) 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 expect(list.accounts.include?(bob)).to be false
end end
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] } delete :destroy, params: { list_id: list.id, account_ids: [list.accounts.first.id] }
end end
it 'returns http success' do it 'removes account from the list', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'removes account from the list' do
expect(list.accounts.count).to eq 0 expect(list.accounts.count).to eq 0
end end
end end

View file

@ -18,13 +18,10 @@ RSpec.describe Api::V1::MarkersController do
get :index, params: { timeline: %w(home notifications) } get :index, params: { timeline: %w(home notifications) }
end end
it 'returns http success' do it 'returns markers', :aggregate_failures do
expect(response).to have_http_status(200)
end
it 'returns markers' do
json = body_as_json json = body_as_json
expect(response).to have_http_status(200)
expect(json.key?(:home)).to be true expect(json.key?(:home)).to be true
expect(json[:home][:last_read_id]).to eq '123' expect(json[:home][:last_read_id]).to eq '123'
expect(json.key?(:notifications)).to be true 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' } } post :create, params: { home: { last_read_id: '69420' } }
end end
it 'returns http success' do it 'creates a marker', :aggregate_failures do
expect(response).to have_http_status(200) 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.timeline).to eq 'home'
expect(user.markers.first.last_read_id).to eq 69_420 expect(user.markers.first.last_read_id).to eq 69_420
end end
@ -54,11 +48,8 @@ RSpec.describe Api::V1::MarkersController do
post :create, params: { home: { last_read_id: '70120' } } post :create, params: { home: { last_read_id: '70120' } }
end end
it 'returns http success' do it 'updates a marker', :aggregate_failures do
expect(response).to have_http_status(200) 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.timeline).to eq 'home'
expect(user.markers.first.last_read_id).to eq 70_120 expect(user.markers.first.last_read_id).to eq 70_120
end end

View file

@ -38,19 +38,10 @@ RSpec.describe Api::V1::MediaController do
post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') } post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
end end
it 'returns http success' do it 'creates a media attachment', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'creates a media attachment' do
expect(MediaAttachment.first).to_not be_nil expect(MediaAttachment.first).to_not be_nil
end
it 'uploads a file' do
expect(MediaAttachment.first).to have_attached_file(:file) 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 expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
end end
end end
@ -60,19 +51,10 @@ RSpec.describe Api::V1::MediaController do
post :create, params: { file: fixture_file_upload('attachment.gif', 'image/gif') } post :create, params: { file: fixture_file_upload('attachment.gif', 'image/gif') }
end end
it 'returns http success' do it 'creates a media attachment', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'creates a media attachment' do
expect(MediaAttachment.first).to_not be_nil expect(MediaAttachment.first).to_not be_nil
end
it 'uploads a file' do
expect(MediaAttachment.first).to have_attached_file(:file) 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 expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
end end
end end
@ -82,17 +64,10 @@ RSpec.describe Api::V1::MediaController do
post :create, params: { file: fixture_file_upload('attachment.webm', 'video/webm') } post :create, params: { file: fixture_file_upload('attachment.webm', 'video/webm') }
end end
it do it 'creates a media attachment', :aggregate_failures do
# returns http success
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
# creates a media attachment
expect(MediaAttachment.first).to_not be_nil expect(MediaAttachment.first).to_not be_nil
# uploads a file
expect(MediaAttachment.first).to have_attached_file(: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 expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
end end
end end

View file

@ -18,18 +18,13 @@ RSpec.describe Api::V1::Polls::VotesController do
post :create, params: { poll_id: poll.id, choices: %w(1) } post :create, params: { poll_id: poll.id, choices: %w(1) }
end end
it 'returns http success' do it 'creates a vote', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'creates a vote' do
vote = poll.votes.where(account: user.account).first vote = poll.votes.where(account: user.account).first
expect(vote).to_not be_nil expect(vote).to_not be_nil
expect(vote.choice).to eq 1 expect(vote.choice).to eq 1
end
it 'updates poll tallies' do
expect(poll.reload.cached_tallies).to eq [0, 1] expect(poll.reload.cached_tallies).to eq [0, 1]
end end
end end

View file

@ -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

View file

@ -21,11 +21,8 @@ describe Api::V1::Statuses::MutesController do
post :create, params: { status_id: status.id } post :create, params: { status_id: status.id }
end end
it 'returns http success' do it 'creates a conversation mute', :aggregate_failures do
expect(response).to have_http_status(200) 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 expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to_not be_nil
end end
end end
@ -38,11 +35,8 @@ describe Api::V1::Statuses::MutesController do
post :destroy, params: { status_id: status.id } post :destroy, params: { status_id: status.id }
end end
it 'returns http success' do it 'destroys the conversation mute', :aggregate_failures do
expect(response).to have_http_status(200) 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 expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to be_nil
end end
end end

View file

@ -24,14 +24,12 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController do
Fabricate(:status, account: bob, reblog_of_id: status.id) Fabricate(:status, account: bob, reblog_of_id: status.id)
end 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 } get :index, params: { status_id: status.id, limit: 2 }
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2) 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.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) expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
end end

View file

@ -28,19 +28,13 @@ describe Api::V1::Statuses::ReblogsController do
end end
context 'with public status' do context 'with public status' do
it 'returns http success' do it 'reblogs the status', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 1 expect(status.reblogs.count).to eq 1
end
it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be true expect(user.account.reblogged?(status)).to be true
end
it 'returns json with updated attributes' do
hash_body = body_as_json hash_body = body_as_json
expect(hash_body[:reblog][:id]).to eq status.id.to_s 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 } post :destroy, params: { status_id: status.id }
end end
it 'returns http success' do it 'destroys the reblog', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 0 expect(status.reblogs.count).to eq 0
end
it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be false expect(user.account.reblogged?(status)).to be false
end
it 'returns json with updated attributes' do
hash_body = body_as_json hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s 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 } post :destroy, params: { status_id: status.id }
end end
it 'returns http success' do it 'destroys the reblog', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 0 expect(status.reblogs.count).to eq 0
end
it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be false expect(user.account.reblogged?(status)).to be false
end
it 'returns json with updated attributes' do
hash_body = body_as_json hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s expect(hash_body[:id]).to eq status.id.to_s

View file

@ -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

View file

@ -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' }]) user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide, keywords_attributes: [{ keyword: 'banned' }, { keyword: 'irrelevant' }])
end end
it 'returns http success' do it 'returns filter information', :aggregate_failures do
get :show, params: { id: status.id }
expect(response).to have_http_status(200)
end
it 'returns filter information' do
get :show, params: { id: status.id } get :show, params: { id: status.id }
json = body_as_json json = body_as_json
expect(response).to have_http_status(200)
expect(json[:filtered][0]).to include({ expect(json[:filtered][0]).to include({
filter: a_hash_including({ filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s, 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) filter.statuses.create!(status_id: status.id)
end end
it 'returns http success' do it 'returns filter information', :aggregate_failures do
get :show, params: { id: status.id }
expect(response).to have_http_status(200)
end
it 'returns filter information' do
get :show, params: { id: status.id } get :show, params: { id: status.id }
json = body_as_json json = body_as_json
expect(response).to have_http_status(200)
expect(json[:filtered][0]).to include({ expect(json[:filtered][0]).to include({
filter: a_hash_including({ filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s, 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' }]) user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide, keywords_attributes: [{ keyword: 'banned' }, { keyword: 'irrelevant' }])
end end
it 'returns http success' do it 'returns filter information', :aggregate_failures do
get :show, params: { id: status.id }
expect(response).to have_http_status(200)
end
it 'returns filter information' do
get :show, params: { id: status.id } get :show, params: { id: status.id }
json = body_as_json json = body_as_json
expect(response).to have_http_status(200)
expect(json[:reblog][:filtered][0]).to include({ expect(json[:reblog][:filtered][0]).to include({
filter: a_hash_including({ filter: a_hash_including({
id: user.account.custom_filters.first.id.to_s, 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' } post :create, params: { status: 'Hello world' }
end end
it 'returns http success' do it 'returns rate limit headers', :aggregate_failures do
expect(response).to have_http_status(200) 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-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
expect(response.headers['X-RateLimit-Remaining']).to eq (RateLimiter::FAMILIES[:statuses][:limit] - 1).to_s expect(response.headers['X-RateLimit-Remaining']).to eq (RateLimiter::FAMILIES[:statuses][:limit] - 1).to_s
end 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] } post :create, params: { status: '@alice hm, @bob is really annoying lately', allowed_mentions: [alice.id] }
end end
it 'returns http unprocessable entity' do it 'returns serialized extra accounts in body', :aggregate_failures do
expect(response).to have_http_status(422) 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 }] expect(body_as_json[:unexpected_accounts].map { |a| a.slice(:id, :acct) }).to eq [{ id: bob.id.to_s, acct: bob.acct }]
end end
end end
@ -157,11 +142,8 @@ RSpec.describe Api::V1::StatusesController do
post :create, params: {} post :create, params: {}
end end
it 'returns http unprocessable entity' do it 'returns rate limit headers', :aggregate_failures do
expect(response).to have_http_status(422) 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 expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
end end
end end
@ -173,11 +155,8 @@ RSpec.describe Api::V1::StatusesController do
post :create, params: { status: 'Hello world' } post :create, params: { status: 'Hello world' }
end end
it 'returns http too many requests' do it 'returns rate limit headers', :aggregate_failures do
expect(response).to have_http_status(429) 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-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
expect(response.headers['X-RateLimit-Remaining']).to eq '0' expect(response.headers['X-RateLimit-Remaining']).to eq '0'
end end
@ -192,11 +171,8 @@ RSpec.describe Api::V1::StatusesController do
post :destroy, params: { id: status.id } post :destroy, params: { id: status.id }
end end
it 'returns http success' do it 'removes the status', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'removes the status' do
expect(Status.find_by(id: status.id)).to be_nil expect(Status.find_by(id: status.id)).to be_nil
end end
end end
@ -209,11 +185,8 @@ RSpec.describe Api::V1::StatusesController do
put :update, params: { id: status.id, status: 'I am updated' } put :update, params: { id: status.id, status: 'I am updated' }
end end
it 'returns http success' do it 'updates the status', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'updates the status' do
expect(status.reload.text).to eq 'I am updated' expect(status.reload.text).to eq 'I am updated'
end end
end end

View file

@ -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

View file

@ -44,14 +44,14 @@ RSpec.describe Api::V2::Admin::AccountsController do
context "when called with #{params.inspect}" do context "when called with #{params.inspect}" do
let(:params) { params } 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(response).to have_http_status(200)
expect(body_json_ids).to eq(expected_results.map { |symbol| send(symbol).id })
end end
it "returns the correct accounts (#{expected_results.inspect})" do def body_json_ids
json = body_as_json body_as_json.map { |a| a[:id].to_i }
expect(json.map { |a| a[:id].to_i }).to eq(expected_results.map { |symbol| send(symbol).id })
end end
end end
end end

View file

@ -40,17 +40,13 @@ RSpec.describe Api::V2::Filters::KeywordsController do
post :create, params: { filter_id: filter_id, keyword: 'magic', whole_word: false } post :create, params: { filter_id: filter_id, keyword: 'magic', whole_word: false }
end end
it 'returns http success' do it 'creates a filter', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns a keyword' do
json = body_as_json json = body_as_json
expect(json[:keyword]).to eq 'magic' expect(json[:keyword]).to eq 'magic'
expect(json[:whole_word]).to be false expect(json[:whole_word]).to be false
end
it 'creates a keyword' do
filter = user.account.custom_filters.first filter = user.account.custom_filters.first
expect(filter).to_not be_nil expect(filter).to_not be_nil
expect(filter.keywords.pluck(:keyword)).to eq ['magic'] 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 } get :show, params: { id: keyword.id }
end end
it 'returns http success' do it 'responds with the keyword', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns expected data' do
json = body_as_json json = body_as_json
expect(json[:keyword]).to eq 'foo' expect(json[:keyword]).to eq 'foo'
expect(json[:whole_word]).to be false 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' } get :update, params: { id: keyword.id, keyword: 'updated' }
end end
it 'returns http success' do it 'updates the keyword', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'updates the keyword' do
expect(keyword.reload.keyword).to eq 'updated' expect(keyword.reload.keyword).to eq 'updated'
end end
@ -125,11 +117,9 @@ RSpec.describe Api::V2::Filters::KeywordsController do
delete :destroy, params: { id: keyword.id } delete :destroy, params: { id: keyword.id }
end end
it 'returns http success' do it 'destroys the keyword', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'removes the filter' do
expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound
end end

View file

@ -41,16 +41,12 @@ RSpec.describe Api::V2::Filters::StatusesController do
post :create, params: { filter_id: filter_id, status_id: status.id } post :create, params: { filter_id: filter_id, status_id: status.id }
end end
it 'returns http success' do it 'creates a filter', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns a status filter' do
json = body_as_json json = body_as_json
expect(json[:status_id]).to eq status.id.to_s expect(json[:status_id]).to eq status.id.to_s
end
it 'creates a status filter' do
filter = user.account.custom_filters.first filter = user.account.custom_filters.first
expect(filter).to_not be_nil expect(filter).to_not be_nil
expect(filter.statuses.pluck(:status_id)).to eq [status.id] 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 } get :show, params: { id: status_filter.id }
end end
it 'returns http success' do it 'responds with the filter', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns expected data' do
json = body_as_json json = body_as_json
expect(json[:status_id]).to eq status_filter.status_id.to_s expect(json[:status_id]).to eq status_filter.status_id.to_s
end end
@ -99,11 +93,9 @@ RSpec.describe Api::V2::Filters::StatusesController do
delete :destroy, params: { id: status_filter.id } delete :destroy, params: { id: status_filter.id }
end end
it 'returns http success' do it 'destroys the filter', :aggregate_failures do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'removes the filter' do
expect { status_filter.reload }.to raise_error ActiveRecord::RecordNotFound expect { status_filter.reload }.to raise_error ActiveRecord::RecordNotFound
end end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -562,6 +562,44 @@ RSpec.describe FeedManager do
end end
end end
describe '#unmerge_tag_from_home' do
let(:receiver) { Fabricate(:account) }
let(:tag) { Fabricate(:tag) }
it 'leaves a tagged status' do
status = Fabricate(:status)
status.tags << tag
described_class.instance.push_to_home(receiver, status)
described_class.instance.unmerge_tag_from_home(tag, receiver)
expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to_not include(status.id.to_s)
end
it 'remains a tagged status written by receiver\'s followee' do
followee = Fabricate(:account)
receiver.follow!(followee)
status = Fabricate(:status, account: followee)
status.tags << tag
described_class.instance.push_to_home(receiver, status)
described_class.instance.unmerge_tag_from_home(tag, receiver)
expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s)
end
it 'remains a tagged status written by receiver' do
status = Fabricate(:status, account: receiver)
status.tags << tag
described_class.instance.push_to_home(receiver, status)
described_class.instance.unmerge_tag_from_home(tag, receiver)
expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s)
end
end
describe '#clear_from_home' do describe '#clear_from_home' do
let(:account) { Fabricate(:account) } let(:account) { Fabricate(:account) }
let(:followed_account) { Fabricate(:account) } let(:followed_account) { Fabricate(:account) }

View file

@ -54,26 +54,6 @@ Devise::Test::ControllerHelpers.module_eval do
end end
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| RSpec.configure do |config|
# This is set before running spec:system, see lib/tasks/tests.rake # This is set before running spec:system, see lib/tasks/tests.rake
config.filter_run_excluding type: lambda { |type| config.filter_run_excluding type: lambda { |type|

View file

@ -51,14 +51,9 @@ RSpec.describe 'Account actions' do
it_behaves_like 'a successful notification delivery' it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :disable, :user 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 it 'disables the target account' do
expect { subject }.to change { target_account.reload.user_disabled? }.from(false).to(true) expect { subject }.to change { target_account.reload.user_disabled? }.from(false).to(true)
expect(response).to have_http_status(200)
end end
end end
@ -70,14 +65,9 @@ RSpec.describe 'Account actions' do
it_behaves_like 'a successful notification delivery' it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :sensitive, :account 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 it 'marks the target account as sensitive' do
expect { subject }.to change { target_account.reload.sensitized? }.from(false).to(true) expect { subject }.to change { target_account.reload.sensitized? }.from(false).to(true)
expect(response).to have_http_status(200)
end end
end end
@ -89,14 +79,9 @@ RSpec.describe 'Account actions' do
it_behaves_like 'a successful notification delivery' it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :silence, :account 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 it 'marks the target account as silenced' do
expect { subject }.to change { target_account.reload.silenced? }.from(false).to(true) expect { subject }.to change { target_account.reload.silenced? }.from(false).to(true)
expect(response).to have_http_status(200)
end end
end end
@ -108,14 +93,9 @@ RSpec.describe 'Account actions' do
it_behaves_like 'a successful notification delivery' it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :suspend, :account 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 it 'marks the target account as suspended' do
expect { subject }.to change { target_account.reload.suspended? }.from(false).to(true) expect { subject }.to change { target_account.reload.suspended? }.from(false).to(true)
expect(response).to have_http_status(200)
end end
end end

View file

@ -92,15 +92,10 @@ RSpec.describe 'Canonical Email Blocks' do
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
context 'when the requested canonical email block exists' do 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 subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns the requested canonical email block data correctly' do
subject
json = body_as_json json = body_as_json
expect(json[:id]).to eq(canonical_email_block.id.to_s) 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 context 'when there is a matching canonical email block' do
let!(:canonical_email_block) { CanonicalEmailBlock.create(params) } let!(:canonical_email_block) { CanonicalEmailBlock.create(params) }
it 'returns http success' do it 'returns the expected canonical email hash', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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) expect(body_as_json[0][:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
end end
end end
context 'when there is no matching canonical email block' do context 'when there is no matching canonical email block' do
it 'returns http success' do it 'returns an empty list', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns an empty list' do
subject
expect(body_as_json).to be_empty expect(body_as_json).to be_empty
end end
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', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'returns the canonical_email_hash correctly', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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) expect(body_as_json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
end end
@ -208,15 +188,10 @@ RSpec.describe 'Canonical Email Blocks' do
context 'when the canonical_email_hash param is provided instead of email' do context 'when the canonical_email_hash param is provided instead of email' do
let(:params) { { canonical_email_hash: 'dd501ce4e6b08698f19df96f2f15737e48a75660b1fa79b6ff58ea25ee4851a4' } } let(:params) { { canonical_email_hash: 'dd501ce4e6b08698f19df96f2f15737e48a75660b1fa79b6ff58ea25ee4851a4' } }
it 'returns http success' do it 'returns the correct canonical_email_hash', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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]) expect(body_as_json[:canonical_email_hash]).to eq(params[:canonical_email_hash])
end end
end end
@ -224,15 +199,10 @@ RSpec.describe 'Canonical Email Blocks' do
context 'when both email and canonical_email_hash params are provided' do context 'when both email and canonical_email_hash params are provided' do
let(:params) { { email: 'example@email.com', canonical_email_hash: 'dd501ce4e6b08698f19df96f2f15737e48a75660b1fa79b6ff58ea25ee4851a4' } } 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 subject
expect(response).to have_http_status(200) 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) expect(body_as_json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
end end
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', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'deletes the canonical email block', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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 expect(CanonicalEmailBlock.find_by(id: canonical_email_block.id)).to be_nil
end end

View file

@ -75,15 +75,10 @@ RSpec.describe 'Domain Allows' do
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'returns the expected allowed domain name', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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 expect(body_as_json[:domain]).to eq domain_allow.domain
end end
@ -108,21 +103,11 @@ RSpec.describe 'Domain Allows' do
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
context 'with a valid domain name' do context 'with a valid domain name' do
it 'returns http success' do it 'returns the expected domain name', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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' 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 expect(DomainAllow.find_by(domain: 'foo.bar.com')).to be_present
end end
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', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'deletes the allowed domain', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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 expect(DomainAllow.find_by(id: domain_allow.id)).to be_nil
end end

View file

@ -143,16 +143,23 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'returns the expected domain block content', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end expect(body_as_json).to eq(
{
it 'returns the expected domain block content' do id: domain_block.id.to_s,
subject domain: domain_block.domain,
created_at: domain_block.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ'),
expect(body_as_json).to eq(expected_response) 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
context 'when the requested domain block does not exist' do context 'when the requested domain block does not exist' do
@ -175,27 +182,18 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'returns expected domain name and severity', :aggregate_failures do
subject
expect(response).to have_http_status(200)
end
it 'returns expected domain name and severity' do
subject subject
body = body_as_json body = body_as_json
expect(response).to have_http_status(200)
expect(body).to match a_hash_including( expect(body).to match a_hash_including(
{ {
domain: 'foo.bar.com', domain: 'foo.bar.com',
severity: 'silence', severity: 'silence',
} }
) )
end
it 'creates a domain block' do
subject
expect(DomainBlock.find_by(domain: 'foo.bar.com')).to be_present expect(DomainBlock.find_by(domain: 'foo.bar.com')).to be_present
end end
@ -205,15 +203,10 @@ RSpec.describe 'Domain Blocks' do
Fabricate(:domain_block, domain: 'bar.com', severity: :suspend) Fabricate(:domain_block, domain: 'bar.com', severity: :suspend)
end end
it 'returns http unprocessable entity' do it 'returns existing domain block in error', :aggregate_failures do
subject subject
expect(response).to have_http_status(422) 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') expect(body_as_json[:existing_domain_block][:domain]).to eq('bar.com')
end end
end end
@ -241,15 +234,10 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'returns the updated domain block', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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( expect(body_as_json).to match a_hash_including(
{ {
id: domain_block.id.to_s, id: domain_block.id.to_s,
@ -283,15 +271,10 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'deletes the domain block', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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 expect(DomainBlock.find_by(id: domain_block.id)).to be_nil
end end

View file

@ -93,15 +93,10 @@ RSpec.describe 'Email Domain Blocks' do
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
context 'when email domain block exists' do context 'when email domain block exists' do
it 'returns http success' do it 'returns the correct blocked domain', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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) expect(body_as_json[:domain]).to eq(email_domain_block.domain)
end end
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', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'returns the correct blocked email domain', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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]) expect(body_as_json[:domain]).to eq(params[:domain])
end 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', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'deletes email domain block', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns an empty body' do
subject
expect(body_as_json).to be_empty 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 expect(EmailDomainBlock.find_by(id: email_domain_block.id)).to be_nil
end end

View file

@ -84,15 +84,10 @@ RSpec.describe 'IP Blocks' do
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'returns the correct ip block', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns the correct ip block' do
subject
json = body_as_json json = body_as_json
expect(json[:ip]).to eq("#{ip_block.ip}/#{ip_block.ip.prefix}") 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', ''
it_behaves_like 'forbidden for wrong role', 'Moderator' it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do it 'returns the correct ip block', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns the correct ip block' do
subject
json = body_as_json json = body_as_json
expect(json[:ip]).to eq("#{params[:ip]}/32") 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!(: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' } } 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 subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns the correct ip block' do
subject
expect(body_as_json).to match(hash_including({ expect(body_as_json).to match(hash_including({
ip: "#{ip_block.ip}/#{ip_block.ip.prefix}", ip: "#{ip_block.ip}/#{ip_block.ip.prefix}",
severity: 'sign_up_requires_approval', 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') } 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 subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns an empty body' do
subject
expect(body_as_json).to be_empty 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 expect(IpBlock.find_by(id: ip_block.id)).to be_nil
end end

View file

@ -122,15 +122,10 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do it 'returns the requested report content', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns the requested report content' do
subject
expect(body_as_json).to include( expect(body_as_json).to include(
{ {
id: report.id.to_s, id: report.id.to_s,
@ -155,18 +150,10 @@ RSpec.describe 'Reports' do
let!(:report) { Fabricate(:report, category: :other) } let!(:report) { Fabricate(:report, category: :other) }
let(:params) { { category: 'spam' } } let(:params) { { category: 'spam' } }
it 'returns http success' do it 'updates the report category', :aggregate_failures do
subject expect { subject }.to change { report.reload.category }.from('other').to('spam')
expect(response).to have_http_status(200) 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 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 scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do it 'marks report as resolved', :aggregate_failures do
subject
expect(response).to have_http_status(200)
end
it 'marks report as resolved' do
expect { subject }.to change { report.reload.unresolved? }.from(true).to(false) expect { subject }.to change { report.reload.unresolved? }.from(true).to(false)
expect(response).to have_http_status(200)
end end
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 scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do it 'marks report as unresolved', :aggregate_failures do
subject
expect(response).to have_http_status(200)
end
it 'marks report as unresolved' do
expect { subject }.to change { report.reload.unresolved? }.from(false).to(true) expect { subject }.to change { report.reload.unresolved? }.from(false).to(true)
expect(response).to have_http_status(200)
end end
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 scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do it 'assigns report to the requesting user', :aggregate_failures do
subject
expect(response).to have_http_status(200)
end
it 'assigns report to the requesting user' do
expect { subject }.to change { report.reload.assigned_account_id }.from(nil).to(user.account.id) expect { subject }.to change { report.reload.assigned_account_id }.from(nil).to(user.account.id)
expect(response).to have_http_status(200)
end end
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 scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do it 'unassigns report from assignee', :aggregate_failures do
subject
expect(response).to have_http_status(200)
end
it 'unassigns report from assignee' do
expect { subject }.to change { report.reload.assigned_account_id }.from(user.account.id).to(nil) 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 end
end end

View file

@ -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

View file

@ -12,14 +12,10 @@ describe 'Credentials' do
let(:token) { Fabricate(:accessible_access_token, scopes: 'read', application: Fabricate(:application)) } let(:token) { Fabricate(:accessible_access_token, scopes: 'read', application: Fabricate(:application)) }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
it 'returns http success' do it 'returns the app information correctly', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns the app information correctly' do
subject
expect(body_as_json).to match( expect(body_as_json).to match(
a_hash_including( a_hash_including(

View file

@ -23,20 +23,11 @@ RSpec.describe 'Apps' do
end end
context 'with valid params' do context 'with valid params' do
it 'returns http success' do it 'creates an OAuth app', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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 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 body = body_as_json
@ -58,15 +49,10 @@ RSpec.describe 'Apps' do
context 'with many duplicate scopes' do context 'with many duplicate scopes' do
let(:scopes) { (%w(read) * 40).join(' ') } let(:scopes) { (%w(read) * 40).join(' ') }
it 'returns http success' do it 'only saves the scope once', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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' expect(Doorkeeper::Application.find_by(name: client_name).scopes.to_s).to eq 'read'
end end
end end

View file

@ -22,15 +22,10 @@ RSpec.describe 'Domain blocks' do
it_behaves_like 'forbidden for wrong scope', 'write:blocks' 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 subject
expect(response).to have_http_status(200) 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) expect(body_as_json).to match_array(blocked_domains)
end end
@ -54,15 +49,10 @@ RSpec.describe 'Domain blocks' do
it_behaves_like 'forbidden for wrong scope', 'read read:blocks' it_behaves_like 'forbidden for wrong scope', 'read read:blocks'
it 'returns http success' do it 'creates a domain block', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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) expect(user.account.domain_blocking?(params[:domain])).to be(true)
end end
@ -100,15 +90,10 @@ RSpec.describe 'Domain blocks' do
it_behaves_like 'forbidden for wrong scope', 'read read:blocks' 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 subject
expect(response).to have_http_status(200) 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) expect(user.account.domain_blocking?('example.com')).to be(false)
end end

View file

@ -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

View file

@ -32,15 +32,10 @@ RSpec.describe 'Follow requests' do
it_behaves_like 'forbidden for wrong scope', 'write write:follows' 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 subject
expect(response).to have_http_status(200) 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) expect(body_as_json).to match_array(expected_response)
end end
@ -68,19 +63,9 @@ RSpec.describe 'Follow requests' do
it_behaves_like 'forbidden for wrong scope', 'read read:follows' it_behaves_like 'forbidden for wrong scope', 'read read:follows'
it 'returns http success' do it 'allows the requesting follower to follow', :aggregate_failures do
subject
expect(response).to have_http_status(200)
end
it 'allows the requesting follower to follow' do
expect { subject }.to change { follower.following?(user.account) }.from(false).to(true) expect { subject }.to change { follower.following?(user.account) }.from(false).to(true)
end expect(response).to have_http_status(200)
it 'returns JSON with followed_by set to true' do
subject
expect(body_as_json[:followed_by]).to be true expect(body_as_json[:followed_by]).to be true
end end
end end
@ -98,21 +83,11 @@ RSpec.describe 'Follow requests' do
it_behaves_like 'forbidden for wrong scope', 'read read:follows' it_behaves_like 'forbidden for wrong scope', 'read read:follows'
it 'returns http success' do it 'removes the follow request', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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 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 expect(body_as_json[:followed_by]).to be false
end end
end end

View file

@ -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

View file

@ -51,16 +51,11 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'write write:lists' it_behaves_like 'forbidden for wrong scope', 'write write:lists'
it 'returns http success' do it 'returns the expected lists', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end expect(body_as_json).to match_array(expected_response)
it 'returns the expected lists' do
subject
expect(body_as_json).to match_array(expected_response_with_antennas)
end end
end end
@ -73,15 +68,10 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'write write:lists' 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 subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns the requested list correctly' do
subject
expect(body_as_json).to eq({ expect(body_as_json).to eq({
id: list.id.to_s, id: list.id.to_s,
title: list.title, title: list.title,
@ -119,21 +109,11 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'read read:lists' it_behaves_like 'forbidden for wrong scope', 'read read:lists'
it 'returns http success' do it 'returns the new list', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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)) 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) expect(List.where(account: user.account).count).to eq(1)
end end
@ -168,15 +148,10 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'read read:lists' it_behaves_like 'forbidden for wrong scope', 'read read:lists'
it 'returns http success' do it 'returns the updated list', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns the updated list' do
subject
list.reload list.reload
expect(body_as_json).to eq({ expect(body_as_json).to eq({
@ -228,15 +203,10 @@ RSpec.describe 'Lists' do
it_behaves_like 'forbidden for wrong scope', 'read read:lists' it_behaves_like 'forbidden for wrong scope', 'read read:lists'
it 'returns http success' do it 'deletes the list', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'deletes the list' do
subject
expect(List.where(id: list.id)).to_not exist expect(List.where(id: list.id)).to_not exist
end end

View file

@ -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

View file

@ -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

View file

@ -17,15 +17,10 @@ RSpec.describe 'Tags' do
let!(:tag) { Fabricate(:tag) } let!(:tag) { Fabricate(:tag) }
let(:name) { tag.name } let(:name) { tag.name }
it 'returns http success' do it 'returns the tag', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end
it 'returns the tag' do
subject
expect(body_as_json[:name]).to eq(name) expect(body_as_json[:name]).to eq(name)
end end
end end
@ -62,15 +57,10 @@ RSpec.describe 'Tags' do
it_behaves_like 'forbidden for wrong scope', 'read read:follows' it_behaves_like 'forbidden for wrong scope', 'read read:follows'
context 'when the tag exists' do context 'when the tag exists' do
it 'returns http success' do it 'creates follow', :aggregate_failures do
subject subject
expect(response).to have_http_status(:success) expect(response).to have_http_status(:success)
end
it 'creates follow' do
subject
expect(TagFollow.where(tag: tag, account: user.account)).to exist expect(TagFollow.where(tag: tag, account: user.account)).to exist
end end
end end
@ -78,21 +68,11 @@ RSpec.describe 'Tags' do
context 'when the tag does not exist' do context 'when the tag does not exist' do
let(:name) { 'hoge' } let(:name) { 'hoge' }
it 'returns http success' do it 'creates a new tag with the specified name', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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 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 expect(TagFollow.where(tag: Tag.find_by(name: name), account: user.account)).to exist
end end
end end
@ -133,15 +113,10 @@ RSpec.describe 'Tags' do
it_behaves_like 'forbidden for wrong scope', 'read read:follows' it_behaves_like 'forbidden for wrong scope', 'read read:follows'
it 'returns http success' do it 'removes the follow', :aggregate_failures do
subject subject
expect(response).to have_http_status(200) 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 expect(TagFollow.where(tag: tag, account: user.account)).to_not exist
end end

View file

@ -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

View file

@ -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

View file

@ -67,39 +67,31 @@ describe MoveWorker do
end end
shared_examples 'block and mute handling' do 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) subject.perform(source_account.id, target_account.id)
expect(block_service).to have_received(:call).with(blocking_account, target_account) 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) 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(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) expect(AccountNote.find_by(account: muting_account, target_account: target_account).comment).to include(source_account.acct)
end end
end end
shared_examples 'followers count handling' do 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) 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 expect(source_account.reload.followers_count).to eq(source_account.passive_relationships.count)
subject.perform(source_account.id, target_account.id)
expect(target_account.reload.followers_count).to eq(target_account.passive_relationships.count) expect(target_account.reload.followers_count).to eq(target_account.passive_relationships.count)
end end
end end
shared_examples 'lists handling' do 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) 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 expect(list.accounts.include?(target_account)).to be true
subject.perform(source_account.id, target_account.id)
expect(ListAccount.all).to all be_valid expect(ListAccount.all).to all be_valid
end end
end end