Merge remote-tracking branch 'parent/main' into upstream-20231120
This commit is contained in:
commit
abec232dd7
85 changed files with 1314 additions and 458 deletions
4
.github/workflows/test-ruby.yml
vendored
4
.github/workflows/test-ruby.yml
vendored
|
@ -229,7 +229,7 @@ jobs:
|
|||
path: tmp/screenshots/
|
||||
|
||||
test-search:
|
||||
name: Testing search
|
||||
name: Elastic Search integration testing
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
|
@ -329,7 +329,7 @@ jobs:
|
|||
- name: Load database schema
|
||||
run: './bin/rails db:create db:schema:load db:seed'
|
||||
|
||||
- run: bundle exec rake spec:search
|
||||
- run: bin/rspec --tag search
|
||||
|
||||
- name: Archive logs
|
||||
uses: actions/upload-artifact@v3
|
||||
|
|
|
@ -38,6 +38,7 @@ RUN apt-get update && \
|
|||
corepack enable
|
||||
|
||||
COPY Gemfile* package.json yarn.lock .yarnrc.yml /opt/mastodon/
|
||||
COPY streaming/package.json /opt/mastodon/streaming/
|
||||
COPY .yarn /opt/mastodon/.yarn
|
||||
|
||||
RUN bundle install -j"$(nproc)"
|
||||
|
|
3
Gemfile
3
Gemfile
|
@ -109,6 +109,9 @@ group :test do
|
|||
# RSpec progress bar formatter
|
||||
gem 'fuubar', '~> 2.5'
|
||||
|
||||
# RSpec helpers for email specs
|
||||
gem 'email_spec'
|
||||
|
||||
# Extra RSpec extenion methods and helpers for sidekiq
|
||||
gem 'rspec-sidekiq', '~> 4.0'
|
||||
|
||||
|
|
|
@ -260,6 +260,10 @@ GEM
|
|||
elasticsearch-transport (7.13.3)
|
||||
faraday (~> 1)
|
||||
multi_json
|
||||
email_spec (2.2.2)
|
||||
htmlentities (~> 4.3.3)
|
||||
launchy (~> 2.1)
|
||||
mail (~> 2.7)
|
||||
encryptor (3.0.0)
|
||||
erubi (1.12.0)
|
||||
et-orbi (1.2.7)
|
||||
|
@ -855,6 +859,7 @@ DEPENDENCIES
|
|||
doorkeeper (~> 5.6)
|
||||
dotenv-rails (~> 2.8)
|
||||
ed25519 (~> 1.3)
|
||||
email_spec
|
||||
fabrication (~> 2.30)
|
||||
faker (~> 3.2)
|
||||
fast_blank (~> 1.0)
|
||||
|
|
|
@ -32,6 +32,9 @@ DB_USER=postgres DB_PASS=password foreman start
|
|||
RAILS_ENV=test bundle exec rspec spec
|
||||
|
||||
# ElasticSearch連携テストを行う
|
||||
新
|
||||
RAILS_ENV=test ES_ENABLED=true bundle exec rspec --tag search
|
||||
旧
|
||||
RAILS_ENV=test ES_ENABLED=true RUN_SEARCH_SPECS=true bundle exec rspec spec/search
|
||||
```
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
|
|||
import classNames from 'classnames';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { ReactComponent as AddPhotoAlternateIcon } from '@material-symbols/svg-600/outlined/add_photo_alternate.svg';
|
||||
import { ReactComponent as EditIcon } from '@material-symbols/svg-600/outlined/edit.svg';
|
||||
|
@ -33,7 +33,6 @@ export const Profile = () => {
|
|||
const [avatar, setAvatar] = useState(null);
|
||||
const [header, setHeader] = useState(null);
|
||||
const [discoverable, setDiscoverable] = useState(account.get('discoverable'));
|
||||
const [indexable, setIndexable] = useState(account.get('indexable'));
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
const [errors, setErrors] = useState();
|
||||
const avatarFileRef = createRef();
|
||||
|
@ -54,10 +53,6 @@ export const Profile = () => {
|
|||
setDiscoverable(e.target.checked);
|
||||
}, [setDiscoverable]);
|
||||
|
||||
const handleIndexableChange = useCallback(e => {
|
||||
setIndexable(e.target.checked);
|
||||
}, [setIndexable]);
|
||||
|
||||
const handleAvatarChange = useCallback(e => {
|
||||
setAvatar(e.target?.files?.[0]);
|
||||
}, [setAvatar]);
|
||||
|
@ -78,12 +73,12 @@ export const Profile = () => {
|
|||
avatar,
|
||||
header,
|
||||
discoverable,
|
||||
indexable,
|
||||
indexable: discoverable,
|
||||
})).then(() => history.push('/start/follows')).catch(err => {
|
||||
setIsSaving(false);
|
||||
setErrors(err.response.data.details);
|
||||
});
|
||||
}, [dispatch, displayName, note, avatar, header, discoverable, indexable, history]);
|
||||
}, [dispatch, displayName, note, avatar, header, discoverable, history]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -141,18 +136,21 @@ export const Profile = () => {
|
|||
<textarea id='note' value={note} onChange={handleNoteChange} maxLength={500} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label className='app-form__toggle'>
|
||||
<div className='app-form__toggle__label'>
|
||||
<strong><FormattedMessage id='onboarding.profile.discoverable' defaultMessage='Make my profile discoverable' /></strong> <span className='recommended'><FormattedMessage id='recommended' defaultMessage='Recommended' /></span>
|
||||
<span className='hint'><FormattedMessage id='onboarding.profile.discoverable_hint' defaultMessage='When you opt in to discoverability on Mastodon, your posts may appear in search results and trending, and your profile may be suggested to people with similar interests to you.' /></span>
|
||||
</div>
|
||||
|
||||
<div className='app-form__toggle__toggle'>
|
||||
<div>
|
||||
<Toggle checked={discoverable} onChange={handleDiscoverableChange} />
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label className='report-dialog-modal__toggle'>
|
||||
<Toggle checked={discoverable} onChange={handleDiscoverableChange} />
|
||||
<FormattedMessage id='onboarding.profile.discoverable' defaultMessage='Feature profile and posts in discovery algorithms' />
|
||||
</label>
|
||||
|
||||
<label className='report-dialog-modal__toggle'>
|
||||
<Toggle checked={indexable} onChange={handleIndexableChange} />
|
||||
<FormattedMessage id='onboarding.profile.indexable' defaultMessage='Include public posts in search results' />
|
||||
</label>
|
||||
|
||||
<div className='onboarding__footer'>
|
||||
<Button block onClick={handleSubmit} disabled={isSaving}>{isSaving ? <LoadingIndicator /> : <FormattedMessage id='onboarding.profile.save_and_continue' defaultMessage='Save and continue' />}</Button>
|
||||
</div>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Заблакіраваны",
|
||||
"account.browse_more_on_origin_server": "Глядзіце больш у арыгінальным профілі",
|
||||
"account.cancel_follow_request": "Скасаваць запыт на падпіску",
|
||||
"account.copy": "Скапіраваць спасылку на профіль",
|
||||
"account.direct": "Згадаць асабіста @{name}",
|
||||
"account.disable_notifications": "Не паведамляць мне пра публікацыі @{name}",
|
||||
"account.domain_blocked": "Дамен заблакаваны",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Адзначыць прачытаным",
|
||||
"conversation.open": "Прагледзець размову",
|
||||
"conversation.with": "З {names}",
|
||||
"copy_icon_button.copied": "Скапіявана ў буфер абмену",
|
||||
"copypaste.copied": "Скапіравана",
|
||||
"copypaste.copy_to_clipboard": "Капіраваць у буфер абмену",
|
||||
"directory.federated": "З вядомага федэсвету",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Blokovaný",
|
||||
"account.browse_more_on_origin_server": "Více na původním profilu",
|
||||
"account.cancel_follow_request": "Zrušit žádost o sledování",
|
||||
"account.copy": "Kopírovat odkaz na profil",
|
||||
"account.direct": "Soukromě zmínit @{name}",
|
||||
"account.disable_notifications": "Přestat mě upozorňovat, když @{name} zveřejní příspěvek",
|
||||
"account.domain_blocked": "Doména blokována",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Označit jako přečtené",
|
||||
"conversation.open": "Zobrazit konverzaci",
|
||||
"conversation.with": "S {names}",
|
||||
"copy_icon_button.copied": "Zkopírováno do schránky",
|
||||
"copypaste.copied": "Zkopírováno",
|
||||
"copypaste.copy_to_clipboard": "Zkopírovat do schránky",
|
||||
"directory.federated": "Ze známého fedivesmíru",
|
||||
|
|
|
@ -191,6 +191,7 @@
|
|||
"conversation.mark_as_read": "Nodi fel wedi'i ddarllen",
|
||||
"conversation.open": "Gweld sgwrs",
|
||||
"conversation.with": "Gyda {names}",
|
||||
"copy_icon_button.copied": "Copïwyd i'r clipfwrdd",
|
||||
"copypaste.copied": "Wedi ei gopïo",
|
||||
"copypaste.copy_to_clipboard": "Copïo i'r clipfwrdd",
|
||||
"directory.federated": "O'r ffedysawd cyfan",
|
||||
|
@ -390,6 +391,7 @@
|
|||
"lists.search": "Chwilio ymysg pobl rydych yn eu dilyn",
|
||||
"lists.subheading": "Eich rhestrau",
|
||||
"load_pending": "{count, plural, one {# eitem newydd} other {# eitem newydd}}",
|
||||
"loading_indicator.label": "Yn llwytho…",
|
||||
"media_gallery.toggle_visible": "{number, plural, one {Cuddio delwedd} other {Cuddio delwedd}}",
|
||||
"moved_to_account_banner.text": "Ar hyn y bryd, mae eich cyfrif {disabledAccount} wedi ei analluogi am i chi symud i {movedToAccount}.",
|
||||
"mute_modal.duration": "Hyd",
|
||||
|
@ -478,6 +480,11 @@
|
|||
"onboarding.follows.empty": "Yn anffodus, nid oes modd dangos unrhyw ganlyniadau ar hyn o bryd. Gallwch geisio defnyddio chwilio neu bori'r dudalen archwilio i ddod o hyd i bobl i'w dilyn, neu ceisio eto yn nes ymlaen.",
|
||||
"onboarding.follows.lead": "Rydych chi'n curadu eich ffrwd gartref eich hun. Po fwyaf o bobl y byddwch chi'n eu dilyn, y mwyaf egnïol a diddorol fydd hi. Gall y proffiliau hyn fod yn fan cychwyn da - gallwch chi bob amser eu dad-ddilyn yn nes ymlaen:",
|
||||
"onboarding.follows.title": "Yn boblogaidd ar Mastodon",
|
||||
"onboarding.profile.display_name_hint": "Eich enw llawn neu'ch enw hwyl…",
|
||||
"onboarding.profile.note": "Bywgraffiad",
|
||||
"onboarding.profile.note_hint": "Gallwch @grybwyll pobl eraill neu #hashnodau…",
|
||||
"onboarding.profile.save_and_continue": "Cadw a pharhau",
|
||||
"onboarding.profile.title": "Gosodiad proffil",
|
||||
"onboarding.share.lead": "Cofiwch ddweud wrth bobl sut y gallan nhw ddod o hyd i chi ar Mastodon!",
|
||||
"onboarding.share.message": "Fi yw {username} ar #Mastodon! Dewch i'm dilyn i yn {url}",
|
||||
"onboarding.share.next_steps": "Camau nesaf posib:",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Blokeret",
|
||||
"account.browse_more_on_origin_server": "Se mere på den oprindelige profil",
|
||||
"account.cancel_follow_request": "Annullér anmodning om at følge",
|
||||
"account.copy": "Kopiér link til profil",
|
||||
"account.direct": "Privat omtale @{name}",
|
||||
"account.disable_notifications": "Advisér mig ikke længere, når @{name} poster",
|
||||
"account.domain_blocked": "Domæne blokeret",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Markér som læst",
|
||||
"conversation.open": "Vis samtale",
|
||||
"conversation.with": "Med {names}",
|
||||
"copy_icon_button.copied": "Kopieret til udklipsholderen",
|
||||
"copypaste.copied": "Kopieret",
|
||||
"copypaste.copy_to_clipboard": "Kopiér til udklipsholder",
|
||||
"directory.federated": "Fra kendt fedivers",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Blockiert",
|
||||
"account.browse_more_on_origin_server": "Mehr auf dem Originalprofil durchsuchen",
|
||||
"account.cancel_follow_request": "Folgeanfrage zurückziehen",
|
||||
"account.copy": "Link zum Profil kopieren",
|
||||
"account.direct": "@{name} privat erwähnen",
|
||||
"account.disable_notifications": "Höre auf mich zu benachrichtigen wenn @{name} etwas postet",
|
||||
"account.domain_blocked": "Domain versteckt",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Als gelesen markieren",
|
||||
"conversation.open": "Unterhaltung anzeigen",
|
||||
"conversation.with": "Mit {names}",
|
||||
"copy_icon_button.copied": "In die Zwischenablage kopiert",
|
||||
"copypaste.copied": "Kopiert",
|
||||
"copypaste.copy_to_clipboard": "In die Zwischenablage kopieren",
|
||||
"directory.federated": "Aus bekanntem Fediverse",
|
||||
|
|
|
@ -506,10 +506,10 @@
|
|||
"onboarding.follows.empty": "Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.",
|
||||
"onboarding.follows.lead": "Your home feed is the primary way to experience Mastodon. The more people you follow, the more active and interesting it will be. To get you started, here are some suggestions:",
|
||||
"onboarding.follows.title": "Personalize your home feed",
|
||||
"onboarding.profile.discoverable": "Feature profile and posts in discovery algorithms",
|
||||
"onboarding.profile.discoverable": "Make my profile discoverable",
|
||||
"onboarding.profile.discoverable_hint": "When you opt in to discoverability on Mastodon, your posts may appear in search results and trending, and your profile may be suggested to people with similar interests to you.",
|
||||
"onboarding.profile.display_name": "Display name",
|
||||
"onboarding.profile.display_name_hint": "Your full name or your fun name…",
|
||||
"onboarding.profile.indexable": "Include public posts in search results",
|
||||
"onboarding.profile.lead": "You can always complete this later in the settings, where even more customization options are available.",
|
||||
"onboarding.profile.note": "Bio",
|
||||
"onboarding.profile.note_hint": "You can @mention other people or #hashtags…",
|
||||
|
@ -570,6 +570,7 @@
|
|||
"privacy_policy.title": "Privacy Policy",
|
||||
"reaction_deck.add": "Add",
|
||||
"reaction_deck.remove": "Remove",
|
||||
"recommended": "Recommended",
|
||||
"refresh": "Refresh",
|
||||
"regeneration_indicator.label": "Loading…",
|
||||
"regeneration_indicator.sublabel": "Your home feed is being prepared!",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Bloqueado",
|
||||
"account.browse_more_on_origin_server": "Explorar más en el perfil original",
|
||||
"account.cancel_follow_request": "Dejar de seguir",
|
||||
"account.copy": "Copiar enlace al perfil",
|
||||
"account.direct": "Mención privada a @{name}",
|
||||
"account.disable_notifications": "Dejar de notificarme cuando @{name} envíe mensajes",
|
||||
"account.domain_blocked": "Dominio bloqueado",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Marcar como leída",
|
||||
"conversation.open": "Ver conversación",
|
||||
"conversation.with": "Con {names}",
|
||||
"copy_icon_button.copied": "Copiado en el portapapeles",
|
||||
"copypaste.copied": "Copiado",
|
||||
"copypaste.copy_to_clipboard": "Copiar al portapapeles",
|
||||
"directory.federated": "Desde fediverso conocido",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Bloqueado",
|
||||
"account.browse_more_on_origin_server": "Ver más en el perfil original",
|
||||
"account.cancel_follow_request": "Retirar solicitud de seguimiento",
|
||||
"account.copy": "Copiar enlace al perfil",
|
||||
"account.direct": "Mención privada @{name}",
|
||||
"account.disable_notifications": "Dejar de notificarme cuando @{name} publique algo",
|
||||
"account.domain_blocked": "Dominio oculto",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Marcar como leído",
|
||||
"conversation.open": "Ver conversación",
|
||||
"conversation.with": "Con {names}",
|
||||
"copy_icon_button.copied": "Copiado al portapapeles",
|
||||
"copypaste.copied": "Copiado",
|
||||
"copypaste.copy_to_clipboard": "Copiar al portapapeles",
|
||||
"directory.federated": "Desde el fediverso conocido",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Bloqueado",
|
||||
"account.browse_more_on_origin_server": "Ver más en el perfil original",
|
||||
"account.cancel_follow_request": "Retirar solicitud de seguimiento",
|
||||
"account.copy": "Copiar enlace al perfil",
|
||||
"account.direct": "Mención privada a @{name}",
|
||||
"account.disable_notifications": "Dejar de notificarme cuando @{name} publique algo",
|
||||
"account.domain_blocked": "Dominio bloqueado",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Marcar como leído",
|
||||
"conversation.open": "Ver conversación",
|
||||
"conversation.with": "Con {names}",
|
||||
"copy_icon_button.copied": "Copiado al portapapeles",
|
||||
"copypaste.copied": "Copiado",
|
||||
"copypaste.copy_to_clipboard": "Copiar al portapapeles",
|
||||
"directory.federated": "Desde el fediverso conocido",
|
||||
|
@ -479,7 +481,17 @@
|
|||
"onboarding.follows.empty": "Desafortunadamente, no se pueden mostrar resultados en este momento. Puedes intentar usar la búsqueda o navegar por la página de exploración para encontrar personas a las que seguir, o inténtalo de nuevo más tarde.",
|
||||
"onboarding.follows.lead": "Tu línea de inicio es la forma principal de experimentar Mastodon. Cuanta más personas sigas, más activa e interesante será. Para empezar, aquí hay algunas sugerencias:",
|
||||
"onboarding.follows.title": "Personaliza tu línea de inicio",
|
||||
"onboarding.profile.discoverable": "Destacar perfil y publicaciones en algoritmos de descubrimiento",
|
||||
"onboarding.profile.display_name": "Nombre para mostrar",
|
||||
"onboarding.profile.display_name_hint": "Tu nombre completo o tu apodo…",
|
||||
"onboarding.profile.indexable": "Incluir publicaciones públicas en los resultados de búsqueda",
|
||||
"onboarding.profile.lead": "Siempre puedes completar esto más tarde en los ajustes, donde hay aún más opciones de personalización disponibles.",
|
||||
"onboarding.profile.note": "Biografía",
|
||||
"onboarding.profile.note_hint": "Puedes @mencionar a otras personas o #etiquetas…",
|
||||
"onboarding.profile.save_and_continue": "Guardar y continuar",
|
||||
"onboarding.profile.title": "Configuración del perfil",
|
||||
"onboarding.profile.upload_avatar": "Subir foto de perfil",
|
||||
"onboarding.profile.upload_header": "Subir encabezado de perfil",
|
||||
"onboarding.share.lead": "¡Cuéntale a otras personas cómo te pueden encontrar en Mastodon!",
|
||||
"onboarding.share.message": "¡Soy {username} en #Mastodon! Ven a seguirme en {url}",
|
||||
"onboarding.share.next_steps": "Posibles siguientes pasos:",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Blokeatuta",
|
||||
"account.browse_more_on_origin_server": "Arakatu gehiago jatorrizko profilean",
|
||||
"account.cancel_follow_request": "Baztertu jarraitzeko eskaera",
|
||||
"account.copy": "Kopiatu profilerako esteka",
|
||||
"account.direct": "Aipatu pribatuki @{name}",
|
||||
"account.disable_notifications": "Utzi jakinarazteari @{name} erabiltzailearen bidalketetan",
|
||||
"account.domain_blocked": "Ezkutatutako domeinua",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Markatu irakurrita bezala",
|
||||
"conversation.open": "Ikusi elkarrizketa",
|
||||
"conversation.with": "Hauekin: {names}",
|
||||
"copy_icon_button.copied": "Arbelera kopiatu da",
|
||||
"copypaste.copied": "Kopiatuta",
|
||||
"copypaste.copy_to_clipboard": "Kopiatu arbelera",
|
||||
"directory.federated": "Fedibertso ezagunekoak",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Estetty",
|
||||
"account.browse_more_on_origin_server": "Selaile lisää alkuperäisellä palvelimella",
|
||||
"account.cancel_follow_request": "Peruuta seurantapyyntö",
|
||||
"account.copy": "Kopioi profiilin linkki",
|
||||
"account.direct": "Mainitse @{name} yksityisesti",
|
||||
"account.disable_notifications": "Lopeta ilmoittamasta minulle, kun @{name} julkaisee",
|
||||
"account.domain_blocked": "Verkkotunnus estetty",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Merkitse luetuksi",
|
||||
"conversation.open": "Näytä keskustelu",
|
||||
"conversation.with": "{names} kanssa",
|
||||
"copy_icon_button.copied": "Kopioitu leikepöydälle",
|
||||
"copypaste.copied": "Kopioitu",
|
||||
"copypaste.copy_to_clipboard": "Kopioi leikepöydälle",
|
||||
"directory.federated": "Koko tunnettu fediversumi",
|
||||
|
|
|
@ -390,6 +390,7 @@
|
|||
"lists.search": "Rechercher parmi les gens que vous suivez",
|
||||
"lists.subheading": "Vos listes",
|
||||
"load_pending": "{count, plural, one {# nouvel élément} other {# nouveaux éléments}}",
|
||||
"loading_indicator.label": "Chargement…",
|
||||
"media_gallery.toggle_visible": "{number, plural, one {Cacher l’image} other {Cacher les images}}",
|
||||
"moved_to_account_banner.text": "Votre compte {disabledAccount} est actuellement désactivé parce que vous avez déménagé sur {movedToAccount}.",
|
||||
"mute_modal.duration": "Durée",
|
||||
|
@ -478,6 +479,9 @@
|
|||
"onboarding.follows.empty": "Malheureusement, aucun résultat ne peut être affiché pour le moment. Vous pouvez essayer de rechercher ou de parcourir la page \"Explorer\" pour trouver des personnes à suivre, ou réessayer plus tard.",
|
||||
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
|
||||
"onboarding.follows.title": "Popular on Mastodon",
|
||||
"onboarding.profile.discoverable": "Autoriser des algorithmes de découverte à mettre en avant votre profil et vos messages",
|
||||
"onboarding.profile.save_and_continue": "Enregistrer et continuer",
|
||||
"onboarding.profile.upload_avatar": "Importer une photo de profil",
|
||||
"onboarding.share.lead": "Faites savoir aux gens comment vous trouver sur Mastodon!",
|
||||
"onboarding.share.message": "Je suis {username} sur #Mastodon! Suivez-moi sur {url}",
|
||||
"onboarding.share.next_steps": "Étapes suivantes possibles:",
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
"closed_registrations_modal.preamble": "Mastodon est décentralisé : peu importe où vous créez votre compte, vous serez en mesure de suivre et d'interagir avec quiconque sur ce serveur. Vous pouvez même l'héberger !",
|
||||
"closed_registrations_modal.title": "Inscription sur Mastodon",
|
||||
"column.about": "À propos",
|
||||
"column.blocks": "Comptes bloqués",
|
||||
"column.blocks": "Utilisateurs bloqués",
|
||||
"column.bookmarks": "Marque-pages",
|
||||
"column.community": "Fil public local",
|
||||
"column.direct": "Mentions privées",
|
||||
|
@ -390,6 +390,7 @@
|
|||
"lists.search": "Rechercher parmi les gens que vous suivez",
|
||||
"lists.subheading": "Vos listes",
|
||||
"load_pending": "{count, plural, one {# nouvel élément} other {# nouveaux éléments}}",
|
||||
"loading_indicator.label": "Chargement…",
|
||||
"media_gallery.toggle_visible": "{number, plural, one {Cacher l’image} other {Cacher les images}}",
|
||||
"moved_to_account_banner.text": "Votre compte {disabledAccount} est actuellement désactivé parce que vous l'avez déplacé à {movedToAccount}.",
|
||||
"mute_modal.duration": "Durée",
|
||||
|
@ -478,6 +479,9 @@
|
|||
"onboarding.follows.empty": "Malheureusement, aucun résultat ne peut être affiché pour le moment. Vous pouvez essayer d'utiliser la recherche ou parcourir la page de découverte pour trouver des personnes à suivre, ou réessayez plus tard.",
|
||||
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
|
||||
"onboarding.follows.title": "Personnaliser votre flux principal",
|
||||
"onboarding.profile.discoverable": "Autoriser des algorithmes de découverte à mettre en avant votre profil et vos messages",
|
||||
"onboarding.profile.save_and_continue": "Enregistrer et continuer",
|
||||
"onboarding.profile.upload_avatar": "Importer une photo de profil",
|
||||
"onboarding.share.lead": "Faites savoir aux gens comment ils peuvent vous trouver sur Mastodon!",
|
||||
"onboarding.share.message": "Je suis {username} sur #Mastodon ! Suivez-moi sur {url}",
|
||||
"onboarding.share.next_steps": "Étapes suivantes possibles :",
|
||||
|
|
|
@ -390,6 +390,7 @@
|
|||
"lists.search": "Procurar entre as persoas que segues",
|
||||
"lists.subheading": "As túas listaxes",
|
||||
"load_pending": "{count, plural, one {# novo elemento} other {# novos elementos}}",
|
||||
"loading_indicator.label": "Estase a cargar…",
|
||||
"media_gallery.toggle_visible": "Agochar {number, plural, one {imaxe} other {imaxes}}",
|
||||
"moved_to_account_banner.text": "A túa conta {disabledAccount} está actualmente desactivada porque movéchela a {movedToAccount}.",
|
||||
"mute_modal.duration": "Duración",
|
||||
|
@ -478,6 +479,17 @@
|
|||
"onboarding.follows.empty": "Desgraciadamente agora mesmo non hai nada que mostrar. Podes intentalo coa busca ou na páxina descubrir para atopar persoas ás que seguir, ou intentalo máis tarde.",
|
||||
"onboarding.follows.lead": "Podes facer que a túa cronoloxía de inicio sexa como ti a queres. Canta máis xente sigas máis interesante será. Estes perfís poderían axudarche a comezar —sempre poderás deixar de seguilos despois!",
|
||||
"onboarding.follows.title": "Popular en Mastodon",
|
||||
"onboarding.profile.discoverable": "Perfil destacado e publicacións nos algoritmos de descubrimento",
|
||||
"onboarding.profile.display_name": "Nome público",
|
||||
"onboarding.profile.display_name_hint": "O teu nome completo ou un nome divertido…",
|
||||
"onboarding.profile.indexable": "Incluír publicacións públicas nos resultados das buscas",
|
||||
"onboarding.profile.lead": "Sempre poderás incluír esta información mais tarde nos axustes, onde terás máis opcións dispoñibles.",
|
||||
"onboarding.profile.note": "Acerca de ti",
|
||||
"onboarding.profile.note_hint": "Podes @mencionar a outras persoas ou usar #cancelos…",
|
||||
"onboarding.profile.save_and_continue": "Gardar e continuar",
|
||||
"onboarding.profile.title": "Configuración do perfil",
|
||||
"onboarding.profile.upload_avatar": "Subir imaxe do perfil",
|
||||
"onboarding.profile.upload_header": "Subir cabeceira para o perfil",
|
||||
"onboarding.share.lead": "Fai que as persoas saiban como atoparte en Mastodon!",
|
||||
"onboarding.share.message": "Son {username} en #Mastodon! Ségueme en {url}",
|
||||
"onboarding.share.next_steps": "Seguintes pasos:",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "לחסום",
|
||||
"account.browse_more_on_origin_server": "ראה יותר בפרופיל המקורי",
|
||||
"account.cancel_follow_request": "משיכת בקשת מעקב",
|
||||
"account.copy": "להעתיק קישור לפרופיל",
|
||||
"account.direct": "הודעה פרטית אל @{name}",
|
||||
"account.disable_notifications": "הפסק לשלוח לי התראות כש@{name} מפרסמים",
|
||||
"account.domain_blocked": "הדומיין חסום",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "סמן כנקרא",
|
||||
"conversation.open": "צפו בשיחה",
|
||||
"conversation.with": "עם {names}",
|
||||
"copy_icon_button.copied": "הועתק ללוח",
|
||||
"copypaste.copied": "הועתק",
|
||||
"copypaste.copy_to_clipboard": "העתקה ללוח הגזירים",
|
||||
"directory.federated": "מהפדרציה הידועה",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Letiltva",
|
||||
"account.browse_more_on_origin_server": "További böngészés az eredeti profilon",
|
||||
"account.cancel_follow_request": "Követési kérés visszavonása",
|
||||
"account.copy": "Hivatkozás másolása a profilba",
|
||||
"account.direct": "@{name} személyes említése",
|
||||
"account.disable_notifications": "Ne figyelmeztessen, ha @{name} bejegyzést tesz közzé",
|
||||
"account.domain_blocked": "Letiltott domain",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Megjelölés olvasottként",
|
||||
"conversation.open": "Beszélgetés megtekintése",
|
||||
"conversation.with": "Velük: {names}",
|
||||
"copy_icon_button.copied": "A szöveg a vágólapra másolva",
|
||||
"copypaste.copied": "Másolva",
|
||||
"copypaste.copy_to_clipboard": "Másolás vágólapra",
|
||||
"directory.federated": "Az ismert fediverzumból",
|
||||
|
@ -481,13 +483,13 @@
|
|||
"onboarding.follows.title": "Népszerű a Mastodonon",
|
||||
"onboarding.profile.discoverable": "Profil és bejegyzések szerepeltetése a felfedezési algoritmusokban",
|
||||
"onboarding.profile.display_name": "Megjelenített név",
|
||||
"onboarding.profile.display_name_hint": "Teljes név vagy becenév…",
|
||||
"onboarding.profile.indexable": "Nyilvános bejegyzések is a keresési eredményekben",
|
||||
"onboarding.profile.lead": "Ezt később bármikor elvégezhető a beállításoknál, ahol még több testreszabási lehetőség áll rendelkezésre.",
|
||||
"onboarding.profile.note": "Biográfia",
|
||||
"onboarding.profile.note_hint": "@említhetünk másokat vagy #hashtag elemeket…",
|
||||
"onboarding.profile.display_name_hint": "Teljes neved vagy vicces neved…",
|
||||
"onboarding.profile.indexable": "Nyilvános bejegyzések szerepeltetése a keresési eredményekben",
|
||||
"onboarding.profile.lead": "Ezt később bármikor befejezheted a beállításokban, ahol még több testreszabási lehetőség áll rendelkezésre.",
|
||||
"onboarding.profile.note": "Bemutatkozás",
|
||||
"onboarding.profile.note_hint": "Megemlíthetsz @másokat vagy #hashtag-eket…",
|
||||
"onboarding.profile.save_and_continue": "Mentés és folytatás",
|
||||
"onboarding.profile.title": "Profil beüzemelés",
|
||||
"onboarding.profile.title": "Profilbeállítás",
|
||||
"onboarding.profile.upload_avatar": "Profilkép feltöltése",
|
||||
"onboarding.profile.upload_header": "Profil fejléc feltöltése",
|
||||
"onboarding.share.lead": "Tudassuk az emberekkel, hogyan találhatnak meg a Mastodonon!",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Útilokaður",
|
||||
"account.browse_more_on_origin_server": "Skoða nánari upplýsingar á notandasniðinu",
|
||||
"account.cancel_follow_request": "Taka fylgjendabeiðni til baka",
|
||||
"account.copy": "Afrita tengil í notandasnið",
|
||||
"account.direct": "Einkaspjall við @{name}",
|
||||
"account.disable_notifications": "Hætta að láta mig vita þegar @{name} sendir inn",
|
||||
"account.domain_blocked": "Lén útilokað",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Merkja sem lesið",
|
||||
"conversation.open": "Skoða samtal",
|
||||
"conversation.with": "Við {names}",
|
||||
"copy_icon_button.copied": "Afritað á klippispjald",
|
||||
"copypaste.copied": "Afritað",
|
||||
"copypaste.copy_to_clipboard": "Afrita á klippispjald",
|
||||
"directory.federated": "Frá samtengdum vefþjónum",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Bloccato",
|
||||
"account.browse_more_on_origin_server": "Sfoglia di più sul profilo originale",
|
||||
"account.cancel_follow_request": "Annulla la richiesta di seguire",
|
||||
"account.copy": "Copia link del profilo",
|
||||
"account.direct": "Menziona privatamente @{name}",
|
||||
"account.disable_notifications": "Smetti di avvisarmi quando @{name} pubblica un post",
|
||||
"account.domain_blocked": "Dominio bloccato",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Segna come letto",
|
||||
"conversation.open": "Visualizza conversazione",
|
||||
"conversation.with": "Con {names}",
|
||||
"copy_icon_button.copied": "Copiato negli appunti",
|
||||
"copypaste.copied": "Copiato",
|
||||
"copypaste.copy_to_clipboard": "Copia negli Appunti",
|
||||
"directory.federated": "Da un fediverse noto",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "차단함",
|
||||
"account.browse_more_on_origin_server": "원본 프로필에서 더 탐색하기",
|
||||
"account.cancel_follow_request": "팔로우 취소",
|
||||
"account.copy": "프로필 링크 복사",
|
||||
"account.direct": "@{name} 님에게 개인적으로 멘션",
|
||||
"account.disable_notifications": "@{name} 의 게시물 알림 끄기",
|
||||
"account.domain_blocked": "도메인 차단함",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "읽은 상태로 표시",
|
||||
"conversation.open": "대화 보기",
|
||||
"conversation.with": "{names} 님과",
|
||||
"copy_icon_button.copied": "클립보드에 복사함",
|
||||
"copypaste.copied": "복사됨",
|
||||
"copypaste.copy_to_clipboard": "클립보드에 복사",
|
||||
"directory.federated": "알려진 연합우주로부터",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Užblokuota",
|
||||
"account.browse_more_on_origin_server": "Naršyti daugiau originaliame profilyje",
|
||||
"account.cancel_follow_request": "Atšaukti sekimą",
|
||||
"account.copy": "Kopijuoti nuorodą į profilį",
|
||||
"account.direct": "Privačiai paminėti @{name}",
|
||||
"account.disable_notifications": "Nustoti man pranešti, kai @{name} paskelbia",
|
||||
"account.domain_blocked": "Užblokuotas domenas",
|
||||
|
@ -91,11 +92,28 @@
|
|||
"bundle_column_error.routing.body": "Prašyto puslapio nepavyko rasti. Ar esi tikras (-a), kad adreso juostoje nurodytas URL adresas yra teisingas?",
|
||||
"bundle_column_error.routing.title": "404",
|
||||
"bundle_modal_error.close": "Uždaryti",
|
||||
"bundle_modal_error.retry": "Bandyti dar kartą",
|
||||
"closed_registrations.other_server_instructions": "Kadangi Mastodon yra decentralizuotas, gali susikurti paskyrą kitame serveryje ir vis tiek bendrauti su šiuo serveriu.",
|
||||
"closed_registrations_modal.description": "Sukurti paskyrą {domain} šiuo metu neįmanoma, tačiau nepamiršk, kad norint naudotis Mastodon nebūtina turėti paskyrą {domain}.",
|
||||
"closed_registrations_modal.find_another_server": "Rasti kitą serverį",
|
||||
"column.domain_blocks": "Hidden domains",
|
||||
"closed_registrations_modal.preamble": "Mastodon yra decentralizuotas, todėl nesvarbu, kur susikursi paskyrą, galėsi sekti ir bendrauti su bet kuriuo šiame serveryje esančiu asmeniu. Jį gali net savarankiškai talpinti!",
|
||||
"closed_registrations_modal.title": "Užsiregistravimas į Mastodon",
|
||||
"column.about": "Apie",
|
||||
"column.blocks": "Užblokuoti naudotojai",
|
||||
"column.bookmarks": "Žymės",
|
||||
"column.community": "Vietinė laiko skalė",
|
||||
"column.direct": "Privatūs paminėjimai",
|
||||
"column.directory": "Naršyti profilius",
|
||||
"column.domain_blocks": "Užblokuoti domenai",
|
||||
"column.favourites": "Mėgstamiausi",
|
||||
"column.firehose": "Tiesioginiai padavimai",
|
||||
"column.follow_requests": "Sekti prašymus",
|
||||
"column.home": "Pradžia",
|
||||
"column.lists": "Sąrašai",
|
||||
"column.mutes": "Užtildyti vartotojai",
|
||||
"column.pins": "Pinned toot",
|
||||
"column.mutes": "Užtildyti naudotojai",
|
||||
"column.notifications": "Pranešimai",
|
||||
"column.pins": "Prisegti įrašai",
|
||||
"column.public": "Federacinė laiko skalė",
|
||||
"column_back_button.label": "Atgal",
|
||||
"column_header.hide_settings": "Slėpti nustatymus",
|
||||
"column_header.pin": "Prisegti",
|
||||
|
@ -106,6 +124,7 @@
|
|||
"compose.language.change": "Keisti kalbą",
|
||||
"compose.language.search": "Ieškoti kalbų...",
|
||||
"compose.published.body": "Įrašas paskelbtas.",
|
||||
"compose_form.direct_message_warning_learn_more": "Sužinoti daugiau",
|
||||
"compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
|
||||
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
|
||||
"compose_form.placeholder": "Kas tavo mintyse?",
|
||||
|
@ -137,6 +156,7 @@
|
|||
"confirmations.reply.confirm": "Atsakyti",
|
||||
"confirmations.reply.message": "Atsakydamas (-a) dabar perrašysi šiuo metu rašomą žinutę. Ar tikrai nori tęsti?",
|
||||
"confirmations.unfollow.confirm": "Nebesekti",
|
||||
"copy_icon_button.copied": "Nukopijuota į iškarpinę",
|
||||
"dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
|
||||
"dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
||||
"embed.instructions": "Embed this status on your website by copying the code below.",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Geblokkeerd",
|
||||
"account.browse_more_on_origin_server": "Zie meer op het originele profiel",
|
||||
"account.cancel_follow_request": "Ontvolgen",
|
||||
"account.copy": "Link naar profiel kopiëren",
|
||||
"account.direct": "@{name} een privébericht sturen",
|
||||
"account.disable_notifications": "Geen melding meer geven wanneer @{name} een bericht plaatst",
|
||||
"account.domain_blocked": "Domein geblokkeerd",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Als gelezen markeren",
|
||||
"conversation.open": "Gesprek tonen",
|
||||
"conversation.with": "Met {names}",
|
||||
"copy_icon_button.copied": "Gekopieerd naar klembord",
|
||||
"copypaste.copied": "Gekopieerd",
|
||||
"copypaste.copy_to_clipboard": "Naar klembord kopiëren",
|
||||
"directory.federated": "Fediverse (wat bekend is)",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Blokkert",
|
||||
"account.browse_more_on_origin_server": "Sjå gjennom meir på den opphavlege profilen",
|
||||
"account.cancel_follow_request": "Trekk attende fylgeførespurnad",
|
||||
"account.copy": "Kopier lenka til profilen",
|
||||
"account.direct": "Nevn @{name} privat",
|
||||
"account.disable_notifications": "Slutt å varsle meg når @{name} skriv innlegg",
|
||||
"account.domain_blocked": "Domenet er sperra",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Marker som lesen",
|
||||
"conversation.open": "Sjå samtale",
|
||||
"conversation.with": "Med {names}",
|
||||
"copy_icon_button.copied": "Kopiert til utklyppstavla",
|
||||
"copypaste.copied": "Kopiert",
|
||||
"copypaste.copy_to_clipboard": "Kopier til utklyppstavla",
|
||||
"directory.federated": "Frå den kjende allheimen",
|
||||
|
@ -390,7 +392,7 @@
|
|||
"lists.search": "Søk blant folk du fylgjer",
|
||||
"lists.subheading": "Listene dine",
|
||||
"load_pending": "{count, plural, one {# nytt element} other {# nye element}}",
|
||||
"loading_indicator.label": "Laster…",
|
||||
"loading_indicator.label": "Lastar…",
|
||||
"media_gallery.toggle_visible": "{number, plural, one {Skjul bilete} other {Skjul bilete}}",
|
||||
"moved_to_account_banner.text": "Kontoen din, {disabledAccount} er for tida deaktivert fordi du har flytta til {movedToAccount}.",
|
||||
"mute_modal.duration": "Varigheit",
|
||||
|
@ -479,17 +481,17 @@
|
|||
"onboarding.follows.empty": "Me kan ikkje visa deg nokon resultat no. Du kan prøva å søkja eller bla gjennom utforsk-sida for å finna folk å fylgja, eller du kan prøva att seinare.",
|
||||
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
|
||||
"onboarding.follows.title": "Popular on Mastodon",
|
||||
"onboarding.profile.discoverable": "Fremhevede profiler og innlegg i oppdagelsealgoritmer",
|
||||
"onboarding.profile.display_name": "Visningsnavn",
|
||||
"onboarding.profile.display_name_hint": "Ditt fulle navn eller ditt morsomme navn…",
|
||||
"onboarding.profile.indexable": "Inkluder offentlige innlegg i søkeresultatene",
|
||||
"onboarding.profile.lead": "Du kan alltid fullføre dette senere i innstillingene, der enda flere tilpasningsalternativer er tilgjengelige.",
|
||||
"onboarding.profile.discoverable": "Ta med profilen og innlegga i oppdagingsalgoritmar",
|
||||
"onboarding.profile.display_name": "Synleg namn",
|
||||
"onboarding.profile.display_name_hint": "Det fulle namnet eller kallenamnet ditt…",
|
||||
"onboarding.profile.indexable": "Ta med offentlege innlegg i søkjeresultat",
|
||||
"onboarding.profile.lead": "Du kan alltid fullføra dette seinare i innstillingane, og der er det endå fleire tilpassingsalternativ.",
|
||||
"onboarding.profile.note": "Om meg",
|
||||
"onboarding.profile.note_hint": "Du kan @nevne andre eller #emneknagger…",
|
||||
"onboarding.profile.save_and_continue": "Lagre og fortsett",
|
||||
"onboarding.profile.title": "Konfigurering av profil",
|
||||
"onboarding.profile.upload_avatar": "Last opp profilbilde",
|
||||
"onboarding.profile.upload_header": "Last opp profiltoppbilde",
|
||||
"onboarding.profile.note_hint": "Du kan @nemna folk eller #emneknaggar…",
|
||||
"onboarding.profile.save_and_continue": "Lagre og hald fram",
|
||||
"onboarding.profile.title": "Profiloppsett",
|
||||
"onboarding.profile.upload_avatar": "Last opp profilbilete",
|
||||
"onboarding.profile.upload_header": "Last opp profiltoppbilete",
|
||||
"onboarding.share.lead": "La folk vita korleis dei kan finna deg på Mastodon!",
|
||||
"onboarding.share.message": "Eg er {username} på #Mastodon! Du kan fylgja meg på {url}",
|
||||
"onboarding.share.next_steps": "Dette kan du gjera no:",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Blokkert",
|
||||
"account.browse_more_on_origin_server": "Bla mer på den opprinnelige profilen",
|
||||
"account.cancel_follow_request": "Avbryt følgeforespørselen",
|
||||
"account.copy": "Kopier lenke til profil",
|
||||
"account.direct": "Nevn @{name} privat",
|
||||
"account.disable_notifications": "Slutt å varsle meg når @{name} legger ut innlegg",
|
||||
"account.domain_blocked": "Domene blokkert",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Marker som lest",
|
||||
"conversation.open": "Vis samtale",
|
||||
"conversation.with": "Med {names}",
|
||||
"copy_icon_button.copied": "Kopiert til utklippstavlen",
|
||||
"copypaste.copied": "Kopiert",
|
||||
"copypaste.copy_to_clipboard": "Kopier til utklippstavle",
|
||||
"directory.federated": "Fra det kjente strømiverset",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Zablokowany(-a)",
|
||||
"account.browse_more_on_origin_server": "Zobacz więcej na oryginalnym profilu",
|
||||
"account.cancel_follow_request": "Wycofaj żądanie obserwowania",
|
||||
"account.copy": "Skopiuj odnośnik do profilu",
|
||||
"account.direct": "Prywatna wzmianka @{name}",
|
||||
"account.disable_notifications": "Przestań powiadamiać mnie o wpisach @{name}",
|
||||
"account.domain_blocked": "Ukryto domenę",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Oznacz jako przeczytane",
|
||||
"conversation.open": "Zobacz konwersację",
|
||||
"conversation.with": "Z {names}",
|
||||
"copy_icon_button.copied": "Skopiowano do schowka",
|
||||
"copypaste.copied": "Skopiowano",
|
||||
"copypaste.copy_to_clipboard": "Skopiuj do schowka",
|
||||
"directory.federated": "Ze znanego fediwersum",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Bloqueado(a)",
|
||||
"account.browse_more_on_origin_server": "Encontrar mais no perfil original",
|
||||
"account.cancel_follow_request": "Retirar pedido para seguir",
|
||||
"account.copy": "Copiar hiperligação para o perfil",
|
||||
"account.direct": "Mencionar @{name} em privado",
|
||||
"account.disable_notifications": "Parar de me notificar das publicações de @{name}",
|
||||
"account.domain_blocked": "Domínio bloqueado",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Marcar como lida",
|
||||
"conversation.open": "Ver conversa",
|
||||
"conversation.with": "Com {names}",
|
||||
"copy_icon_button.copied": "Copiado para a área de transferência",
|
||||
"copypaste.copied": "Copiado",
|
||||
"copypaste.copy_to_clipboard": "Copiar para a área de transferência",
|
||||
"directory.federated": "Do fediverso conhecido",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "E bllokuar",
|
||||
"account.browse_more_on_origin_server": "Shfletoni më tepër rreth profilit origjinal",
|
||||
"account.cancel_follow_request": "Tërhiq mbrapsht kërkesë për ndjekje",
|
||||
"account.copy": "Kopjoje lidhjen te profili",
|
||||
"account.direct": "Përmendje private për @{name}",
|
||||
"account.disable_notifications": "Resht së njoftuari mua, kur poston @{name}",
|
||||
"account.domain_blocked": "Përkatësia u bllokua",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Vëri shenjë si të lexuar",
|
||||
"conversation.open": "Shfaq bisedën",
|
||||
"conversation.with": "Me {names}",
|
||||
"copy_icon_button.copied": "U kopjua në të papastër",
|
||||
"copypaste.copied": "U kopjua",
|
||||
"copypaste.copy_to_clipboard": "Kopjoje në të papastër",
|
||||
"directory.federated": "Nga fedivers i njohur",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Блокиран",
|
||||
"account.browse_more_on_origin_server": "Прегледајте још на оригиналном профилу",
|
||||
"account.cancel_follow_request": "Откажи праћење",
|
||||
"account.copy": "Копирај везу у профил",
|
||||
"account.direct": "Приватно помени @{name}",
|
||||
"account.disable_notifications": "Заустави обавештавање за објаве корисника @{name}",
|
||||
"account.domain_blocked": "Домен је блокиран",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Означи као прочитано",
|
||||
"conversation.open": "Прикажи разговор",
|
||||
"conversation.with": "Са {names}",
|
||||
"copy_icon_button.copied": "Копирано",
|
||||
"copypaste.copied": "Копирано",
|
||||
"copypaste.copy_to_clipboard": "Копирај",
|
||||
"directory.federated": "Са знаног федиверзума",
|
||||
|
@ -390,6 +392,7 @@
|
|||
"lists.search": "Претражи међу људима које пратите",
|
||||
"lists.subheading": "Ваше листе",
|
||||
"load_pending": "{count, plural, one {# нова ставка} few {# нове ставке} other {# нових ставки}}",
|
||||
"loading_indicator.label": "Учитавање…",
|
||||
"media_gallery.toggle_visible": "{number, plural, one {Сакриј слику} few {Сакриј слике} other {Сакриј слике}}",
|
||||
"moved_to_account_banner.text": "Ваш налог {disabledAccount} је тренутно онемогућен јер сте прешли на {movedToAccount}.",
|
||||
"mute_modal.duration": "Трајање",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Blockerad",
|
||||
"account.browse_more_on_origin_server": "Läs mer på den ursprungliga profilen",
|
||||
"account.cancel_follow_request": "Återkalla din begäran om att få följa",
|
||||
"account.copy": "Kopiera länk till profil",
|
||||
"account.direct": "Nämn @{name} privat",
|
||||
"account.disable_notifications": "Sluta notifiera mig när @{name} gör inlägg",
|
||||
"account.domain_blocked": "Domän blockerad",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Markera som läst",
|
||||
"conversation.open": "Visa konversation",
|
||||
"conversation.with": "Med {names}",
|
||||
"copy_icon_button.copied": "Kopierad till urklipp",
|
||||
"copypaste.copied": "Kopierad",
|
||||
"copypaste.copy_to_clipboard": "Kopiera till urklipp",
|
||||
"directory.federated": "Från känt fediversum",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "ปิดกั้นอยู่",
|
||||
"account.browse_more_on_origin_server": "เรียกดูเพิ่มเติมในโปรไฟล์ดั้งเดิม",
|
||||
"account.cancel_follow_request": "ยกเลิกการติดตาม",
|
||||
"account.copy": "คัดลอกลิงก์ไปยังโปรไฟล์",
|
||||
"account.direct": "กล่าวถึง @{name} แบบส่วนตัว",
|
||||
"account.disable_notifications": "หยุดแจ้งเตือนฉันเมื่อ @{name} โพสต์",
|
||||
"account.domain_blocked": "ปิดกั้นโดเมนอยู่",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "ทำเครื่องหมายว่าอ่านแล้ว",
|
||||
"conversation.open": "ดูการสนทนา",
|
||||
"conversation.with": "กับ {names}",
|
||||
"copy_icon_button.copied": "คัดลอกไปยังคลิปบอร์ดแล้ว",
|
||||
"copypaste.copied": "คัดลอกแล้ว",
|
||||
"copypaste.copy_to_clipboard": "คัดลอกไปยังคลิปบอร์ด",
|
||||
"directory.federated": "จากจักรวาลสหพันธ์ที่รู้จัก",
|
||||
|
@ -481,15 +483,15 @@
|
|||
"onboarding.follows.title": "ปรับแต่งฟีดหน้าแรกของคุณ",
|
||||
"onboarding.profile.discoverable": "แสดงโปรไฟล์และโพสต์ในอัลกอริทึมการค้นพบ",
|
||||
"onboarding.profile.display_name": "ชื่อที่แสดง",
|
||||
"onboarding.profile.display_name_hint": "ชื่อเต็มหรือชื่อแบบสนุกสนานของคุณ",
|
||||
"onboarding.profile.display_name_hint": "ชื่อเต็มของคุณหรือชื่อแบบสนุกสนานของคุณ…",
|
||||
"onboarding.profile.indexable": "รวมโพสต์สาธารณะในผลลัพธ์การค้นหา",
|
||||
"onboarding.profile.lead": "คุณสามารถกลับมาทำต่อได้เสมอในการตั้งค่า ซึ่งจะมีตัวเลือกในการปรับแต่งมากกว่า",
|
||||
"onboarding.profile.note": "ชีวประวัติ",
|
||||
"onboarding.profile.note_hint": "คุณสามารถ @กล่าวถึง ผู้คนอื่น ๆ หรือ #แฮชแท็ก",
|
||||
"onboarding.profile.note_hint": "คุณสามารถ @กล่าวถึง ผู้คนอื่น ๆ หรือ #แฮชแท็ก…",
|
||||
"onboarding.profile.save_and_continue": "บันทึกและดำเนินการต่อ",
|
||||
"onboarding.profile.title": "การตั้งค่าโปรไฟล์",
|
||||
"onboarding.profile.upload_avatar": "อัปโหลดรูปโปรไฟล์",
|
||||
"onboarding.profile.upload_header": "อัปโหลดรูปส่วนหัวโปรไฟล์",
|
||||
"onboarding.profile.upload_avatar": "อัปโหลดรูปภาพโปรไฟล์",
|
||||
"onboarding.profile.upload_header": "อัปโหลดส่วนหัวโปรไฟล์",
|
||||
"onboarding.share.lead": "แจ้งให้ผู้คนทราบวิธีที่เขาสามารถค้นหาคุณใน Mastodon!",
|
||||
"onboarding.share.message": "ฉันคือ {username} ใน #Mastodon! มาติดตามฉันที่ {url}",
|
||||
"onboarding.share.next_steps": "ขั้นตอนถัดไปที่เป็นไปได้:",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "Заблоковані",
|
||||
"account.browse_more_on_origin_server": "Переглянути більше в оригінальному профілі",
|
||||
"account.cancel_follow_request": "Відкликати запит на стеження",
|
||||
"account.copy": "Копіювати посилання на профіль",
|
||||
"account.direct": "Особиста згадка @{name}",
|
||||
"account.disable_notifications": "Не повідомляти мене про дописи @{name}",
|
||||
"account.domain_blocked": "Домен заблоковано",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "Позначити як прочитане",
|
||||
"conversation.open": "Переглянути бесіду",
|
||||
"conversation.with": "З {names}",
|
||||
"copy_icon_button.copied": "Скопійовано до буфера обміну",
|
||||
"copypaste.copied": "Скопійовано",
|
||||
"copypaste.copy_to_clipboard": "Копіювати до буфера обміну",
|
||||
"directory.federated": "З відомого федесвіту",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "已屏蔽",
|
||||
"account.browse_more_on_origin_server": "在原始个人资料页面上浏览详情",
|
||||
"account.cancel_follow_request": "撤回关注请求",
|
||||
"account.copy": "复制资料卡链接",
|
||||
"account.direct": "私下提及 @{name}",
|
||||
"account.disable_notifications": "当 @{name} 发布嘟文时不要通知我",
|
||||
"account.domain_blocked": "域名已屏蔽",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "标记为已读",
|
||||
"conversation.open": "查看对话",
|
||||
"conversation.with": "与 {names}",
|
||||
"copy_icon_button.copied": "已复制到剪贴板",
|
||||
"copypaste.copied": "已复制",
|
||||
"copypaste.copy_to_clipboard": "复制到剪贴板",
|
||||
"directory.federated": "来自已知的联邦宇宙",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "已封鎖",
|
||||
"account.browse_more_on_origin_server": "前往原始的個人檔案頁瀏覽更多",
|
||||
"account.cancel_follow_request": "撤回追蹤請求",
|
||||
"account.copy": "複製個人檔案連結",
|
||||
"account.direct": "私下提及 @{name}",
|
||||
"account.disable_notifications": "當 @{name} 發文時不要再通知我",
|
||||
"account.domain_blocked": "網域被封鎖",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "標為已讀",
|
||||
"conversation.open": "檢視對話",
|
||||
"conversation.with": "與 {names}",
|
||||
"copy_icon_button.copied": "已複製到剪貼簿",
|
||||
"copypaste.copied": "已複製",
|
||||
"copypaste.copy_to_clipboard": "複製到剪貼簿",
|
||||
"directory.federated": "來自已知的聯盟網絡",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"account.blocked": "已封鎖",
|
||||
"account.browse_more_on_origin_server": "在該伺服器上的個人檔案頁面瀏覽更多",
|
||||
"account.cancel_follow_request": "收回跟隨請求",
|
||||
"account.copy": "複製個人檔案連結",
|
||||
"account.direct": "私訊 @{name}",
|
||||
"account.disable_notifications": "取消來自 @{name} 嘟文的通知",
|
||||
"account.domain_blocked": "已封鎖網域",
|
||||
|
@ -191,6 +192,7 @@
|
|||
"conversation.mark_as_read": "標記為已讀",
|
||||
"conversation.open": "檢視對話",
|
||||
"conversation.with": "與 {names}",
|
||||
"copy_icon_button.copied": "已複製到剪貼簿",
|
||||
"copypaste.copied": "已複製",
|
||||
"copypaste.copy_to_clipboard": "複製到剪貼簿",
|
||||
"directory.federated": "來自已知聯邦宇宙",
|
||||
|
|
|
@ -2382,8 +2382,7 @@ $ui-header-height: 55px;
|
|||
|
||||
> .scrollable {
|
||||
background: $ui-base-color;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1223,10 +1223,6 @@ code {
|
|||
}
|
||||
|
||||
.app-form {
|
||||
& > * {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&__avatar-input,
|
||||
&__header-input {
|
||||
display: block;
|
||||
|
@ -1291,4 +1287,49 @@ code {
|
|||
&__header-input {
|
||||
aspect-ratio: 580/193;
|
||||
}
|
||||
|
||||
&__toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
color: $darker-text-color;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
|
||||
.icon {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
&__label {
|
||||
flex: 1 1 auto;
|
||||
|
||||
strong {
|
||||
color: $primary-text-color;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.recommended {
|
||||
position: absolute;
|
||||
margin: 0 4px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
&__toggle {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__toggle > div {
|
||||
display: flex;
|
||||
border-inline-start: 1px solid lighten($ui-base-color, 8%);
|
||||
padding-inline-start: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -611,6 +611,7 @@ es:
|
|||
created_at: Denunciado
|
||||
delete_and_resolve: Eliminar publicaciones
|
||||
forwarded: Reenviado
|
||||
forwarded_replies_explanation: Este informe es de un usuario remoto y sobre contenido remoto. Se le ha enviado porque el contenido reportado es en respuesta a uno de sus usuarios.
|
||||
forwarded_to: Reenviado a %{domain}
|
||||
mark_as_resolved: Marcar como resuelto
|
||||
mark_as_sensitive: Marcar como sensible
|
||||
|
|
|
@ -613,6 +613,7 @@ eu:
|
|||
created_at: Salatua
|
||||
delete_and_resolve: Ezabatu bidalketak
|
||||
forwarded: Birbidalia
|
||||
forwarded_replies_explanation: Salaketa hau beste instantzia bateko erabiltzaile baten edukiari buruzkoa da, eta zure instantziako erabiltzaile bati egidako erantzuna delako bidali dizugu mezu hau.
|
||||
forwarded_to: 'Hona birbidalia: %{domain}'
|
||||
mark_as_resolved: Markatu konpondutako gisa
|
||||
mark_as_sensitive: Markatu hunkigarri gisa
|
||||
|
|
|
@ -384,7 +384,7 @@ gl:
|
|||
domain_blocks:
|
||||
add_new: Engadir novo bloqueo de dominio
|
||||
confirm_suspension:
|
||||
cancel: Cancelar
|
||||
cancel: Desbotar
|
||||
confirm: Suspender
|
||||
permanent_action: Ao retirar a suspensión non restableces os datos ou a relación.
|
||||
preamble_html: Vas suspender a <strong>%{domain}</strong> e os seus subdominios.
|
||||
|
@ -611,6 +611,7 @@ gl:
|
|||
created_at: Denunciado
|
||||
delete_and_resolve: Eliminar publicacións
|
||||
forwarded: Reenviado
|
||||
forwarded_replies_explanation: Esta denuncia procede dunha usuaria remota e acerca de contido remoto. Enviouseche unha copia porque o contido denunciado é unha resposta a unha das túas usuarias.
|
||||
forwarded_to: Reenviado a %{domain}
|
||||
mark_as_resolved: Marcar como resolto
|
||||
mark_as_sensitive: Marcar como sensible
|
||||
|
|
|
@ -611,7 +611,7 @@ hu:
|
|||
created_at: Jelentve
|
||||
delete_and_resolve: Bejegyzések törlése
|
||||
forwarded: Továbbítva
|
||||
forwarded_replies_explanation: Ez a jelentés egy távoli felhasználótól származik, és távoli tartalomról szól. Azért lett neked továbbítva, mert a jelentett tartalom az egyik felhasználódnak küldött válasz.
|
||||
forwarded_replies_explanation: Ez a jelentés egy távoli flehasználótól származik, és távoli tartalomról szól. Azért lett neked továbbítva, mert a jelentett tartalom az egyik felhasználódnak küldött válasz.
|
||||
forwarded_to: 'Továbbítva ide: %{domain}'
|
||||
mark_as_resolved: Megjelölés megoldottként
|
||||
mark_as_sensitive: Érzékenynek jelölés
|
||||
|
|
|
@ -763,7 +763,7 @@ ko:
|
|||
open: 누구나 가입 할 수 있음
|
||||
security:
|
||||
authorized_fetch: 연합된 서버들에게서 인증 필수
|
||||
authorized_fetch_hint: 연합된 서버들에게서 인증을 요구하는 것은 사용자 레벨과 서버 레벨의 차단은 좀 더 확실하게 해줍니다. 한편으로는 성능적인 페널티, 답글의 전달 범위 감소, 몇몇 연합된 서비스들과의 호환성 문제가 있을 가능성이 있습니다. 추가적으로 이 기능은 전용 액터가 공개돤 게시물이나 계정을 페치하는 것은 막지 않습니다.
|
||||
authorized_fetch_hint: 연합된 서버들에게서 인증을 요구하는 것은 사용자 레벨과 서버 레벨의 차단을 좀 더 확실하게 해줍니다. 한편으로는 성능적인 페널티, 답글의 전달 범위 감소, 몇몇 연합된 서비스들과의 호환성 문제가 있을 가능성이 있습니다. 추가적으로 이 기능은 전용 액터가 공개돤 게시물이나 계정을 페치하는 것은 막지 않습니다.
|
||||
authorized_fetch_overridden_hint: 현재 이 값은 환경변수에 의해 설정되어 있기에 설정을 변경할 수 없습니다.
|
||||
federation_authentication: 연합 인증 필수
|
||||
title: 서버 설정
|
||||
|
|
|
@ -534,7 +534,7 @@ nn:
|
|||
total_reported: Rapportar om dei
|
||||
total_storage: Medievedlegg
|
||||
totals_time_period_hint_html: Totalsum vist nedanfor gjeld data for alle tidsperiodar.
|
||||
unknown_instance: Dette domenet er ukjent for denne serveren.
|
||||
unknown_instance: Domenet er ukjent for denne tenaren.
|
||||
invites:
|
||||
deactivate_all: Slå av alle
|
||||
filter:
|
||||
|
@ -611,7 +611,7 @@ nn:
|
|||
created_at: Rapportert
|
||||
delete_and_resolve: Slett innlegg
|
||||
forwarded: Videresendt
|
||||
forwarded_replies_explanation: Denne rapporten er fra en ekstern bruker og handler om eksternt innhold. Den er videresendt til deg fordi det rapporterte innholdet svarer til en av brukerne dine.
|
||||
forwarded_replies_explanation: Denne rapporten gjeld innhald på ein annan nettstad. Rapporten er vidaresend til deg fordi det rapporterte innhaldet er eit svar på noko ein av brukarane på nettstaden din har skrive.
|
||||
forwarded_to: Videresendt til %{domain}
|
||||
mark_as_resolved: Merk som løyst
|
||||
mark_as_sensitive: Marker som ømtolig
|
||||
|
@ -1042,14 +1042,14 @@ nn:
|
|||
hint_html: Berre ein ting til! Vi må bekrefte at du er et menneske (så vi kan halde spam ute!). Løys CAPTCHA-en nedanfor og klikk "Fortsett".
|
||||
title: Sikkerheitssjekk
|
||||
confirmations:
|
||||
awaiting_review: Din e-post adresse er bekreftet! %{domain} ansatte gjennomgår nå registreringen din. Du vil motta en e-post hvis de godkjenner din konto!
|
||||
awaiting_review_title: Din registrering blir vurdert
|
||||
clicking_this_link: klikke på denne lenken
|
||||
login_link: logg inn
|
||||
proceed_to_login_html: Du kan nå fortsette til %{login_link}.
|
||||
redirect_to_app_html: Du burde bli omdirigert til <strong>%{app_name}</strong> -appen. Hvis det ikke skjedde, kan du prøve %{clicking_this_link} eller manuelt gå tilbake til appen.
|
||||
registration_complete: Registreringen på %{domain} er nå fullført!
|
||||
welcome_title: Velkommen, %{name}!
|
||||
awaiting_review: Epostadressa di er stadfesta! Styrarane på %{domain} ser gjennom registreringa di. Du får ein epost frå dei om dei godkjenner brukarkontoen din.
|
||||
awaiting_review_title: Me går gjennom registreringa di
|
||||
clicking_this_link: klikka på denne lenka
|
||||
login_link: logga inn
|
||||
proceed_to_login_html: No kan du %{login_link}.
|
||||
redirect_to_app_html: Du skulle vorte vidaresend til <strong>%{app_name}</strong>-appen. Viss det ikkje skjedde, kan du prøva å %{clicking_this_link} eller manuelt gå tilbake til appen.
|
||||
registration_complete: Du har registrert deg som brukar på %{domain}.
|
||||
welcome_title: Velkomen, %{name}!
|
||||
wrong_email_hint: Viss epostadressa er feil, kan du endra ho i kontoinnstillingane.
|
||||
delete_account: Slett konto
|
||||
delete_account_html: Om du vil sletta kontoen din, kan du <a href="%{path}">gå hit</a>. Du vert spurd etter stadfesting.
|
||||
|
@ -1111,7 +1111,7 @@ nn:
|
|||
functional: Kontoen din er fullt operativt.
|
||||
pending: Søknaden din ventar på gjennomgang frå personalet vårt. Dette kan taka litt tid. Du får ein e-post om søknaden din vert godkjend.
|
||||
redirecting_to: Kontoen din er inaktiv fordi den for øyeblikket omdirigerer til %{acct}.
|
||||
self_destruct: Siden %{domain} stenger, vil du kun ha begrenset tilgang til kontoen din.
|
||||
self_destruct: Av di %{domain} er i ferd med å stenga, vil du berre få avgrensa tilgang til brukarkontoen din.
|
||||
view_strikes: Vis tidligere advarsler mot kontoen din
|
||||
too_fast: Skjemaet ble sendt inn for raskt, prøv på nytt.
|
||||
use_security_key: Bruk sikkerhetsnøkkel
|
||||
|
@ -1583,8 +1583,8 @@ nn:
|
|||
over_total_limit: Du har overskredet grensen på %{limit} planlagte tuter
|
||||
too_soon: Den planlagte datoen må være i fremtiden
|
||||
self_destruct:
|
||||
lead_html: Dessverre stenger <strong>%{domain}</strong> for alltid. Hvis du hadde en konto der vil du ikke kunne fortsette å bruke den, men du kan fremdeles be om en sikkerhetskopi av dataene dine.
|
||||
title: Denne serveren stenger
|
||||
lead_html: Diverre stengjer <strong>%{domain}</strong> dørene for godt. Viss du hadde ein brukarkonto der, vil du ikkje kunna halda fram å bruka han, men du kan få ut ein tryggingskopi av dataa dine.
|
||||
title: Denne tenaren stengjer
|
||||
sessions:
|
||||
activity: Siste aktivitet
|
||||
browser: Nettlesar
|
||||
|
|
|
@ -1533,7 +1533,7 @@
|
|||
posting_defaults: Innleggsstandarder
|
||||
public_timelines: Offentlige tidslinjer
|
||||
privacy:
|
||||
hint_html: "<strong>Tilpass hvordan du vil at din profil og dine innlegg skal bli funnet.</strong> En rekke funksjoner i Mastodon kan hjelpe deg med å nå et bredere publikum når de aktiverte. Ta deg et øyeblikk til å vurdere disse innstillingene for å forsikre deg om at de passer deg og ditt bruk."
|
||||
hint_html: "<strong>Tilpass hvordan du vil at din profil og dine innlegg skal bli funnet.</strong> En rekke funksjoner i Mastodon kan hjelpe deg med å nå et bredere publikum når det er aktivert. Ta deg et øyeblikk til å vurdere disse innstillingene for å forsikre deg om at de passer deg og ditt bruk."
|
||||
privacy: Personvern
|
||||
privacy_hint_html: Kontrollér hvor mye du ønsker å dele til fordel for andre. Folk oppdager interessante profiler og kule app'er ved å bla gjennom andres følgere og ved å se hvilke app'er de bruker, men du kan velge å holde det skjult.
|
||||
reach: Rekkevidde
|
||||
|
|
|
@ -623,6 +623,7 @@ sr:
|
|||
created_at: Пријављена
|
||||
delete_and_resolve: Обриши објаве
|
||||
forwarded: Прослеђено
|
||||
forwarded_replies_explanation: Овај извештај је од удаљеног корисника и о удаљеном садржају. Прослеђен вам је јер је пријављени садржај у одговору једном од ваших корисника.
|
||||
forwarded_to: Прослеђено ка %{domain}
|
||||
mark_as_resolved: Означи као решену
|
||||
mark_as_sensitive: Обележи као осетљиво
|
||||
|
|
|
@ -560,7 +560,7 @@ th:
|
|||
enabled: เปิดใช้งานอยู่
|
||||
inbox_url: URL ของรีเลย์
|
||||
pending: กำลังรอการอนุมัติของรีเลย์
|
||||
save_and_enable: บันทึกแล้วเปิดใช้งาน
|
||||
save_and_enable: บันทึกและเปิดใช้งาน
|
||||
setup: ตั้งค่าการเชื่อมต่อรีเลย์
|
||||
signatures_not_enabled: รีเลย์อาจทำงานไม่ถูกต้องขณะที่มีการเปิดใช้งานโหมดปลอดภัยหรือโหมดการติดต่อกับภายนอกแบบจำกัด
|
||||
status: สถานะ
|
||||
|
@ -599,7 +599,7 @@ th:
|
|||
created_at: รายงานเมื่อ
|
||||
delete_and_resolve: ลบโพสต์
|
||||
forwarded: ส่งต่อแล้ว
|
||||
forwarded_replies_explanation: รายงานนี้มาจากผู้ใช้ระยะไกล และเป็นรายงานเกี่ยวกับเนื้อหาระยะไกล ซึ่งถูกส่งต่อมาหาคุณเนื่องจากเนื้อหาที่ถูกรายงานอยู่ในการตอบกลับไปยังหนึ่งในผู้ใช้ของคุณ
|
||||
forwarded_replies_explanation: รายงานนี้มาจากผู้ใช้ระยะไกลและเกี่ยวกับเนื้อหาระยะไกล มีการส่งต่อรายงานไปยังคุณเนื่องจากเนื้อหาที่รายงานอยู่ในการตอบกลับหนึ่งในผู้ใช้ของคุณ
|
||||
forwarded_to: ส่งต่อไปยัง %{domain} แล้ว
|
||||
mark_as_resolved: ทำเครื่องหมายว่าแก้ปัญหาแล้ว
|
||||
mark_as_sensitive: ทำเครื่องหมายว่าละเอียดอ่อน
|
||||
|
|
|
@ -611,6 +611,7 @@ tr:
|
|||
created_at: Şikayet edildi
|
||||
delete_and_resolve: Gönderileri sil
|
||||
forwarded: İletildi
|
||||
forwarded_replies_explanation: Bu bildirim başka bir sunucudaki kullanıcı ve içerik ile ilgili. Bildirilen içerik kullanıcılarınızdan birine yanıt şeklinde olduğu için size yönlendirildi.
|
||||
forwarded_to: "%{domain}'e iletildi"
|
||||
mark_as_resolved: Giderildi olarak işaretle
|
||||
mark_as_sensitive: Hassas olarak işaretle
|
||||
|
|
|
@ -599,6 +599,7 @@ zh-CN:
|
|||
created_at: 举报时间
|
||||
delete_and_resolve: 删除嘟文
|
||||
forwarded: 已转发
|
||||
forwarded_replies_explanation: 该举报来自外站用户,涉及外站内容。之所以转发给您,是因为被举报的内容是对您站点一位用户的回复。
|
||||
forwarded_to: 转发举报至 %{domain}
|
||||
mark_as_resolved: 标记为已处理
|
||||
mark_as_sensitive: 标记为敏感内容
|
||||
|
|
|
@ -9,13 +9,3 @@ if Rake::Task.task_defined?('spec:system')
|
|||
|
||||
Rake::Task['spec:system'].enhance ['spec:enable_system_specs']
|
||||
end
|
||||
|
||||
if Rake::Task.task_defined?('spec:search')
|
||||
namespace :spec do
|
||||
task :enable_search_specs do # rubocop:disable Rails/RakeEnvironment
|
||||
ENV['RUN_SEARCH_SPECS'] = 'true'
|
||||
end
|
||||
end
|
||||
|
||||
Rake::Task['spec:search'].enhance ['spec:enable_search_specs']
|
||||
end
|
||||
|
|
5
spec/fabricators/account_deletion_request_fabricator.rb
Normal file
5
spec/fabricators/account_deletion_request_fabricator.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Fabricator(:account_deletion_request) do
|
||||
account
|
||||
end
|
7
spec/fabricators/import_fabricator.rb
Normal file
7
spec/fabricators/import_fabricator.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Fabricator(:import) do
|
||||
account
|
||||
type :following
|
||||
data { attachment_fixture('imports.txt') }
|
||||
end
|
|
@ -13,14 +13,13 @@ RSpec.describe AdminMailer do
|
|||
recipient.user.update(locale: :en)
|
||||
end
|
||||
|
||||
it 'renders the headers' do
|
||||
expect(mail.subject).to eq("New report for cb6e6126.ngrok.io (##{report.id})")
|
||||
expect(mail.to).to eq [recipient.user_email]
|
||||
expect(mail.from).to eq ['notifications@localhost']
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to eq("Mike,\r\n\r\nJohn has reported Mike\r\n\r\nView: https://cb6e6126.ngrok.io/admin/reports/#{report.id}\r\n")
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(deliver_to(recipient.user_email))
|
||||
.and(deliver_from('notifications@localhost'))
|
||||
.and(have_subject("New report for cb6e6126.ngrok.io (##{report.id})"))
|
||||
.and(have_body_text("Mike,\r\n\r\nJohn has reported Mike\r\n\r\nView: https://cb6e6126.ngrok.io/admin/reports/#{report.id}\r\n"))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -33,14 +32,13 @@ RSpec.describe AdminMailer do
|
|||
recipient.user.update(locale: :en)
|
||||
end
|
||||
|
||||
it 'renders the headers' do
|
||||
expect(mail.subject).to eq("#{appeal.account.username} is appealing a moderation decision on cb6e6126.ngrok.io")
|
||||
expect(mail.to).to eq [recipient.user_email]
|
||||
expect(mail.from).to eq ['notifications@localhost']
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to match "#{appeal.account.username} is appealing a moderation decision by #{appeal.strike.account.username}"
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(deliver_to(recipient.user_email))
|
||||
.and(deliver_from('notifications@localhost'))
|
||||
.and(have_subject("#{appeal.account.username} is appealing a moderation decision on cb6e6126.ngrok.io"))
|
||||
.and(have_body_text("#{appeal.account.username} is appealing a moderation decision by #{appeal.strike.account.username}"))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -53,14 +51,13 @@ RSpec.describe AdminMailer do
|
|||
recipient.user.update(locale: :en)
|
||||
end
|
||||
|
||||
it 'renders the headers' do
|
||||
expect(mail.subject).to eq("New account up for review on cb6e6126.ngrok.io (#{user.account.username})")
|
||||
expect(mail.to).to eq [recipient.user_email]
|
||||
expect(mail.from).to eq ['notifications@localhost']
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to match 'The details of the new account are below. You can approve or reject this application.'
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(deliver_to(recipient.user_email))
|
||||
.and(deliver_from('notifications@localhost'))
|
||||
.and(have_subject("New account up for review on cb6e6126.ngrok.io (#{user.account.username})"))
|
||||
.and(have_body_text('The details of the new account are below. You can approve or reject this application.'))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -95,14 +92,13 @@ RSpec.describe AdminMailer do
|
|||
recipient.user.update(locale: :en)
|
||||
end
|
||||
|
||||
it 'renders the headers' do
|
||||
expect(mail.subject).to eq('New trends up for review on cb6e6126.ngrok.io')
|
||||
expect(mail.to).to eq [recipient.user_email]
|
||||
expect(mail.from).to eq ['notifications@localhost']
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to match 'The following items need a review before they can be displayed publicly'
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(deliver_to(recipient.user_email))
|
||||
.and(deliver_from('notifications@localhost'))
|
||||
.and(have_subject('New trends up for review on cb6e6126.ngrok.io'))
|
||||
.and(have_body_text('The following items need a review before they can be displayed publicly'))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -114,14 +110,13 @@ RSpec.describe AdminMailer do
|
|||
recipient.user.update(locale: :en)
|
||||
end
|
||||
|
||||
it 'renders the headers' do
|
||||
expect(mail.subject).to eq('New Mastodon versions are available for cb6e6126.ngrok.io!')
|
||||
expect(mail.to).to eq [recipient.user_email]
|
||||
expect(mail.from).to eq ['notifications@localhost']
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to match 'New Mastodon versions have been released, you may want to update!'
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(deliver_to(recipient.user_email))
|
||||
.and(deliver_from('notifications@localhost'))
|
||||
.and(have_subject('New Mastodon versions are available for cb6e6126.ngrok.io!'))
|
||||
.and(have_body_text('New Mastodon versions have been released, you may want to update!'))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -133,18 +128,16 @@ RSpec.describe AdminMailer do
|
|||
recipient.user.update(locale: :en)
|
||||
end
|
||||
|
||||
it 'renders the headers', :aggregate_failures do
|
||||
expect(mail.subject).to eq('Critical Mastodon updates are available for cb6e6126.ngrok.io!')
|
||||
expect(mail.to).to eq [recipient.user_email]
|
||||
expect(mail.from).to eq ['notifications@localhost']
|
||||
|
||||
expect(mail['Importance'].value).to eq 'high'
|
||||
expect(mail['Priority'].value).to eq 'urgent'
|
||||
expect(mail['X-Priority'].value).to eq '1'
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to match 'New critical versions of Mastodon have been released, you may want to update as soon as possible!'
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(deliver_to(recipient.user_email))
|
||||
.and(deliver_from('notifications@localhost'))
|
||||
.and(have_subject('Critical Mastodon updates are available for cb6e6126.ngrok.io!'))
|
||||
.and(have_body_text('New critical versions of Mastodon have been released, you may want to update as soon as possible!'))
|
||||
.and(have_header('Importance', 'high'))
|
||||
.and(have_header('Priority', 'urgent'))
|
||||
.and(have_header('X-Priority', '1'))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,24 +8,27 @@ RSpec.describe NotificationMailer do
|
|||
let(:foreign_status) { Fabricate(:status, account: sender, text: 'The body of the foreign status') }
|
||||
let(:own_status) { Fabricate(:status, account: receiver.account, text: 'The body of the own status') }
|
||||
|
||||
shared_examples 'headers' do |type, thread|
|
||||
it 'renders the to and from headers' do
|
||||
expect(mail[:to].value).to eq "#{receiver.account.username} <#{receiver.email}>"
|
||||
expect(mail.from).to eq ['notifications@localhost']
|
||||
shared_examples 'standard headers' do |type|
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_header('To', "#{receiver.account.username} <#{receiver.email}>"))
|
||||
.and(have_header('List-ID', "<#{type}.alice.cb6e6126.ngrok.io>"))
|
||||
.and(have_header('List-Unsubscribe', %r{<https://cb6e6126.ngrok.io/unsubscribe\?token=.+>}))
|
||||
.and(have_header('List-Unsubscribe', /&type=#{type}/))
|
||||
.and(have_header('List-Unsubscribe-Post', 'List-Unsubscribe=One-Click'))
|
||||
.and(deliver_to("#{receiver.account.username} <#{receiver.email}>"))
|
||||
.and(deliver_from('notifications@localhost'))
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders the list headers' do
|
||||
expect(mail['List-ID'].value).to eq "<#{type}.alice.cb6e6126.ngrok.io>"
|
||||
expect(mail['List-Unsubscribe'].value).to match(%r{<https://cb6e6126.ngrok.io/unsubscribe\?token=.+>})
|
||||
expect(mail['List-Unsubscribe'].value).to match("&type=#{type}")
|
||||
expect(mail['List-Unsubscribe-Post'].value).to eq 'List-Unsubscribe=One-Click'
|
||||
end
|
||||
|
||||
if thread
|
||||
it 'renders the thread headers' do
|
||||
expect(mail['In-Reply-To'].value).to match(/<conversation-\d+.\d\d\d\d-\d\d-\d\d@cb6e6126.ngrok.io>/)
|
||||
expect(mail['References'].value).to match(/<conversation-\d+.\d\d\d\d-\d\d-\d\d@cb6e6126.ngrok.io>/)
|
||||
end
|
||||
shared_examples 'thread headers' do
|
||||
it 'renders the email with conversation thread headers' do
|
||||
conversation_header_regex = /<conversation-\d+.\d\d\d\d-\d\d-\d\d@cb6e6126.ngrok.io>/
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_header('In-Reply-To', conversation_header_regex))
|
||||
.and(have_header('References', conversation_header_regex))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -35,15 +38,15 @@ RSpec.describe NotificationMailer do
|
|||
let(:mail) { prepared_mailer_for(receiver.account).mention }
|
||||
|
||||
include_examples 'localized subject', 'notification_mailer.mention.subject', name: 'bob'
|
||||
include_examples 'headers', 'mention', true
|
||||
include_examples 'standard headers', 'mention'
|
||||
include_examples 'thread headers'
|
||||
|
||||
it 'renders the subject' do
|
||||
expect(mail.subject).to eq('You were mentioned by bob')
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to match('You were mentioned by bob')
|
||||
expect(mail.body.encoded).to include 'The body of the foreign status'
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject('You were mentioned by bob'))
|
||||
.and(have_body_text('You were mentioned by bob'))
|
||||
.and(have_body_text('The body of the foreign status'))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -53,14 +56,13 @@ RSpec.describe NotificationMailer do
|
|||
let(:mail) { prepared_mailer_for(receiver.account).follow }
|
||||
|
||||
include_examples 'localized subject', 'notification_mailer.follow.subject', name: 'bob'
|
||||
include_examples 'headers', 'follow', false
|
||||
include_examples 'standard headers', 'follow'
|
||||
|
||||
it 'renders the subject' do
|
||||
expect(mail.subject).to eq('bob is now following you')
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to match('bob is now following you')
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject('bob is now following you'))
|
||||
.and(have_body_text('bob is now following you'))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -70,15 +72,15 @@ RSpec.describe NotificationMailer do
|
|||
let(:mail) { prepared_mailer_for(own_status.account).favourite }
|
||||
|
||||
include_examples 'localized subject', 'notification_mailer.favourite.subject', name: 'bob'
|
||||
include_examples 'headers', 'favourite', true
|
||||
include_examples 'standard headers', 'favourite'
|
||||
include_examples 'thread headers'
|
||||
|
||||
it 'renders the subject' do
|
||||
expect(mail.subject).to eq('bob favorited your post')
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to match('Your post was favorited by bob')
|
||||
expect(mail.body.encoded).to include 'The body of the own status'
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject('bob favorited your post'))
|
||||
.and(have_body_text('Your post was favorited by bob'))
|
||||
.and(have_body_text('The body of the own status'))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -88,15 +90,15 @@ RSpec.describe NotificationMailer do
|
|||
let(:mail) { prepared_mailer_for(own_status.account).reblog }
|
||||
|
||||
include_examples 'localized subject', 'notification_mailer.reblog.subject', name: 'bob'
|
||||
include_examples 'headers', 'reblog', true
|
||||
include_examples 'standard headers', 'reblog'
|
||||
include_examples 'thread headers'
|
||||
|
||||
it 'renders the subject' do
|
||||
expect(mail.subject).to eq('bob boosted your post')
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to match('Your post was boosted by bob')
|
||||
expect(mail.body.encoded).to include 'The body of the own status'
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject('bob boosted your post'))
|
||||
.and(have_body_text('Your post was boosted by bob'))
|
||||
.and(have_body_text('The body of the own status'))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -106,14 +108,13 @@ RSpec.describe NotificationMailer do
|
|||
let(:mail) { prepared_mailer_for(receiver.account).follow_request }
|
||||
|
||||
include_examples 'localized subject', 'notification_mailer.follow_request.subject', name: 'bob'
|
||||
include_examples 'headers', 'follow_request', false
|
||||
include_examples 'standard headers', 'follow_request'
|
||||
|
||||
it 'renders the subject' do
|
||||
expect(mail.subject).to eq('Pending follower: bob')
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to match('bob has requested to follow you')
|
||||
it 'renders the email' do
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject('Pending follower: bob'))
|
||||
.and(have_body_text('bob has requested to follow you'))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -10,9 +10,12 @@ describe UserMailer do
|
|||
|
||||
it 'renders confirmation instructions' do
|
||||
receiver.update!(locale: nil)
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.confirmation_instructions.title')
|
||||
expect(mail.body.encoded).to include 'spec'
|
||||
expect(mail.body.encoded).to include Rails.configuration.x.local_domain
|
||||
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_body_text(I18n.t('devise.mailer.confirmation_instructions.title')))
|
||||
.and(have_body_text('spec'))
|
||||
.and(have_body_text(Rails.configuration.x.local_domain))
|
||||
end
|
||||
|
||||
include_examples 'localized subject',
|
||||
|
@ -25,13 +28,17 @@ describe UserMailer do
|
|||
|
||||
it 'renders reconfirmation instructions' do
|
||||
receiver.update!(email: 'new-email@example.com', locale: nil)
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.reconfirmation_instructions.title')
|
||||
expect(mail.body.encoded).to include 'spec'
|
||||
expect(mail.body.encoded).to include Rails.configuration.x.local_domain
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.reconfirmation_instructions.subject',
|
||||
instance: Rails.configuration.x.local_domain,
|
||||
locale: I18n.default_locale)
|
||||
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_body_text(I18n.t('devise.mailer.reconfirmation_instructions.title')))
|
||||
.and(have_body_text('spec'))
|
||||
.and(have_body_text(Rails.configuration.x.local_domain))
|
||||
end
|
||||
|
||||
include_examples 'localized subject',
|
||||
'devise.mailer.confirmation_instructions.subject',
|
||||
instance: Rails.configuration.x.local_domain
|
||||
end
|
||||
|
||||
describe '#reset_password_instructions' do
|
||||
|
@ -39,8 +46,11 @@ describe UserMailer do
|
|||
|
||||
it 'renders reset password instructions' do
|
||||
receiver.update!(locale: nil)
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.reset_password_instructions.title')
|
||||
expect(mail.body.encoded).to include 'spec'
|
||||
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_body_text(I18n.t('devise.mailer.reset_password_instructions.title')))
|
||||
.and(have_body_text('spec'))
|
||||
end
|
||||
|
||||
include_examples 'localized subject',
|
||||
|
@ -52,7 +62,10 @@ describe UserMailer do
|
|||
|
||||
it 'renders password change notification' do
|
||||
receiver.update!(locale: nil)
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.password_change.title')
|
||||
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_body_text(I18n.t('devise.mailer.password_change.title')))
|
||||
end
|
||||
|
||||
include_examples 'localized subject',
|
||||
|
@ -64,7 +77,10 @@ describe UserMailer do
|
|||
|
||||
it 'renders email change notification' do
|
||||
receiver.update!(locale: nil)
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.email_changed.title')
|
||||
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_body_text(I18n.t('devise.mailer.email_changed.title')))
|
||||
end
|
||||
|
||||
include_examples 'localized subject',
|
||||
|
@ -77,8 +93,11 @@ describe UserMailer do
|
|||
|
||||
it 'renders warning notification' do
|
||||
receiver.update!(locale: nil)
|
||||
expect(mail.body.encoded).to include I18n.t('user_mailer.warning.title.suspend', acct: receiver.account.acct)
|
||||
expect(mail.body.encoded).to include strike.text
|
||||
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_body_text(I18n.t('user_mailer.warning.title.suspend', acct: receiver.account.acct)))
|
||||
.and(have_body_text(strike.text))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -88,7 +107,10 @@ describe UserMailer do
|
|||
|
||||
it 'renders webauthn credential deleted notification' do
|
||||
receiver.update!(locale: nil)
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.webauthn_credential.deleted.title')
|
||||
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_body_text(I18n.t('devise.mailer.webauthn_credential.deleted.title')))
|
||||
end
|
||||
|
||||
include_examples 'localized subject',
|
||||
|
@ -103,7 +125,10 @@ describe UserMailer do
|
|||
|
||||
it 'renders suspicious sign in notification' do
|
||||
receiver.update!(locale: nil)
|
||||
expect(mail.body.encoded).to include I18n.t('user_mailer.suspicious_sign_in.explanation')
|
||||
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_body_text(I18n.t('user_mailer.suspicious_sign_in.explanation')))
|
||||
end
|
||||
|
||||
include_examples 'localized subject',
|
||||
|
@ -115,8 +140,10 @@ describe UserMailer do
|
|||
let(:mail) { described_class.appeal_approved(receiver, appeal) }
|
||||
|
||||
it 'renders appeal_approved notification' do
|
||||
expect(mail.subject).to eq I18n.t('user_mailer.appeal_approved.subject', date: I18n.l(appeal.created_at))
|
||||
expect(mail.body.encoded).to include I18n.t('user_mailer.appeal_approved.title')
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject(I18n.t('user_mailer.appeal_approved.subject', date: I18n.l(appeal.created_at))))
|
||||
.and(have_body_text(I18n.t('user_mailer.appeal_approved.title')))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -125,8 +152,10 @@ describe UserMailer do
|
|||
let(:mail) { described_class.appeal_rejected(receiver, appeal) }
|
||||
|
||||
it 'renders appeal_rejected notification' do
|
||||
expect(mail.subject).to eq I18n.t('user_mailer.appeal_rejected.subject', date: I18n.l(appeal.created_at))
|
||||
expect(mail.body.encoded).to include I18n.t('user_mailer.appeal_rejected.title')
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject(I18n.t('user_mailer.appeal_rejected.subject', date: I18n.l(appeal.created_at))))
|
||||
.and(have_body_text(I18n.t('user_mailer.appeal_rejected.title')))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -134,8 +163,10 @@ describe UserMailer do
|
|||
let(:mail) { described_class.two_factor_enabled(receiver) }
|
||||
|
||||
it 'renders two_factor_enabled mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.two_factor_enabled.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.two_factor_enabled.explanation')
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject(I18n.t('devise.mailer.two_factor_enabled.subject')))
|
||||
.and(have_body_text(I18n.t('devise.mailer.two_factor_enabled.explanation')))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -143,8 +174,10 @@ describe UserMailer do
|
|||
let(:mail) { described_class.two_factor_disabled(receiver) }
|
||||
|
||||
it 'renders two_factor_disabled mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.two_factor_disabled.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.two_factor_disabled.explanation')
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject(I18n.t('devise.mailer.two_factor_disabled.subject')))
|
||||
.and(have_body_text(I18n.t('devise.mailer.two_factor_disabled.explanation')))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -152,8 +185,10 @@ describe UserMailer do
|
|||
let(:mail) { described_class.webauthn_enabled(receiver) }
|
||||
|
||||
it 'renders webauthn_enabled mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.webauthn_enabled.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.webauthn_enabled.explanation')
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject(I18n.t('devise.mailer.webauthn_enabled.subject')))
|
||||
.and(have_body_text(I18n.t('devise.mailer.webauthn_enabled.explanation')))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -161,8 +196,10 @@ describe UserMailer do
|
|||
let(:mail) { described_class.webauthn_disabled(receiver) }
|
||||
|
||||
it 'renders webauthn_disabled mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.webauthn_disabled.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.webauthn_disabled.explanation')
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject(I18n.t('devise.mailer.webauthn_disabled.subject')))
|
||||
.and(have_body_text(I18n.t('devise.mailer.webauthn_disabled.explanation')))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -170,8 +207,10 @@ describe UserMailer do
|
|||
let(:mail) { described_class.two_factor_recovery_codes_changed(receiver) }
|
||||
|
||||
it 'renders two_factor_recovery_codes_changed mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.two_factor_recovery_codes_changed.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.two_factor_recovery_codes_changed.explanation')
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject(I18n.t('devise.mailer.two_factor_recovery_codes_changed.subject')))
|
||||
.and(have_body_text(I18n.t('devise.mailer.two_factor_recovery_codes_changed.explanation')))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -180,8 +219,10 @@ describe UserMailer do
|
|||
let(:mail) { described_class.webauthn_credential_added(receiver, credential) }
|
||||
|
||||
it 'renders webauthn_credential_added mail' do
|
||||
expect(mail.subject).to eq I18n.t('devise.mailer.webauthn_credential.added.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('devise.mailer.webauthn_credential.added.explanation')
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject(I18n.t('devise.mailer.webauthn_credential.added.subject')))
|
||||
.and(have_body_text(I18n.t('devise.mailer.webauthn_credential.added.explanation')))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -189,8 +230,10 @@ describe UserMailer do
|
|||
let(:mail) { described_class.welcome(receiver) }
|
||||
|
||||
it 'renders welcome mail' do
|
||||
expect(mail.subject).to eq I18n.t('user_mailer.welcome.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('user_mailer.welcome.explanation')
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject(I18n.t('user_mailer.welcome.subject')))
|
||||
.and(have_body_text(I18n.t('user_mailer.welcome.explanation')))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -199,8 +242,10 @@ describe UserMailer do
|
|||
let(:mail) { described_class.backup_ready(receiver, backup) }
|
||||
|
||||
it 'renders backup_ready mail' do
|
||||
expect(mail.subject).to eq I18n.t('user_mailer.backup_ready.subject')
|
||||
expect(mail.body.encoded).to include I18n.t('user_mailer.backup_ready.explanation')
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_subject(I18n.t('user_mailer.backup_ready.subject')))
|
||||
.and(have_body_text(I18n.t('user_mailer.backup_ready.explanation')))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,12 +23,14 @@ RSpec.describe AccountRelationshipsPresenter do
|
|||
let(:options) { {} }
|
||||
|
||||
it 'sets default maps' do
|
||||
expect(presenter.following).to eq default_map
|
||||
expect(presenter.followed_by).to eq default_map
|
||||
expect(presenter.blocking).to eq default_map
|
||||
expect(presenter.muting).to eq default_map
|
||||
expect(presenter.requested).to eq default_map
|
||||
expect(presenter.domain_blocking).to eq default_map
|
||||
expect(presenter).to have_attributes(
|
||||
following: default_map,
|
||||
followed_by: default_map,
|
||||
blocking: default_map,
|
||||
muting: default_map,
|
||||
requested: default_map,
|
||||
domain_blocking: default_map
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -22,9 +22,12 @@ RSpec.describe FamiliarFollowersPresenter do
|
|||
it 'returns followers you follow' do
|
||||
result = subject.accounts.first
|
||||
|
||||
expect(result).to_not be_nil
|
||||
expect(result.id).to eq requested_accounts.first.id
|
||||
expect(result.accounts).to contain_exactly(familiar_follower)
|
||||
expect(result)
|
||||
.to be_present
|
||||
.and have_attributes(
|
||||
id: requested_accounts.first.id,
|
||||
accounts: contain_exactly(familiar_follower)
|
||||
)
|
||||
end
|
||||
|
||||
context 'when requested account hides followers' do
|
||||
|
@ -35,9 +38,12 @@ RSpec.describe FamiliarFollowersPresenter do
|
|||
it 'does not return followers you follow' do
|
||||
result = subject.accounts.first
|
||||
|
||||
expect(result).to_not be_nil
|
||||
expect(result.id).to eq requested_accounts.first.id
|
||||
expect(result.accounts).to be_empty
|
||||
expect(result)
|
||||
.to be_present
|
||||
.and have_attributes(
|
||||
id: requested_accounts.first.id,
|
||||
accounts: be_empty
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -49,9 +55,12 @@ RSpec.describe FamiliarFollowersPresenter do
|
|||
it 'does not return followers you follow' do
|
||||
result = subject.accounts.first
|
||||
|
||||
expect(result).to_not be_nil
|
||||
expect(result.id).to eq requested_accounts.first.id
|
||||
expect(result.accounts).to be_empty
|
||||
expect(result)
|
||||
.to be_present
|
||||
.and have_attributes(
|
||||
id: requested_accounts.first.id,
|
||||
accounts: be_empty
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,11 +22,13 @@ RSpec.describe StatusRelationshipsPresenter do
|
|||
let(:options) { {} }
|
||||
|
||||
it 'sets default maps' do
|
||||
expect(presenter.reblogs_map).to eq default_map
|
||||
expect(presenter.favourites_map).to eq default_map
|
||||
expect(presenter.bookmarks_map).to eq default_map
|
||||
expect(presenter.mutes_map).to eq default_map
|
||||
expect(presenter.pins_map).to eq default_map
|
||||
expect(presenter).to have_attributes(
|
||||
reblogs_map: eq(default_map),
|
||||
favourites_map: eq(default_map),
|
||||
bookmarks_map: eq(default_map),
|
||||
mutes_map: eq(default_map),
|
||||
pins_map: eq(default_map)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -80,18 +82,30 @@ RSpec.describe StatusRelationshipsPresenter do
|
|||
|
||||
it 'sets @filters_map to filter top-level status' do
|
||||
matched_filters = presenter.filters_map[statuses[0].id]
|
||||
expect(matched_filters.size).to eq 1
|
||||
|
||||
expect(matched_filters[0].filter.title).to eq 'filter1'
|
||||
expect(matched_filters[0].keyword_matches).to eq ['banned']
|
||||
expect(matched_filters)
|
||||
.to be_an(Array)
|
||||
.and have_attributes(size: 1)
|
||||
.and contain_exactly(
|
||||
have_attributes(
|
||||
filter: have_attributes(title: 'filter1'),
|
||||
keyword_matches: contain_exactly('banned')
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
it 'sets @filters_map to filter reblogged status' do
|
||||
matched_filters = presenter.filters_map[statuses[1].reblog_of_id]
|
||||
expect(matched_filters.size).to eq 1
|
||||
|
||||
expect(matched_filters[0].filter.title).to eq 'filter1'
|
||||
expect(matched_filters[0].keyword_matches).to eq ['irrelevant']
|
||||
expect(matched_filters)
|
||||
.to be_an(Array)
|
||||
.and have_attributes(size: 1)
|
||||
.and contain_exactly(
|
||||
have_attributes(
|
||||
filter: have_attributes(title: 'filter1'),
|
||||
keyword_matches: contain_exactly('irrelevant')
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -107,18 +121,30 @@ RSpec.describe StatusRelationshipsPresenter do
|
|||
|
||||
it 'sets @filters_map to filter top-level status' do
|
||||
matched_filters = presenter.filters_map[statuses[0].id]
|
||||
expect(matched_filters.size).to eq 1
|
||||
|
||||
expect(matched_filters[0].filter.title).to eq 'filter1'
|
||||
expect(matched_filters[0].status_matches).to eq [statuses[0].id]
|
||||
expect(matched_filters)
|
||||
.to be_an(Array)
|
||||
.and have_attributes(size: 1)
|
||||
.and contain_exactly(
|
||||
have_attributes(
|
||||
filter: have_attributes(title: 'filter1'),
|
||||
status_matches: contain_exactly(statuses.first.id)
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
it 'sets @filters_map to filter reblogged status' do
|
||||
matched_filters = presenter.filters_map[statuses[1].reblog_of_id]
|
||||
expect(matched_filters.size).to eq 1
|
||||
|
||||
expect(matched_filters[0].filter.title).to eq 'filter1'
|
||||
expect(matched_filters[0].status_matches).to eq [statuses[1].reblog_of_id]
|
||||
expect(matched_filters)
|
||||
.to be_an(Array)
|
||||
.and have_attributes(size: 1)
|
||||
.and contain_exactly(
|
||||
have_attributes(
|
||||
filter: have_attributes(title: 'filter1'),
|
||||
status_matches: contain_exactly(statuses.second.reblog_of_id)
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,6 @@ ENV['RAILS_ENV'] ||= 'test'
|
|||
|
||||
# This needs to be defined before Rails is initialized
|
||||
RUN_SYSTEM_SPECS = ENV.fetch('RUN_SYSTEM_SPECS', false)
|
||||
RUN_SEARCH_SPECS = ENV.fetch('RUN_SEARCH_SPECS', false)
|
||||
|
||||
if RUN_SYSTEM_SPECS
|
||||
STREAMING_PORT = ENV.fetch('TEST_STREAMING_PORT', '4020')
|
||||
|
@ -21,6 +20,7 @@ require 'webmock/rspec'
|
|||
require 'paperclip/matchers'
|
||||
require 'capybara/rspec'
|
||||
require 'chewy/rspec'
|
||||
require 'email_spec/rspec'
|
||||
|
||||
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
|
||||
|
||||
|
@ -54,20 +54,28 @@ RSpec.configure do |config|
|
|||
case type
|
||||
when :system
|
||||
!RUN_SYSTEM_SPECS
|
||||
when :search
|
||||
!RUN_SEARCH_SPECS
|
||||
end
|
||||
}
|
||||
|
||||
# By default, skip the elastic search integration specs
|
||||
config.filter_run_excluding search: true
|
||||
|
||||
config.fixture_path = Rails.root.join('spec', 'fixtures')
|
||||
config.use_transactional_fixtures = true
|
||||
config.order = 'random'
|
||||
config.infer_spec_type_from_file_location!
|
||||
config.filter_rails_from_backtrace!
|
||||
|
||||
# Set type to `cli` for all CLI specs
|
||||
config.define_derived_metadata(file_path: Regexp.new('spec/lib/mastodon/cli')) do |metadata|
|
||||
metadata[:type] = :cli
|
||||
end
|
||||
|
||||
# Set `search` metadata true for all specs in spec/search/
|
||||
config.define_derived_metadata(file_path: Regexp.new('spec/search/*')) do |metadata|
|
||||
metadata[:search] = true
|
||||
end
|
||||
|
||||
config.include Devise::Test::ControllerHelpers, type: :controller
|
||||
config.include Devise::Test::ControllerHelpers, type: :helper
|
||||
config.include Devise::Test::ControllerHelpers, type: :view
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'GET /api/v1/accounts/{account_id}' do
|
||||
it 'returns account entity as 200 OK' do
|
||||
account = Fabricate(:account)
|
||||
|
||||
get "/api/v1/accounts/#{account.id}"
|
||||
|
||||
aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json[:id]).to eq(account.id.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns 404 if account not found' do
|
||||
get '/api/v1/accounts/1'
|
||||
|
||||
aggregate_failures do
|
||||
expect(response).to have_http_status(404)
|
||||
expect(body_as_json[:error]).to eq('Record not found')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when with token' do
|
||||
it 'returns account entity as 200 OK if token is valid' do
|
||||
account = Fabricate(:account)
|
||||
user = Fabricate(:user, account: account)
|
||||
token = Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts').token
|
||||
|
||||
get "/api/v1/accounts/#{account.id}", headers: { Authorization: "Bearer #{token}" }
|
||||
|
||||
aggregate_failures do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json[:id]).to eq(account.id.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns 403 if scope of token is invalid' do
|
||||
account = Fabricate(:account)
|
||||
user = Fabricate(:user, account: account)
|
||||
token = Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:statuses').token
|
||||
|
||||
get "/api/v1/accounts/#{account.id}", headers: { Authorization: "Bearer #{token}" }
|
||||
|
||||
aggregate_failures do
|
||||
expect(response).to have_http_status(403)
|
||||
expect(body_as_json[:error]).to eq('This action is outside the authorized scopes')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,65 +2,108 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::AccountsController do
|
||||
render_views
|
||||
describe '/api/v1/accounts' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:scopes) { '' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:scopes) { '' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
describe 'GET /api/v1/accounts/:id' do
|
||||
context 'when logged out' do
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
it 'returns account entity as 200 OK', :aggregate_failures do
|
||||
get "/api/v1/accounts/#{account.id}"
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json[:id]).to eq(account.id.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the account does not exist' do
|
||||
it 'returns http not found' do
|
||||
get '/api/v1/accounts/1'
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(body_as_json[:error]).to eq('Record not found')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when logged in' do
|
||||
subject do
|
||||
get "/api/v1/accounts/#{account.id}", headers: headers
|
||||
end
|
||||
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:scopes) { 'read:accounts' }
|
||||
|
||||
it 'returns account entity as 200 OK', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json[:id]).to eq(account.id.to_s)
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:app) { Fabricate(:application) }
|
||||
let(:token) { Doorkeeper::AccessToken.find_or_create_for(application: app, resource_owner: nil, scopes: 'read write', use_refresh_token: false) }
|
||||
let(:agreement) { nil }
|
||||
|
||||
before do
|
||||
post :create, params: { username: 'test', password: '12345678', email: 'hello@world.tld', agreement: agreement }
|
||||
describe 'POST /api/v1/accounts' do
|
||||
subject do
|
||||
post '/api/v1/accounts', headers: headers, params: { username: 'test', password: '12345678', email: 'hello@world.tld', agreement: agreement }
|
||||
end
|
||||
|
||||
let(:client_app) { Fabricate(:application) }
|
||||
let(:token) { Doorkeeper::AccessToken.find_or_create_for(application: client_app, resource_owner: nil, scopes: 'read write', use_refresh_token: false) }
|
||||
let(:agreement) { nil }
|
||||
|
||||
context 'when given truthy agreement' do
|
||||
let(:agreement) { 'true' }
|
||||
|
||||
it 'creates a user', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json[:access_token]).to_not be_blank
|
||||
|
||||
user = User.find_by(email: 'hello@world.tld')
|
||||
expect(user).to_not be_nil
|
||||
expect(user.created_by_application_id).to eq app.id
|
||||
expect(user.created_by_application_id).to eq client_app.id
|
||||
end
|
||||
end
|
||||
|
||||
context 'when given no agreement' do
|
||||
it 'returns http unprocessable entity' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #follow' do
|
||||
describe 'POST /api/v1/accounts/:id/follow' do
|
||||
let(:scopes) { 'write:follows' }
|
||||
let(:my_actor_type) { 'Person' }
|
||||
let(:lock_follow_from_bot) { false }
|
||||
let(:other_account) { Fabricate(:account, username: 'bob', locked: locked) }
|
||||
|
||||
context 'when posting to an other account' do
|
||||
subject do
|
||||
post "/api/v1/accounts/#{other_account.id}/follow", headers: headers
|
||||
end
|
||||
|
||||
before do
|
||||
other_account.user.settings['lock_follow_from_bot'] = lock_follow_from_bot
|
||||
other_account.user.save!
|
||||
user.account.update!(actor_type: my_actor_type)
|
||||
|
||||
post :follow, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
context 'with unlocked account' do
|
||||
let(:locked) { false }
|
||||
|
||||
it 'creates a following relation between user and target user', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
|
||||
json = body_as_json
|
||||
|
@ -78,6 +121,8 @@ RSpec.describe Api::V1::AccountsController do
|
|||
let(:locked) { true }
|
||||
|
||||
it 'creates a follow request relation between user and target user', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
|
||||
json = body_as_json
|
||||
|
@ -97,10 +142,14 @@ RSpec.describe Api::V1::AccountsController do
|
|||
let(:my_actor_type) { 'Service' }
|
||||
|
||||
it 'returns http success' do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'returns JSON with following=false and requested=true' do
|
||||
subject
|
||||
|
||||
json = body_as_json
|
||||
|
||||
expect(json[:following]).to be false
|
||||
|
@ -108,6 +157,8 @@ RSpec.describe Api::V1::AccountsController do
|
|||
end
|
||||
|
||||
it 'creates a follow request relation between user and target user' do
|
||||
subject
|
||||
|
||||
expect(user.account.requested?(other_account)).to be true
|
||||
end
|
||||
|
||||
|
@ -123,48 +174,53 @@ RSpec.describe Api::V1::AccountsController do
|
|||
end
|
||||
|
||||
it 'changes reblogs option' do
|
||||
post :follow, params: { id: other_account.id, reblogs: true }
|
||||
post "/api/v1/accounts/#{other_account.id}/follow", headers: headers, params: { reblogs: true }
|
||||
|
||||
json = body_as_json
|
||||
|
||||
expect(json[:following]).to be true
|
||||
expect(json[:showing_reblogs]).to be true
|
||||
expect(json[:notifying]).to be false
|
||||
expect(body_as_json).to include({
|
||||
following: true,
|
||||
showing_reblogs: true,
|
||||
notifying: false,
|
||||
})
|
||||
end
|
||||
|
||||
it 'changes notify option' do
|
||||
post :follow, params: { id: other_account.id, notify: true }
|
||||
post "/api/v1/accounts/#{other_account.id}/follow", headers: headers, params: { notify: true }
|
||||
|
||||
json = body_as_json
|
||||
|
||||
expect(json[:following]).to be true
|
||||
expect(json[:showing_reblogs]).to be false
|
||||
expect(json[:notifying]).to be true
|
||||
expect(body_as_json).to include({
|
||||
following: true,
|
||||
showing_reblogs: false,
|
||||
notifying: true,
|
||||
})
|
||||
end
|
||||
|
||||
it 'changes languages option' do
|
||||
post :follow, params: { id: other_account.id, languages: %w(en es) }
|
||||
post "/api/v1/accounts/#{other_account.id}/follow", headers: headers, params: { languages: %w(en es) }
|
||||
|
||||
json = body_as_json
|
||||
|
||||
expect(json[:following]).to be true
|
||||
expect(json[:showing_reblogs]).to be false
|
||||
expect(json[:notifying]).to be false
|
||||
expect(json[:languages]).to match_array %w(en es)
|
||||
expect(body_as_json).to include({
|
||||
following: true,
|
||||
showing_reblogs: false,
|
||||
notifying: false,
|
||||
languages: match_array(%w(en es)),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #unfollow' do
|
||||
describe 'POST /api/v1/accounts/:id/unfollow' do
|
||||
subject do
|
||||
post "/api/v1/accounts/#{other_account.id}/unfollow", headers: headers
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:follows' }
|
||||
let(:other_account) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
user.account.follow!(other_account)
|
||||
post :unfollow, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'removes the following relation between user and target user', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(user.account.following?(other_account)).to be false
|
||||
end
|
||||
|
@ -172,16 +228,21 @@ RSpec.describe Api::V1::AccountsController do
|
|||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #remove_from_followers' do
|
||||
describe 'POST /api/v1/accounts/:id/remove_from_followers' do
|
||||
subject do
|
||||
post "/api/v1/accounts/#{other_account.id}/remove_from_followers", headers: headers
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:follows' }
|
||||
let(:other_account) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
other_account.follow!(user.account)
|
||||
post :remove_from_followers, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'removes the followed relation between user and target user', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(user.account.followed_by?(other_account)).to be false
|
||||
end
|
||||
|
@ -189,16 +250,21 @@ RSpec.describe Api::V1::AccountsController do
|
|||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #block' do
|
||||
describe 'POST /api/v1/accounts/:id/block' do
|
||||
subject do
|
||||
post "/api/v1/accounts/#{other_account.id}/block", headers: headers
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:blocks' }
|
||||
let(:other_account) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
user.account.follow!(other_account)
|
||||
post :block, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'creates a blocking relation', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(user.account.following?(other_account)).to be false
|
||||
expect(user.account.blocking?(other_account)).to be true
|
||||
|
@ -207,16 +273,21 @@ RSpec.describe Api::V1::AccountsController do
|
|||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #unblock' do
|
||||
describe 'POST /api/v1/accounts/:id/unblock' do
|
||||
subject do
|
||||
post "/api/v1/accounts/#{other_account.id}/unblock", headers: headers
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:blocks' }
|
||||
let(:other_account) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
user.account.block!(other_account)
|
||||
post :unblock, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'removes the blocking relation between user and target user', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(user.account.blocking?(other_account)).to be false
|
||||
end
|
||||
|
@ -224,16 +295,21 @@ RSpec.describe Api::V1::AccountsController do
|
|||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #mute' do
|
||||
describe 'POST /api/v1/accounts/:id/mute' do
|
||||
subject do
|
||||
post "/api/v1/accounts/#{other_account.id}/mute", headers: headers
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:mutes' }
|
||||
let(:other_account) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
user.account.follow!(other_account)
|
||||
post :mute, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'mutes notifications', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(user.account.following?(other_account)).to be true
|
||||
expect(user.account.muting?(other_account)).to be true
|
||||
|
@ -243,16 +319,21 @@ RSpec.describe Api::V1::AccountsController do
|
|||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #mute with notifications set to false' do
|
||||
describe 'POST /api/v1/accounts/:id/mute with notifications set to false' do
|
||||
subject do
|
||||
post "/api/v1/accounts/#{other_account.id}/mute", headers: headers, params: { notifications: false }
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:mutes' }
|
||||
let(:other_account) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
user.account.follow!(other_account)
|
||||
post :mute, params: { id: other_account.id, notifications: false }
|
||||
end
|
||||
|
||||
it 'does not mute notifications', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(user.account.following?(other_account)).to be true
|
||||
expect(user.account.muting?(other_account)).to be true
|
||||
|
@ -262,16 +343,21 @@ RSpec.describe Api::V1::AccountsController do
|
|||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #mute with nonzero duration set' do
|
||||
describe 'POST /api/v1/accounts/:id/mute with nonzero duration set' do
|
||||
subject do
|
||||
post "/api/v1/accounts/#{other_account.id}/mute", headers: headers, params: { duration: 300 }
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:mutes' }
|
||||
let(:other_account) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
user.account.follow!(other_account)
|
||||
post :mute, params: { id: other_account.id, duration: 300 }
|
||||
end
|
||||
|
||||
it 'mutes notifications', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(user.account.following?(other_account)).to be true
|
||||
expect(user.account.muting?(other_account)).to be true
|
||||
|
@ -281,16 +367,21 @@ RSpec.describe Api::V1::AccountsController do
|
|||
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
|
||||
end
|
||||
|
||||
describe 'POST #unmute' do
|
||||
describe 'POST /api/v1/accounts/:id/unmute' do
|
||||
subject do
|
||||
post "/api/v1/accounts/#{other_account.id}/unmute", headers: headers
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:mutes' }
|
||||
let(:other_account) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
user.account.mute!(other_account)
|
||||
post :unmute, params: { id: other_account.id }
|
||||
end
|
||||
|
||||
it 'removes the muting relation between user and target user', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(user.account.muting?(other_account)).to be false
|
||||
end
|
|
@ -8,18 +8,12 @@ RSpec.describe 'Account actions' do
|
|||
let(:scopes) { 'admin:write admin:write:accounts' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:mailer) { instance_double(ActionMailer::MessageDelivery, deliver_later!: nil) }
|
||||
|
||||
before do
|
||||
allow(UserMailer).to receive(:warning).with(target_account.user, anything).and_return(mailer)
|
||||
end
|
||||
|
||||
shared_examples 'a successful notification delivery' do
|
||||
it 'notifies the user about the action taken' do
|
||||
subject
|
||||
|
||||
expect(UserMailer).to have_received(:warning).with(target_account.user, anything).once
|
||||
expect(mailer).to have_received(:deliver_later!).once
|
||||
expect { subject }
|
||||
.to have_enqueued_job(ActionMailer::MailDeliveryJob)
|
||||
.with('UserMailer', 'warning', 'deliver_now!', args: [User, AccountWarning])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,24 +2,26 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::StatusesController 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, application: app, scopes: scopes) }
|
||||
|
||||
describe '/api/v1/statuses' do
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:client_app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: client_app, scopes: scopes) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
describe 'GET /api/v1/statuses/:id' do
|
||||
subject do
|
||||
get "/api/v1/statuses/#{status.id}", headers: headers
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
let(:scopes) { 'read:statuses' }
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'write write:statuses'
|
||||
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: status.id }
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
|
@ -31,11 +33,10 @@ RSpec.describe Api::V1::StatusesController do
|
|||
end
|
||||
|
||||
it 'returns filter information', :aggregate_failures do
|
||||
get :show, params: { id: status.id }
|
||||
json = body_as_json
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json[:filtered][0]).to include({
|
||||
expect(body_as_json[:filtered][0]).to include({
|
||||
filter: a_hash_including({
|
||||
id: user.account.custom_filters.first.id.to_s,
|
||||
title: 'filter1',
|
||||
|
@ -55,11 +56,10 @@ RSpec.describe Api::V1::StatusesController do
|
|||
end
|
||||
|
||||
it 'returns filter information', :aggregate_failures do
|
||||
get :show, params: { id: status.id }
|
||||
json = body_as_json
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json[:filtered][0]).to include({
|
||||
expect(body_as_json[:filtered][0]).to include({
|
||||
filter: a_hash_including({
|
||||
id: user.account.custom_filters.first.id.to_s,
|
||||
title: 'filter1',
|
||||
|
@ -78,11 +78,10 @@ RSpec.describe Api::V1::StatusesController do
|
|||
end
|
||||
|
||||
it 'returns filter information', :aggregate_failures do
|
||||
get :show, params: { id: status.id }
|
||||
json = body_as_json
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json[:reblog][:filtered][0]).to include({
|
||||
expect(body_as_json[:reblog][:filtered][0]).to include({
|
||||
filter: a_hash_including({
|
||||
id: user.account.custom_filters.first.id.to_s,
|
||||
title: 'filter1',
|
||||
|
@ -94,7 +93,7 @@ RSpec.describe Api::V1::StatusesController do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'GET #context' do
|
||||
describe 'GET /api/v1/statuses/:id/context' do
|
||||
let(:scopes) { 'read:statuses' }
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
let!(:thread) { Fabricate(:status, account: user.account, thread: status) }
|
||||
|
@ -142,7 +141,8 @@ RSpec.describe Api::V1::StatusesController do
|
|||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :context, params: { id: status.id }
|
||||
get "/api/v1/statuses/#{status.id}/context", headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
|
@ -190,15 +190,20 @@ RSpec.describe Api::V1::StatusesController do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
describe 'POST /api/v1/statuses' do
|
||||
subject do
|
||||
post '/api/v1/statuses', headers: headers, params: params
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:statuses' }
|
||||
let(:params) { { status: 'Hello world' } }
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read read:statuses'
|
||||
|
||||
context 'with a basic status body' do
|
||||
before do
|
||||
post :create, params: { status: 'Hello world' }
|
||||
end
|
||||
|
||||
it 'returns rate limit headers', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
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
|
||||
|
@ -209,22 +214,22 @@ RSpec.describe Api::V1::StatusesController do
|
|||
let!(:alice) { Fabricate(:account, username: 'alice') }
|
||||
let!(:bob) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
before do
|
||||
post :create, params: { status: '@alice hm, @bob is really annoying lately', allowed_mentions: [alice.id] }
|
||||
end
|
||||
let(:params) { { status: '@alice hm, @bob is really annoying lately', allowed_mentions: [alice.id] } }
|
||||
|
||||
it 'returns serialized extra accounts in body', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
expect(body_as_json[:unexpected_accounts].map { |a| a.slice(:id, :acct) }).to eq [{ id: bob.id.to_s, acct: bob.acct }]
|
||||
end
|
||||
end
|
||||
|
||||
context 'with missing parameters' do
|
||||
before do
|
||||
post :create, params: {}
|
||||
end
|
||||
let(:params) { {} }
|
||||
|
||||
it 'returns rate limit headers', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
|
||||
end
|
||||
|
@ -234,10 +239,11 @@ RSpec.describe Api::V1::StatusesController do
|
|||
before do
|
||||
rate_limiter = RateLimiter.new(user.account, family: :statuses)
|
||||
300.times { rate_limiter.record! }
|
||||
post :create, params: { status: 'Hello world' }
|
||||
end
|
||||
|
||||
it 'returns rate limit headers', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(429)
|
||||
expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s
|
||||
expect(response.headers['X-RateLimit-Remaining']).to eq '0'
|
||||
|
@ -245,29 +251,37 @@ RSpec.describe Api::V1::StatusesController do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
describe 'DELETE /api/v1/statuses/:id' do
|
||||
subject do
|
||||
delete "/api/v1/statuses/#{status.id}", headers: headers
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:statuses' }
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
post :destroy, params: { id: status.id }
|
||||
end
|
||||
it_behaves_like 'forbidden for wrong scope', 'read read:statuses'
|
||||
|
||||
it 'removes the status', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(Status.find_by(id: status.id)).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
describe 'PUT /api/v1/statuses/:id' do
|
||||
subject do
|
||||
put "/api/v1/statuses/#{status.id}", headers: headers, params: { status: 'I am updated' }
|
||||
end
|
||||
|
||||
let(:scopes) { 'write:statuses' }
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
put :update, params: { id: status.id, status: 'I am updated' }
|
||||
end
|
||||
it_behaves_like 'forbidden for wrong scope', 'read read:statuses'
|
||||
|
||||
it 'updates the status', :aggregate_failures do
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(status.reload.text).to eq 'I am updated'
|
||||
end
|
||||
|
@ -275,49 +289,49 @@ RSpec.describe Api::V1::StatusesController do
|
|||
end
|
||||
|
||||
context 'without an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token).and_return(nil)
|
||||
end
|
||||
|
||||
context 'with a private status' do
|
||||
let(:status) { Fabricate(:status, account: user.account, visibility: :private) }
|
||||
let(:status) { Fabricate(:status, visibility: :private) }
|
||||
|
||||
describe 'GET #show' do
|
||||
describe 'GET /api/v1/statuses/:id' do
|
||||
it 'returns http unauthorized' do
|
||||
get :show, params: { id: status.id }
|
||||
get "/api/v1/statuses/#{status.id}"
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #context' do
|
||||
describe 'GET /api/v1/statuses/:id/context' do
|
||||
before do
|
||||
Fabricate(:status, account: user.account, thread: status)
|
||||
Fabricate(:status, thread: status)
|
||||
end
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
get :context, params: { id: status.id }
|
||||
get "/api/v1/statuses/#{status.id}/context"
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a public status' do
|
||||
let(:status) { Fabricate(:status, account: user.account, visibility: :public) }
|
||||
let(:status) { Fabricate(:status, visibility: :public) }
|
||||
|
||||
describe 'GET #show' do
|
||||
describe 'GET /api/v1/statuses/:id' do
|
||||
it 'returns http success' do
|
||||
get :show, params: { id: status.id }
|
||||
get "/api/v1/statuses/#{status.id}"
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #context' do
|
||||
describe 'GET /api/v1/statuses/:id/context' do
|
||||
before do
|
||||
Fabricate(:status, account: user.account, thread: status)
|
||||
Fabricate(:status, thread: status)
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :context, params: { id: status.id }
|
||||
get "/api/v1/statuses/#{status.id}/context"
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
|
@ -60,7 +60,7 @@ RSpec.configure do |config|
|
|||
end
|
||||
end
|
||||
|
||||
config.around :each, type: :search do |example|
|
||||
config.around :each, :search do |example|
|
||||
search_data_manager.populate_indexes
|
||||
example.run
|
||||
search_data_manager.remove_indexes
|
||||
|
@ -73,6 +73,6 @@ RSpec.configure do |config|
|
|||
end
|
||||
|
||||
def search_examples_present?
|
||||
RUN_SEARCH_SPECS
|
||||
RSpec.world.filtered_examples.values.flatten.any? { |example| example.metadata[:search] == true }
|
||||
end
|
||||
end
|
||||
|
|
52
spec/workers/account_refresh_worker_spec.rb
Normal file
52
spec/workers/account_refresh_worker_spec.rb
Normal file
|
@ -0,0 +1,52 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe AccountRefreshWorker do
|
||||
let(:worker) { described_class.new }
|
||||
let(:service) { instance_double(ResolveAccountService, call: true) }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
allow(ResolveAccountService).to receive(:new).and_return(service)
|
||||
end
|
||||
|
||||
context 'when account does not exist' do
|
||||
it 'returns immediately without processing' do
|
||||
worker.perform(123_123_123)
|
||||
|
||||
expect(service).to_not have_received(:call)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when account exists' do
|
||||
context 'when account does not need refreshing' do
|
||||
let(:account) { Fabricate(:account, last_webfingered_at: recent_webfinger_at) }
|
||||
|
||||
it 'returns immediately without processing' do
|
||||
worker.perform(account.id)
|
||||
|
||||
expect(service).to_not have_received(:call)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when account needs refreshing' do
|
||||
let(:account) { Fabricate(:account, last_webfingered_at: outdated_webfinger_at) }
|
||||
|
||||
it 'schedules an account update' do
|
||||
worker.perform(account.id)
|
||||
|
||||
expect(service).to have_received(:call)
|
||||
end
|
||||
end
|
||||
|
||||
def recent_webfinger_at
|
||||
(Account::BACKGROUND_REFRESH_INTERVAL - 3.days).ago
|
||||
end
|
||||
|
||||
def outdated_webfinger_at
|
||||
(Account::BACKGROUND_REFRESH_INTERVAL + 3.days).ago
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
18
spec/workers/activitypub/post_upgrade_worker_spec.rb
Normal file
18
spec/workers/activitypub/post_upgrade_worker_spec.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ActivityPub::PostUpgradeWorker do
|
||||
let(:worker) { described_class.new }
|
||||
|
||||
describe '#perform' do
|
||||
let(:domain) { 'host.example' }
|
||||
|
||||
it 'updates relevant values' do
|
||||
account = Fabricate(:account, domain: domain, last_webfingered_at: 1.day.ago, protocol: :ostatus)
|
||||
worker.perform(domain)
|
||||
|
||||
expect(account.reload.last_webfingered_at).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ActivityPub::SynchronizeFeaturedTagsCollectionWorker do
|
||||
let(:worker) { described_class.new }
|
||||
let(:service) { instance_double(ActivityPub::FetchFeaturedTagsCollectionService, call: true) }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
allow(ActivityPub::FetchFeaturedTagsCollectionService).to receive(:new).and_return(service)
|
||||
end
|
||||
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:url) { 'https://host.example' }
|
||||
|
||||
it 'sends the account and url to the service' do
|
||||
worker.perform(account.id, url)
|
||||
|
||||
expect(service).to have_received(:call).with(account, url)
|
||||
end
|
||||
|
||||
it 'returns true for non-existent record' do
|
||||
result = worker.perform(123_123_123, url)
|
||||
|
||||
expect(result).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
28
spec/workers/admin/suspension_worker_spec.rb
Normal file
28
spec/workers/admin/suspension_worker_spec.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Admin::SuspensionWorker do
|
||||
let(:worker) { described_class.new }
|
||||
let(:service) { instance_double(SuspendAccountService, call: true) }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
allow(SuspendAccountService).to receive(:new).and_return(service)
|
||||
end
|
||||
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
it 'sends the account to the service' do
|
||||
worker.perform(account.id)
|
||||
|
||||
expect(service).to have_received(:call).with(account)
|
||||
end
|
||||
|
||||
it 'returns true for non-existent record' do
|
||||
result = worker.perform(123_123_123)
|
||||
|
||||
expect(result).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
29
spec/workers/after_account_domain_block_worker_spec.rb
Normal file
29
spec/workers/after_account_domain_block_worker_spec.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe AfterAccountDomainBlockWorker do
|
||||
let(:worker) { described_class.new }
|
||||
let(:service) { instance_double(AfterBlockDomainFromAccountService, call: true) }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
allow(AfterBlockDomainFromAccountService).to receive(:new).and_return(service)
|
||||
end
|
||||
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:domain) { 'host.example' }
|
||||
|
||||
it 'sends the account and domain to the service' do
|
||||
worker.perform(account.id, domain)
|
||||
|
||||
expect(service).to have_received(:call).with(account, domain)
|
||||
end
|
||||
|
||||
it 'returns true for non-existent record' do
|
||||
result = worker.perform(123_123_123, domain)
|
||||
|
||||
expect(result).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
36
spec/workers/backup_worker_spec.rb
Normal file
36
spec/workers/backup_worker_spec.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe BackupWorker do
|
||||
let(:worker) { described_class.new }
|
||||
let(:service) { instance_double(BackupService, call: true) }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
allow(BackupService).to receive(:new).and_return(service)
|
||||
end
|
||||
|
||||
let(:backup) { Fabricate(:backup) }
|
||||
let!(:other_backup) { Fabricate(:backup, user: backup.user) }
|
||||
|
||||
it 'sends the backup to the service and removes other backups' do
|
||||
expect do
|
||||
worker.perform(backup.id)
|
||||
end.to change(UserMailer.deliveries, :size).by(1)
|
||||
|
||||
expect(service).to have_received(:call).with(backup)
|
||||
expect { other_backup.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
|
||||
context 'when sidekiq retries are exhausted' do
|
||||
it 'destroys the backup' do
|
||||
described_class.within_sidekiq_retries_exhausted_block({ 'args' => [backup.id] }) do
|
||||
worker.perform(backup.id)
|
||||
end
|
||||
|
||||
expect { backup.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
42
spec/workers/delete_mute_worker_spec.rb
Normal file
42
spec/workers/delete_mute_worker_spec.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe DeleteMuteWorker do
|
||||
let(:worker) { described_class.new }
|
||||
let(:service) { instance_double(UnmuteService, call: true) }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
allow(UnmuteService).to receive(:new).and_return(service)
|
||||
end
|
||||
|
||||
context 'with an expired mute' do
|
||||
let(:mute) { Fabricate(:mute, expires_at: 1.day.ago) }
|
||||
|
||||
it 'sends the mute to the service' do
|
||||
worker.perform(mute.id)
|
||||
|
||||
expect(service).to have_received(:call).with(mute.account, mute.target_account)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an unexpired mute' do
|
||||
let(:mute) { Fabricate(:mute, expires_at: 1.day.from_now) }
|
||||
|
||||
it 'does not send the mute to the service' do
|
||||
worker.perform(mute.id)
|
||||
|
||||
expect(service).to_not have_received(:call)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a non-existent mute' do
|
||||
it 'does not send the mute to the service' do
|
||||
worker.perform(123_123_123)
|
||||
|
||||
expect(service).to_not have_received(:call)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -12,6 +12,7 @@ describe FeedInsertWorker do
|
|||
describe 'perform' do
|
||||
let(:follower) { Fabricate(:account) }
|
||||
let(:status) { Fabricate(:status) }
|
||||
let(:list) { Fabricate(:list) }
|
||||
|
||||
context 'when there are no records' do
|
||||
it 'skips push with missing status' do
|
||||
|
@ -46,11 +47,29 @@ describe FeedInsertWorker do
|
|||
it 'pushes the status onto the home timeline without filter' do
|
||||
instance = instance_double(FeedManager, push_to_home: nil, filter?: false)
|
||||
allow(FeedManager).to receive(:instance).and_return(instance)
|
||||
result = subject.perform(status.id, follower.id)
|
||||
result = subject.perform(status.id, follower.id, :home)
|
||||
|
||||
expect(result).to be_nil
|
||||
expect(instance).to have_received(:push_to_home).with(follower, status, update: nil)
|
||||
end
|
||||
|
||||
it 'pushes the status onto the tags timeline without filter' do
|
||||
instance = instance_double(FeedManager, push_to_home: nil, filter?: false)
|
||||
allow(FeedManager).to receive(:instance).and_return(instance)
|
||||
result = subject.perform(status.id, follower.id, :tags)
|
||||
|
||||
expect(result).to be_nil
|
||||
expect(instance).to have_received(:push_to_home).with(follower, status, update: nil)
|
||||
end
|
||||
|
||||
it 'pushes the status onto the list timeline without filter' do
|
||||
instance = instance_double(FeedManager, push_to_list: nil, filter?: false)
|
||||
allow(FeedManager).to receive(:instance).and_return(instance)
|
||||
result = subject.perform(status.id, list.id, :list)
|
||||
|
||||
expect(result).to be_nil
|
||||
expect(instance).to have_received(:push_to_list).with(list, status, update: nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with notification' do
|
||||
|
|
23
spec/workers/import_worker_spec.rb
Normal file
23
spec/workers/import_worker_spec.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ImportWorker do
|
||||
let(:worker) { described_class.new }
|
||||
let(:service) { instance_double(ImportService, call: true) }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
allow(ImportService).to receive(:new).and_return(service)
|
||||
end
|
||||
|
||||
let(:import) { Fabricate(:import) }
|
||||
|
||||
it 'sends the import to the service' do
|
||||
worker.perform(import.id)
|
||||
|
||||
expect(service).to have_received(:call).with(import)
|
||||
expect { import.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,12 +2,38 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
describe PostProcessMediaWorker do
|
||||
describe PostProcessMediaWorker, :paperclip_processing do
|
||||
let(:worker) { described_class.new }
|
||||
|
||||
describe 'perform' do
|
||||
it 'runs without error for missing record' do
|
||||
expect { worker.perform(nil) }.to_not raise_error
|
||||
describe '#perform' do
|
||||
let(:media_attachment) { Fabricate(:media_attachment) }
|
||||
|
||||
it 'reprocesses and updates the media attachment' do
|
||||
worker.perform(media_attachment.id)
|
||||
|
||||
expect(media_attachment.processing).to eq('complete')
|
||||
end
|
||||
|
||||
it 'returns true for non-existent record' do
|
||||
result = worker.perform(123_123_123)
|
||||
|
||||
expect(result).to be(true)
|
||||
end
|
||||
|
||||
context 'when sidekiq retries are exhausted' do
|
||||
it 'sets state to failed' do
|
||||
described_class.within_sidekiq_retries_exhausted_block({ 'args' => [media_attachment.id] }) do
|
||||
worker.perform(media_attachment.id)
|
||||
end
|
||||
|
||||
expect(media_attachment.reload.processing).to eq('failed')
|
||||
end
|
||||
|
||||
it 'returns true for non-existent record' do
|
||||
described_class.within_sidekiq_retries_exhausted_block({ 'args' => [123_123_123] }) do
|
||||
expect(worker.perform(123_123_123)).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
38
spec/workers/publish_announcement_reaction_worker_spec.rb
Normal file
38
spec/workers/publish_announcement_reaction_worker_spec.rb
Normal file
|
@ -0,0 +1,38 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe PublishAnnouncementReactionWorker do
|
||||
let(:worker) { described_class.new }
|
||||
|
||||
describe '#perform' do
|
||||
before { Fabricate(:account, user: Fabricate(:user, current_sign_in_at: 1.hour.ago)) }
|
||||
|
||||
let(:announcement) { Fabricate(:announcement) }
|
||||
let(:name) { 'name value' }
|
||||
|
||||
it 'sends the announcement and name to the service when subscribed' do
|
||||
allow(redis).to receive(:exists?).and_return(true)
|
||||
allow(redis).to receive(:publish)
|
||||
|
||||
worker.perform(announcement.id, name)
|
||||
|
||||
expect(redis).to have_received(:publish)
|
||||
end
|
||||
|
||||
it 'does not send the announcement and name to the service when not subscribed' do
|
||||
allow(redis).to receive(:exists?).and_return(false)
|
||||
allow(redis).to receive(:publish)
|
||||
|
||||
worker.perform(announcement.id, name)
|
||||
|
||||
expect(redis).to_not have_received(:publish)
|
||||
end
|
||||
|
||||
it 'returns true for non-existent record' do
|
||||
result = worker.perform(123_123_123, name)
|
||||
|
||||
expect(result).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,9 +5,48 @@ require 'rails_helper'
|
|||
describe RedownloadAvatarWorker do
|
||||
let(:worker) { described_class.new }
|
||||
|
||||
describe 'perform' do
|
||||
it 'runs without error for missing record' do
|
||||
expect { worker.perform(nil) }.to_not raise_error
|
||||
describe '#perform' do
|
||||
it 'returns nil for non-existent record' do
|
||||
result = worker.perform(123_123_123)
|
||||
|
||||
expect(result).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil for suspended account' do
|
||||
account = Fabricate(:account, suspended_at: 10.days.ago)
|
||||
|
||||
expect(worker.perform(account.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil with a domain block' do
|
||||
account = Fabricate(:account, domain: 'host.example')
|
||||
Fabricate(:domain_block, domain: account.domain, reject_media: true)
|
||||
|
||||
expect(worker.perform(account.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil without an avatar remote url' do
|
||||
account = Fabricate(:account, avatar_remote_url: '')
|
||||
|
||||
expect(worker.perform(account.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil when avatar file name is present' do
|
||||
stub_request(:get, 'https://example.host/file').to_return request_fixture('avatar.txt')
|
||||
account = Fabricate(:account, avatar_remote_url: 'https://example.host/file', avatar_file_name: 'test.jpg')
|
||||
|
||||
expect(worker.perform(account.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'reprocesses a remote avatar' do
|
||||
stub_request(:get, 'https://example.host/file').to_return request_fixture('avatar.txt')
|
||||
account = Fabricate(:account, avatar_remote_url: 'https://example.host/file')
|
||||
account.update_column(:avatar_file_name, nil) # rubocop:disable Rails/SkipsModelValidations
|
||||
|
||||
result = worker.perform(account.id)
|
||||
|
||||
expect(result).to be(true)
|
||||
expect(account.reload.avatar_file_name).to_not be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,9 +5,48 @@ require 'rails_helper'
|
|||
describe RedownloadHeaderWorker do
|
||||
let(:worker) { described_class.new }
|
||||
|
||||
describe 'perform' do
|
||||
it 'runs without error for missing record' do
|
||||
expect { worker.perform(nil) }.to_not raise_error
|
||||
describe '#perform' do
|
||||
it 'returns nil for non-existent record' do
|
||||
result = worker.perform(123_123_123)
|
||||
|
||||
expect(result).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil for suspended account' do
|
||||
account = Fabricate(:account, suspended_at: 10.days.ago)
|
||||
|
||||
expect(worker.perform(account.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil with a domain block' do
|
||||
account = Fabricate(:account, domain: 'host.example')
|
||||
Fabricate(:domain_block, domain: account.domain, reject_media: true)
|
||||
|
||||
expect(worker.perform(account.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil without an header remote url' do
|
||||
account = Fabricate(:account, header_remote_url: '')
|
||||
|
||||
expect(worker.perform(account.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil when header file name is present' do
|
||||
stub_request(:get, 'https://example.host/file').to_return request_fixture('avatar.txt')
|
||||
account = Fabricate(:account, header_remote_url: 'https://example.host/file', header_file_name: 'test.jpg')
|
||||
|
||||
expect(worker.perform(account.id)).to be_nil
|
||||
end
|
||||
|
||||
it 'reprocesses a remote header' do
|
||||
stub_request(:get, 'https://example.host/file').to_return request_fixture('avatar.txt')
|
||||
account = Fabricate(:account, header_remote_url: 'https://example.host/file')
|
||||
account.update_column(:header_file_name, nil) # rubocop:disable Rails/SkipsModelValidations
|
||||
|
||||
result = worker.perform(account.id)
|
||||
|
||||
expect(result).to be(true)
|
||||
expect(account.reload.header_file_name).to_not be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
37
spec/workers/redownload_media_worker_spec.rb
Normal file
37
spec/workers/redownload_media_worker_spec.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe RedownloadMediaWorker do
|
||||
let(:worker) { described_class.new }
|
||||
|
||||
describe '#perform' do
|
||||
it 'returns nil for non-existent record' do
|
||||
result = worker.perform(123_123_123)
|
||||
|
||||
expect(result).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil without a remote_url' do
|
||||
media_attachment = Fabricate(:media_attachment, remote_url: '')
|
||||
|
||||
result = worker.perform(media_attachment.id)
|
||||
|
||||
expect(result).to be_nil
|
||||
end
|
||||
|
||||
context 'with a valid remote url' do
|
||||
let(:url) { 'https://example.host/file.txt' }
|
||||
|
||||
before { stub_request(:get, url).to_return(status: 200) }
|
||||
|
||||
it 'processes downloads for valid record' do
|
||||
media_attachment = Fabricate(:media_attachment, remote_url: url)
|
||||
|
||||
worker.perform(media_attachment.id)
|
||||
|
||||
expect(a_request(:get, url)).to have_been_made
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
28
spec/workers/removal_worker_spec.rb
Normal file
28
spec/workers/removal_worker_spec.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe RemovalWorker do
|
||||
let(:worker) { described_class.new }
|
||||
let(:service) { instance_double(RemoveStatusService, call: true) }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
allow(RemoveStatusService).to receive(:new).and_return(service)
|
||||
end
|
||||
|
||||
let(:status) { Fabricate(:status) }
|
||||
|
||||
it 'sends the status to the service' do
|
||||
worker.perform(status.id)
|
||||
|
||||
expect(service).to have_received(:call).with(status)
|
||||
end
|
||||
|
||||
it 'returns true for non-existent record' do
|
||||
result = worker.perform(123_123_123)
|
||||
|
||||
expect(result).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
60
spec/workers/scheduler/self_destruct_scheduler_spec.rb
Normal file
60
spec/workers/scheduler/self_destruct_scheduler_spec.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Scheduler::SelfDestructScheduler do
|
||||
let(:worker) { described_class.new }
|
||||
|
||||
describe '#perform' do
|
||||
let!(:account) { Fabricate(:account, domain: nil, suspended_at: nil) }
|
||||
|
||||
context 'when not in self destruct mode' do
|
||||
before do
|
||||
allow(SelfDestructHelper).to receive(:self_destruct?).and_return(false)
|
||||
end
|
||||
|
||||
it 'returns without processing' do
|
||||
worker.perform
|
||||
|
||||
expect(account.reload.suspended_at).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when in self-destruct mode' do
|
||||
before do
|
||||
allow(SelfDestructHelper).to receive(:self_destruct?).and_return(true)
|
||||
end
|
||||
|
||||
context 'when sidekiq is overwhelmed' do
|
||||
before do
|
||||
stats = instance_double(Sidekiq::Stats, enqueued: described_class::MAX_ENQUEUED**2)
|
||||
allow(Sidekiq::Stats).to receive(:new).and_return(stats)
|
||||
end
|
||||
|
||||
it 'returns without processing' do
|
||||
worker.perform
|
||||
|
||||
expect(account.reload.suspended_at).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when sidekiq is operational' do
|
||||
it 'suspends local non-suspended accounts' do
|
||||
worker.perform
|
||||
|
||||
expect(account.reload.suspended_at).to_not be_nil
|
||||
end
|
||||
|
||||
it 'suspends local suspended accounts marked for deletion' do
|
||||
account.update(suspended_at: 10.days.ago)
|
||||
deletion_request = Fabricate(:account_deletion_request, account: account)
|
||||
|
||||
worker.perform
|
||||
|
||||
expect(account.reload.suspended_at).to be > 1.day.ago
|
||||
expect { deletion_request.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,9 +5,21 @@ require 'rails_helper'
|
|||
describe Webhooks::DeliveryWorker do
|
||||
let(:worker) { described_class.new }
|
||||
|
||||
describe 'perform' do
|
||||
it 'runs without error' do
|
||||
expect { worker.perform(nil, nil) }.to_not raise_error
|
||||
describe '#perform' do
|
||||
let(:webhook) { Fabricate(:webhook) }
|
||||
|
||||
it 'reprocesses and updates the webhook' do
|
||||
stub_request(:post, webhook.url).to_return(status: 200, body: '')
|
||||
|
||||
worker.perform(webhook.id, 'body')
|
||||
|
||||
expect(a_request(:post, webhook.url)).to have_been_made.at_least_once
|
||||
end
|
||||
|
||||
it 'returns true for non-existent record' do
|
||||
result = worker.perform(123_123_123, '')
|
||||
|
||||
expect(result).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -2569,9 +2569,9 @@ __metadata:
|
|||
linkType: soft
|
||||
|
||||
"@material-symbols/svg-600@npm:^0.14.0":
|
||||
version: 0.14.0
|
||||
resolution: "@material-symbols/svg-600@npm:0.14.0"
|
||||
checksum: e6547a9a0b2072f4109f2e4e0863367ea2507efce740c427a8544100db02ffff52f33608aac1a355f4977e2c0b2ce6cdd6bfee9177bb13cee0b28418f948b5a5
|
||||
version: 0.14.1
|
||||
resolution: "@material-symbols/svg-600@npm:0.14.1"
|
||||
checksum: fb5252285bbeccc45a4b131e8b165470b5b57e146bc7ea586eb82e580037d1218f6dad5fee4e6822c357041ff547f34c9c7432cce0a811b14f7e41d8ae23009b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -13812,17 +13812,17 @@ __metadata:
|
|||
linkType: hard
|
||||
|
||||
"react-redux-loading-bar@npm:^5.0.4":
|
||||
version: 5.0.4
|
||||
resolution: "react-redux-loading-bar@npm:5.0.4"
|
||||
version: 5.0.5
|
||||
resolution: "react-redux-loading-bar@npm:5.0.5"
|
||||
dependencies:
|
||||
prop-types: "npm:^15.7.2"
|
||||
react-lifecycles-compat: "npm:^3.0.4"
|
||||
peerDependencies:
|
||||
react: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
react-redux: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
redux: ^3.0.0 || ^4.0.0
|
||||
checksum: 11eea2ef6dfae232e278eceb83d07f9f57a2ece3ef23ce888dccf24964b669c9ee83a6db12b1f3c757b5b3410f7a7ccda96a4b4216c4ad9b42bf831ccea7a4a2
|
||||
react-redux: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
|
||||
redux: ^3.0.0 || ^4.0.0 || ^5.0.0
|
||||
checksum: 0dbac046c5b8b6bd209ccfc25ccc55dc9158cd737b42b68fd1900dfe46a59c9c7e2b0082d8901b749e7cf2d7e23074590aae74f350a814f205105f47895a6214
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue