Merge remote-tracking branch 'origin/develop' into language-detection
This commit is contained in:
commit
2b1ef1bbdf
1005 changed files with 13890 additions and 4733 deletions
BIN
test/fixtures/DSCN0010.png
vendored
Normal file
BIN
test/fixtures/DSCN0010.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 744 KiB |
BIN
test/fixtures/break_analyze.png
vendored
Normal file
BIN
test/fixtures/break_analyze.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 360 KiB |
112
test/fixtures/denniskoch.json
vendored
Normal file
112
test/fixtures/denniskoch.json
vendored
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"Curve25519Key": "toot:Curve25519Key",
|
||||
"Device": "toot:Device",
|
||||
"Ed25519Key": "toot:Ed25519Key",
|
||||
"Ed25519Signature": "toot:Ed25519Signature",
|
||||
"EncryptedMessage": "toot:EncryptedMessage",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"alsoKnownAs": {
|
||||
"@id": "as:alsoKnownAs",
|
||||
"@type": "@id"
|
||||
},
|
||||
"cipherText": "toot:cipherText",
|
||||
"claim": {
|
||||
"@id": "toot:claim",
|
||||
"@type": "@id"
|
||||
},
|
||||
"deviceId": "toot:deviceId",
|
||||
"devices": {
|
||||
"@id": "toot:devices",
|
||||
"@type": "@id"
|
||||
},
|
||||
"discoverable": "toot:discoverable",
|
||||
"featured": {
|
||||
"@id": "toot:featured",
|
||||
"@type": "@id"
|
||||
},
|
||||
"featuredTags": {
|
||||
"@id": "toot:featuredTags",
|
||||
"@type": "@id"
|
||||
},
|
||||
"fingerprintKey": {
|
||||
"@id": "toot:fingerprintKey",
|
||||
"@type": "@id"
|
||||
},
|
||||
"focalPoint": {
|
||||
"@container": "@list",
|
||||
"@id": "toot:focalPoint"
|
||||
},
|
||||
"identityKey": {
|
||||
"@id": "toot:identityKey",
|
||||
"@type": "@id"
|
||||
},
|
||||
"indexable": "toot:indexable",
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"memorial": "toot:memorial",
|
||||
"messageFranking": "toot:messageFranking",
|
||||
"messageType": "toot:messageType",
|
||||
"movedTo": {
|
||||
"@id": "as:movedTo",
|
||||
"@type": "@id"
|
||||
},
|
||||
"publicKeyBase64": "toot:publicKeyBase64",
|
||||
"schema": "http://schema.org#",
|
||||
"suspended": "toot:suspended",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"value": "schema:value"
|
||||
}
|
||||
],
|
||||
"attachment": [
|
||||
{
|
||||
"name": "GitHub",
|
||||
"type": "PropertyValue",
|
||||
"value": "<a href=\"https://github.com/pxlrbt/\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"\">github.com/pxlrbt/</span><span class=\"invisible\"></span></a>"
|
||||
},
|
||||
{
|
||||
"name": "Discord",
|
||||
"type": "PropertyValue",
|
||||
"value": "pxlrbt#6029"
|
||||
}
|
||||
],
|
||||
"devices": "https://phpc.social/users/denniskoch/collections/devices",
|
||||
"discoverable": true,
|
||||
"endpoints": {
|
||||
"sharedInbox": "https://phpc.social/inbox"
|
||||
},
|
||||
"featured": "https://phpc.social/users/denniskoch/collections/featured",
|
||||
"featuredTags": "https://phpc.social/users/denniskoch/collections/tags",
|
||||
"followers": "https://phpc.social/users/denniskoch/followers",
|
||||
"following": "https://phpc.social/users/denniskoch/following",
|
||||
"icon": {
|
||||
"mediaType": "image/jpeg",
|
||||
"type": "Image",
|
||||
"url": "https://media.phpc.social/accounts/avatars/109/364/097/179/042/485/original/6e770c7b3f5ef72d.jpg"
|
||||
},
|
||||
"id": "https://phpc.social/users/denniskoch",
|
||||
"image": {
|
||||
"mediaType": "image/jpeg",
|
||||
"type": "Image",
|
||||
"url": "https://media.phpc.social/accounts/headers/109/364/097/179/042/485/original/709da24705260c04.jpg"
|
||||
},
|
||||
"inbox": "https://phpc.social/users/denniskoch/inbox",
|
||||
"indexable": true,
|
||||
"manuallyApprovesFollowers": false,
|
||||
"memorial": false,
|
||||
"name": "Dennis Koch",
|
||||
"outbox": "https://phpc.social/users/denniskoch/outbox",
|
||||
"preferredUsername": "denniskoch",
|
||||
"publicKey": {
|
||||
"id": "https://phpc.social/users/denniskoch#main-key",
|
||||
"owner": "https://phpc.social/users/denniskoch",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4dmcSlqLj18gPvuslkmt\nQTniZ8ybO4pgvMvPLYtBuTBUjo49vJ/8Sw6jB5zcKb1haqIdny7Rv/vY3kCdCXcP\nloh1I+jthEgqLT8JpZWGwLGwg9piFhrMGADmt3N8du7HfglzuZ8LlVpnZ8feCw7I\nS2ua/ZCxE47mI45Z3ed2kkFYKWopWWqFn2lan/1OyHrcFKtCvaVjRdvo0UUt2tgl\nvyJI4+zN8FnrCbsMtcbI5nSzfJIrOc4LeaGmLJh+0o2rwoOQZc2487XWbeyfhjsq\nPRBpYN7pfHWQDvzQIN075LHTf9zDFsm6+HqY7Zs5rYxr72rvcX7d9JcP6CasIosY\nqwIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||
},
|
||||
"published": "2022-11-18T00:00:00Z",
|
||||
"summary": "<p>🧑💻 Full Stack Developer<br />🚀 Laravel, Filament, Livewire, Vue, Inertia<br />🌍 Germany</p>",
|
||||
"tag": [],
|
||||
"type": "Person",
|
||||
"url": "https://phpc.social/@denniskoch"
|
||||
}
|
||||
90
test/fixtures/mastodon-update-with-likes.json
vendored
Normal file
90
test/fixtures/mastodon-update-with-likes.json
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
{
|
||||
"atomUri": "ostatus:atomUri",
|
||||
"conversation": "ostatus:conversation",
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"sensitive": "as:sensitive",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"votersCount": "toot:votersCount"
|
||||
},
|
||||
"https://w3id.org/security/v1"
|
||||
],
|
||||
"actor": "https://pol.social/users/mkljczk",
|
||||
"cc": ["https://www.w3.org/ns/activitystreams#Public",
|
||||
"https://pol.social/users/aemstuz", "https://gts.mkljczk.pl/users/mkljczk",
|
||||
"https://pl.fediverse.pl/users/mkljczk",
|
||||
"https://fedi.kutno.pl/users/mkljczk"],
|
||||
"id": "https://pol.social/users/mkljczk/statuses/113907871635572263#updates/1738096776",
|
||||
"object": {
|
||||
"atomUri": "https://pol.social/users/mkljczk/statuses/113907871635572263",
|
||||
"attachment": [],
|
||||
"attributedTo": "https://pol.social/users/mkljczk",
|
||||
"cc": ["https://www.w3.org/ns/activitystreams#Public",
|
||||
"https://pol.social/users/aemstuz", "https://gts.mkljczk.pl/users/mkljczk",
|
||||
"https://pl.fediverse.pl/users/mkljczk",
|
||||
"https://fedi.kutno.pl/users/mkljczk"],
|
||||
"content": "<p>test</p>",
|
||||
"contentMap": {
|
||||
"pl": "<p>test</p>"
|
||||
},
|
||||
"conversation": "https://fedi.kutno.pl/contexts/43c14c70-d3fb-42b4-a36d-4eacfab9695a",
|
||||
"id": "https://pol.social/users/mkljczk/statuses/113907871635572263",
|
||||
"inReplyTo": "https://pol.social/users/aemstuz/statuses/113907854282654767",
|
||||
"inReplyToAtomUri": "https://pol.social/users/aemstuz/statuses/113907854282654767",
|
||||
"likes": {
|
||||
"id": "https://pol.social/users/mkljczk/statuses/113907871635572263/likes",
|
||||
"totalItems": 1,
|
||||
"type": "Collection"
|
||||
},
|
||||
"published": "2025-01-28T20:29:45Z",
|
||||
"replies": {
|
||||
"first": {
|
||||
"items": [],
|
||||
"next": "https://pol.social/users/mkljczk/statuses/113907871635572263/replies?only_other_accounts=true&page=true",
|
||||
"partOf": "https://pol.social/users/mkljczk/statuses/113907871635572263/replies",
|
||||
"type": "CollectionPage"
|
||||
},
|
||||
"id": "https://pol.social/users/mkljczk/statuses/113907871635572263/replies",
|
||||
"type": "Collection"
|
||||
},
|
||||
"sensitive": false,
|
||||
"shares": {
|
||||
"id": "https://pol.social/users/mkljczk/statuses/113907871635572263/shares",
|
||||
"totalItems": 0,
|
||||
"type": "Collection"
|
||||
},
|
||||
"summary": null,
|
||||
"tag": [
|
||||
{
|
||||
"href": "https://pol.social/users/aemstuz",
|
||||
"name": "@aemstuz",
|
||||
"type": "Mention"
|
||||
},
|
||||
{
|
||||
"href": "https://gts.mkljczk.pl/users/mkljczk",
|
||||
"name": "@mkljczk@gts.mkljczk.pl",
|
||||
"type": "Mention"
|
||||
},
|
||||
{
|
||||
"href": "https://pl.fediverse.pl/users/mkljczk",
|
||||
"name": "@mkljczk@fediverse.pl",
|
||||
"type": "Mention"
|
||||
},
|
||||
{
|
||||
"href": "https://fedi.kutno.pl/users/mkljczk",
|
||||
"name": "@mkljczk@fedi.kutno.pl",
|
||||
"type": "Mention"
|
||||
}
|
||||
],
|
||||
"to": ["https://pol.social/users/mkljczk/followers"],
|
||||
"type": "Note",
|
||||
"updated": "2025-01-28T20:39:36Z",
|
||||
"url": "https://pol.social/@mkljczk/113907871635572263"
|
||||
},
|
||||
"published": "2025-01-28T20:39:36Z",
|
||||
"to": ["https://pol.social/users/mkljczk/followers"],
|
||||
"type": "Update"
|
||||
}
|
||||
109
test/fixtures/receiver_worker_signature_activity.json
vendored
Normal file
109
test/fixtures/receiver_worker_signature_activity.json
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"claim": {
|
||||
"@id": "toot:claim",
|
||||
"@type": "@id"
|
||||
},
|
||||
"memorial": "toot:memorial",
|
||||
"atomUri": "ostatus:atomUri",
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"blurhash": "toot:blurhash",
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"discoverable": "toot:discoverable",
|
||||
"focalPoint": {
|
||||
"@container": "@list",
|
||||
"@id": "toot:focalPoint"
|
||||
},
|
||||
"votersCount": "toot:votersCount",
|
||||
"Hashtag": "as:Hashtag",
|
||||
"Emoji": "toot:Emoji",
|
||||
"alsoKnownAs": {
|
||||
"@id": "as:alsoKnownAs",
|
||||
"@type": "@id"
|
||||
},
|
||||
"sensitive": "as:sensitive",
|
||||
"movedTo": {
|
||||
"@id": "as:movedTo",
|
||||
"@type": "@id"
|
||||
},
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"conversation": "ostatus:conversation",
|
||||
"Device": "toot:Device",
|
||||
"schema": "http://schema.org#",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"cipherText": "toot:cipherText",
|
||||
"suspended": "toot:suspended",
|
||||
"messageType": "toot:messageType",
|
||||
"featuredTags": {
|
||||
"@id": "toot:featuredTags",
|
||||
"@type": "@id"
|
||||
},
|
||||
"Curve25519Key": "toot:Curve25519Key",
|
||||
"deviceId": "toot:deviceId",
|
||||
"Ed25519Signature": "toot:Ed25519Signature",
|
||||
"featured": {
|
||||
"@id": "toot:featured",
|
||||
"@type": "@id"
|
||||
},
|
||||
"devices": {
|
||||
"@id": "toot:devices",
|
||||
"@type": "@id"
|
||||
},
|
||||
"value": "schema:value",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"messageFranking": "toot:messageFranking",
|
||||
"publicKeyBase64": "toot:publicKeyBase64",
|
||||
"identityKey": {
|
||||
"@id": "toot:identityKey",
|
||||
"@type": "@id"
|
||||
},
|
||||
"Ed25519Key": "toot:Ed25519Key",
|
||||
"indexable": "toot:indexable",
|
||||
"EncryptedMessage": "toot:EncryptedMessage",
|
||||
"fingerprintKey": {
|
||||
"@id": "toot:fingerprintKey",
|
||||
"@type": "@id"
|
||||
}
|
||||
}
|
||||
],
|
||||
"actor": "https://phpc.social/users/denniskoch",
|
||||
"cc": [],
|
||||
"id": "https://phpc.social/users/denniskoch/statuses/112847382711461301/activity",
|
||||
"inReplyTo": null,
|
||||
"inReplyToAtomUri": null,
|
||||
"object": {
|
||||
"atomUri": "https://phpc.social/users/denniskoch/statuses/112847382711461301",
|
||||
"attachment": [],
|
||||
"attributedTo": "https://phpc.social/users/denniskoch",
|
||||
"cc": [],
|
||||
"content": "<p><span class=\"h-card\" translate=\"no\"><a href=\"https://mastodon.social/@bastianallgeier\" class=\"u-url mention\">@<span>bastianallgeier</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://chaos.social/@distantnative\" class=\"u-url mention\">@<span>distantnative</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://fosstodon.org/@kev\" class=\"u-url mention\">@<span>kev</span></a></span> Another main argument: Discord is popular. Many people have an account, so you can just join an server quickly. Also you know the app and how to get around.</p>",
|
||||
"contentMap": {
|
||||
"en": "<p><span class=\"h-card\" translate=\"no\"><a href=\"https://mastodon.social/@bastianallgeier\" class=\"u-url mention\">@<span>bastianallgeier</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://chaos.social/@distantnative\" class=\"u-url mention\">@<span>distantnative</span></a></span> <span class=\"h-card\" translate=\"no\"><a href=\"https://fosstodon.org/@kev\" class=\"u-url mention\">@<span>kev</span></a></span> Another main argument: Discord is popular. Many people have an account, so you can just join an server quickly. Also you know the app and how to get around.</p>"
|
||||
},
|
||||
"conversation": "tag:mastodon.social,2024-07-25:objectId=760068442:objectType=Conversation",
|
||||
"id": "https://phpc.social/users/denniskoch/statuses/112847382711461301",
|
||||
"published": "2024-07-25T13:33:29Z",
|
||||
"replies": null,
|
||||
"sensitive": false,
|
||||
"tag": [],
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"type": "Note",
|
||||
"url": "https://phpc.social/@denniskoch/112847382711461301"
|
||||
},
|
||||
"published": "2024-07-25T13:33:29Z",
|
||||
"signature": {
|
||||
"created": "2024-07-25T13:33:29Z",
|
||||
"creator": "https://phpc.social/users/denniskoch#main-key",
|
||||
"signatureValue": "slz9BKJzd2n1S44wdXGOU+bV/wsskdgAaUpwxj8R16mYOL8+DTpE6VnfSKoZGsBBJT8uG5gnVfVEz1YsTUYtymeUgLMh7cvd8VnJnZPS+oixbmBRVky/Myf91TEgQQE7G4vDmTdB4ii54hZrHcOOYYf5FKPNRSkMXboKA6LMqNtekhbI+JTUJYIB02WBBK6PUyo15f6B1RJ6HGWVgud9NE0y1EZXfrkqUt682p8/9D49ORf7AwjXUJibKic2RbPvhEBj70qUGfBm4vvgdWhSUn1IG46xh+U0+NrTSUED82j1ZVOeua/2k/igkGs8cSBkY35quXTkPz6gbqCCH66CuA==",
|
||||
"type": "RsaSignature2017"
|
||||
},
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"type": "Create"
|
||||
}
|
||||
4
test/fixtures/tesla_mock/gleasonator.com_host_meta
vendored
Normal file
4
test/fixtures/tesla_mock/gleasonator.com_host_meta
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Link rel="lrdd" template="https://gleasonator.com/.well-known/webfinger?resource={uri}" type="application/xrd+xml" />
|
||||
</XRD>
|
||||
28
test/fixtures/tesla_mock/webfinger_spoof.json
vendored
Normal file
28
test/fixtures/tesla_mock/webfinger_spoof.json
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"aliases": [
|
||||
"https://gleasonator.com/users/alex",
|
||||
"https://mitra.social/users/alex"
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"href": "https://gleasonator.com/users/alex",
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"type": "text/html"
|
||||
},
|
||||
{
|
||||
"href": "https://gleasonator.com/users/alex",
|
||||
"rel": "self",
|
||||
"type": "application/activity+json"
|
||||
},
|
||||
{
|
||||
"href": "https://gleasonator.com/users/alex",
|
||||
"rel": "self",
|
||||
"type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
|
||||
},
|
||||
{
|
||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template": "https://gleasonator.com/ostatus_subscribe?acct={uri}"
|
||||
}
|
||||
],
|
||||
"subject": "acct:trump@whitehouse.gov"
|
||||
}
|
||||
27
test/fixtures/unindexed_fk.sql
vendored
Normal file
27
test/fixtures/unindexed_fk.sql
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-- Unindexed FK -- Missing indexes - For CI
|
||||
|
||||
WITH y AS (
|
||||
SELECT
|
||||
pg_catalog.format('%I', c1.relname) AS referencing_tbl,
|
||||
pg_catalog.quote_ident(a1.attname) AS referencing_column,
|
||||
(SELECT pg_get_expr(indpred, indrelid) FROM pg_catalog.pg_index WHERE indrelid = t.conrelid AND indkey[0] = t.conkey[1] AND indpred IS NOT NULL LIMIT 1) partial_statement
|
||||
FROM pg_catalog.pg_constraint t
|
||||
JOIN pg_catalog.pg_attribute a1 ON a1.attrelid = t.conrelid AND a1.attnum = t.conkey[1]
|
||||
JOIN pg_catalog.pg_class c1 ON c1.oid = t.conrelid
|
||||
JOIN pg_catalog.pg_namespace n1 ON n1.oid = c1.relnamespace
|
||||
JOIN pg_catalog.pg_class c2 ON c2.oid = t.confrelid
|
||||
JOIN pg_catalog.pg_namespace n2 ON n2.oid = c2.relnamespace
|
||||
JOIN pg_catalog.pg_attribute a2 ON a2.attrelid = t.confrelid AND a2.attnum = t.confkey[1]
|
||||
WHERE t.contype = 'f'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_catalog.pg_index i
|
||||
WHERE i.indrelid = t.conrelid
|
||||
AND i.indkey[0] = t.conkey[1]
|
||||
AND indpred IS NULL
|
||||
)
|
||||
)
|
||||
SELECT referencing_tbl || '.' || referencing_column as "column"
|
||||
FROM y
|
||||
WHERE (partial_statement IS NULL OR partial_statement <> ('(' || referencing_column || ' IS NOT NULL)'))
|
||||
ORDER BY 1;
|
||||
41
test/fixtures/webfinger/graf-imposter-webfinger.json
vendored
Normal file
41
test/fixtures/webfinger/graf-imposter-webfinger.json
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"subject": "acct:graf@poa.st",
|
||||
"aliases": [
|
||||
"https://fba.ryona.agenc/webfingertest"
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"type": "text/html",
|
||||
"href": "https://fba.ryona.agenc/webfingertest"
|
||||
},
|
||||
{
|
||||
"rel": "self",
|
||||
"type": "application/activity+json",
|
||||
"href": "https://fba.ryona.agenc/webfingertest"
|
||||
},
|
||||
{
|
||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template": "https://fba.ryona.agenc/contact/follow?url={uri}"
|
||||
},
|
||||
{
|
||||
"rel": "http://schemas.google.com/g/2010#updates-from",
|
||||
"type": "application/atom+xml",
|
||||
"href": ""
|
||||
},
|
||||
{
|
||||
"rel": "salmon",
|
||||
"href": "https://fba.ryona.agenc/salmon/friendica"
|
||||
},
|
||||
{
|
||||
"rel": "http://microformats.org/profile/hcard",
|
||||
"type": "text/html",
|
||||
"href": "https://fba.ryona.agenc/hcard/friendica"
|
||||
},
|
||||
{
|
||||
"rel": "http://joindiaspora.com/seed_location",
|
||||
"type": "text/html",
|
||||
"href": "https://fba.ryona.agenc"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -51,7 +51,6 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do
|
|||
clear_config(:configurable_from_database, true)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "config migration refused when deprecated settings are found" do
|
||||
clear_config([:media_proxy, :whitelist], ["domain_without_scheme.com"])
|
||||
assert config_records() == []
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
|
|||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
|
@ -45,28 +46,509 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
|
|||
end
|
||||
|
||||
describe "prune_objects" do
|
||||
test "it prunes old objects from the database" do
|
||||
insert(:note)
|
||||
setup do
|
||||
deadline = Pleroma.Config.get([:instance, :remote_post_retention_days]) + 1
|
||||
|
||||
date =
|
||||
old_insert_date =
|
||||
Timex.now()
|
||||
|> Timex.shift(days: -deadline)
|
||||
|> Timex.to_naive_datetime()
|
||||
|> NaiveDateTime.truncate(:second)
|
||||
|
||||
%{id: id} =
|
||||
%{old_insert_date: old_insert_date}
|
||||
end
|
||||
|
||||
test "it prunes old objects from the database", %{old_insert_date: old_insert_date} do
|
||||
insert(:note)
|
||||
|
||||
%{id: note_remote_public_id} =
|
||||
:note
|
||||
|> insert()
|
||||
|> Ecto.Changeset.change(%{inserted_at: date})
|
||||
|> Ecto.Changeset.change(%{updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
assert length(Repo.all(Object)) == 2
|
||||
note_remote_non_public =
|
||||
%{id: note_remote_non_public_id, data: note_remote_non_public_data} =
|
||||
:note
|
||||
|> insert()
|
||||
|
||||
note_remote_non_public
|
||||
|> Ecto.Changeset.change(%{
|
||||
updated_at: old_insert_date,
|
||||
data: note_remote_non_public_data |> update_in(["to"], fn _ -> [] end)
|
||||
})
|
||||
|> Repo.update!()
|
||||
|
||||
assert length(Repo.all(Object)) == 3
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects"])
|
||||
|
||||
assert length(Repo.all(Object)) == 1
|
||||
refute Object.get_by_id(id)
|
||||
refute Object.get_by_id(note_remote_public_id)
|
||||
refute Object.get_by_id(note_remote_non_public_id)
|
||||
end
|
||||
|
||||
test "it cleans up bookmarks", %{old_insert_date: old_insert_date} do
|
||||
user = insert(:user)
|
||||
{:ok, old_object_activity} = CommonAPI.post(user, %{status: "yadayada"})
|
||||
|
||||
Repo.one(Object)
|
||||
|> Ecto.Changeset.change(%{updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
{:ok, new_object_activity} = CommonAPI.post(user, %{status: "yadayada"})
|
||||
|
||||
{:ok, _} = Bookmark.create(user.id, old_object_activity.id)
|
||||
{:ok, _} = Bookmark.create(user.id, new_object_activity.id)
|
||||
|
||||
assert length(Repo.all(Object)) == 2
|
||||
assert length(Repo.all(Bookmark)) == 2
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects"])
|
||||
|
||||
assert length(Repo.all(Object)) == 1
|
||||
assert length(Repo.all(Bookmark)) == 1
|
||||
refute Bookmark.get(user.id, old_object_activity.id)
|
||||
end
|
||||
|
||||
test "with the --keep-non-public option it still keeps non-public posts even if they are not local",
|
||||
%{old_insert_date: old_insert_date} do
|
||||
insert(:note)
|
||||
|
||||
%{id: note_remote_id} =
|
||||
:note
|
||||
|> insert()
|
||||
|> Ecto.Changeset.change(%{updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
note_remote_non_public =
|
||||
%{data: note_remote_non_public_data} =
|
||||
:note
|
||||
|> insert()
|
||||
|
||||
note_remote_non_public
|
||||
|> Ecto.Changeset.change(%{
|
||||
updated_at: old_insert_date,
|
||||
data: note_remote_non_public_data |> update_in(["to"], fn _ -> [] end)
|
||||
})
|
||||
|> Repo.update!()
|
||||
|
||||
assert length(Repo.all(Object)) == 3
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects", "--keep-non-public"])
|
||||
|
||||
assert length(Repo.all(Object)) == 2
|
||||
refute Object.get_by_id(note_remote_id)
|
||||
end
|
||||
|
||||
test "with the --keep-threads and --keep-non-public option it keeps old threads with non-public replies even if the interaction is not local",
|
||||
%{old_insert_date: old_insert_date} do
|
||||
# For non-public we only check Create Activities because only these are relevant for threads
|
||||
# Flags are always non-public, Announces from relays can be non-public...
|
||||
|
||||
remote_user1 = insert(:user, local: false)
|
||||
remote_user2 = insert(:user, local: false)
|
||||
|
||||
# Old remote non-public reply (should be kept)
|
||||
{:ok, old_remote_post1_activity} =
|
||||
CommonAPI.post(remote_user1, %{status: "some thing", local: false})
|
||||
|
||||
old_remote_post1_activity
|
||||
|> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
{:ok, old_remote_non_public_reply_activity} =
|
||||
CommonAPI.post(remote_user2, %{
|
||||
status: "some reply",
|
||||
in_reply_to_status_id: old_remote_post1_activity.id
|
||||
})
|
||||
|
||||
old_remote_non_public_reply_activity
|
||||
|> Ecto.Changeset.change(%{
|
||||
local: false,
|
||||
updated_at: old_insert_date,
|
||||
data: old_remote_non_public_reply_activity.data |> update_in(["to"], fn _ -> [] end)
|
||||
})
|
||||
|> Repo.update!()
|
||||
|
||||
# Old remote non-public Announce (should be removed)
|
||||
{:ok, old_remote_post2_activity = %{data: %{"object" => old_remote_post2_id}}} =
|
||||
CommonAPI.post(remote_user1, %{status: "some thing", local: false})
|
||||
|
||||
old_remote_post2_activity
|
||||
|> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
{:ok, old_remote_non_public_repeat_activity} =
|
||||
CommonAPI.repeat(old_remote_post2_activity.id, remote_user2)
|
||||
|
||||
old_remote_non_public_repeat_activity
|
||||
|> Ecto.Changeset.change(%{
|
||||
local: false,
|
||||
updated_at: old_insert_date,
|
||||
data: old_remote_non_public_repeat_activity.data |> update_in(["to"], fn _ -> [] end)
|
||||
})
|
||||
|> Repo.update!()
|
||||
|
||||
assert length(Repo.all(Object)) == 3
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects", "--keep-threads", "--keep-non-public"])
|
||||
|
||||
Repo.all(Pleroma.Activity)
|
||||
assert length(Repo.all(Object)) == 2
|
||||
refute Object.get_by_ap_id(old_remote_post2_id)
|
||||
end
|
||||
|
||||
test "with the --keep-threads option it still keeps non-old threads even with no local interactions" do
|
||||
remote_user = insert(:user, local: false)
|
||||
remote_user2 = insert(:user, local: false)
|
||||
|
||||
{:ok, remote_post_activity} =
|
||||
CommonAPI.post(remote_user, %{status: "some thing", local: false})
|
||||
|
||||
{:ok, remote_post_reply_activity} =
|
||||
CommonAPI.post(remote_user2, %{
|
||||
status: "some reply",
|
||||
in_reply_to_status_id: remote_post_activity.id
|
||||
})
|
||||
|
||||
remote_post_activity
|
||||
|> Ecto.Changeset.change(%{local: false})
|
||||
|> Repo.update!()
|
||||
|
||||
remote_post_reply_activity
|
||||
|> Ecto.Changeset.change(%{local: false})
|
||||
|> Repo.update!()
|
||||
|
||||
assert length(Repo.all(Object)) == 2
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects", "--keep-threads"])
|
||||
|
||||
assert length(Repo.all(Object)) == 2
|
||||
end
|
||||
|
||||
test "with the --keep-threads option it deletes old threads with no local interaction", %{
|
||||
old_insert_date: old_insert_date
|
||||
} do
|
||||
remote_user = insert(:user, local: false)
|
||||
remote_user2 = insert(:user, local: false)
|
||||
|
||||
{:ok, old_remote_post_activity} =
|
||||
CommonAPI.post(remote_user, %{status: "some thing", local: false})
|
||||
|
||||
old_remote_post_activity
|
||||
|> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
{:ok, old_remote_post_reply_activity} =
|
||||
CommonAPI.post(remote_user2, %{
|
||||
status: "some reply",
|
||||
in_reply_to_status_id: old_remote_post_activity.id
|
||||
})
|
||||
|
||||
old_remote_post_reply_activity
|
||||
|> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
{:ok, old_favourite_activity} =
|
||||
CommonAPI.favorite(old_remote_post_activity.id, remote_user2)
|
||||
|
||||
old_favourite_activity
|
||||
|> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
{:ok, old_repeat_activity} = CommonAPI.repeat(old_remote_post_activity.id, remote_user2)
|
||||
|
||||
old_repeat_activity
|
||||
|> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
assert length(Repo.all(Object)) == 2
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects", "--keep-threads"])
|
||||
|
||||
assert length(Repo.all(Object)) == 0
|
||||
end
|
||||
|
||||
test "with the --keep-threads option it keeps old threads with local interaction", %{
|
||||
old_insert_date: old_insert_date
|
||||
} do
|
||||
remote_user = insert(:user, local: false)
|
||||
local_user = insert(:user, local: true)
|
||||
|
||||
# local reply
|
||||
{:ok, old_remote_post1_activity} =
|
||||
CommonAPI.post(remote_user, %{status: "some thing", local: false})
|
||||
|
||||
old_remote_post1_activity
|
||||
|> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
{:ok, old_local_post2_reply_activity} =
|
||||
CommonAPI.post(local_user, %{
|
||||
status: "some reply",
|
||||
in_reply_to_status_id: old_remote_post1_activity.id
|
||||
})
|
||||
|
||||
old_local_post2_reply_activity
|
||||
|> Ecto.Changeset.change(%{local: true, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
# local Like
|
||||
{:ok, old_remote_post3_activity} =
|
||||
CommonAPI.post(remote_user, %{status: "some thing", local: false})
|
||||
|
||||
old_remote_post3_activity
|
||||
|> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
{:ok, old_favourite_activity} = CommonAPI.favorite(old_remote_post3_activity.id, local_user)
|
||||
|
||||
old_favourite_activity
|
||||
|> Ecto.Changeset.change(%{local: true, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
# local Announce
|
||||
{:ok, old_remote_post4_activity} =
|
||||
CommonAPI.post(remote_user, %{status: "some thing", local: false})
|
||||
|
||||
old_remote_post4_activity
|
||||
|> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
{:ok, old_repeat_activity} = CommonAPI.repeat(old_remote_post4_activity.id, local_user)
|
||||
|
||||
old_repeat_activity
|
||||
|> Ecto.Changeset.change(%{local: true, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
assert length(Repo.all(Object)) == 4
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects", "--keep-threads"])
|
||||
|
||||
assert length(Repo.all(Object)) == 4
|
||||
end
|
||||
|
||||
test "with the --keep-threads option it keeps old threads with bookmarked posts", %{
|
||||
old_insert_date: old_insert_date
|
||||
} do
|
||||
remote_user = insert(:user, local: false)
|
||||
local_user = insert(:user, local: true)
|
||||
|
||||
{:ok, old_remote_post_activity} =
|
||||
CommonAPI.post(remote_user, %{status: "some thing", local: false})
|
||||
|
||||
old_remote_post_activity
|
||||
|> Ecto.Changeset.change(%{local: false, updated_at: old_insert_date})
|
||||
|> Repo.update!()
|
||||
|
||||
Pleroma.Bookmark.create(local_user.id, old_remote_post_activity.id)
|
||||
|
||||
assert length(Repo.all(Object)) == 1
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects", "--keep-threads"])
|
||||
|
||||
assert length(Repo.all(Object)) == 1
|
||||
end
|
||||
|
||||
test "We don't have unexpected tables which may contain objects that are referenced by activities" do
|
||||
# We can delete orphaned activities. For that we look for the objects
|
||||
# they reference in the 'objects', 'activities', and 'users' table.
|
||||
# If someone adds another table with objects (idk, maybe with separate
|
||||
# relations, or collections or w/e), then we need to make sure we
|
||||
# add logic for that in the 'prune_objects' task so that we don't
|
||||
# wrongly delete their corresponding activities.
|
||||
# So when someone adds (or removes) a table, this test will fail.
|
||||
# Either the table contains objects which can be referenced from the
|
||||
# activities table
|
||||
# => in that case the prune_objects job should be adapted so we don't
|
||||
# delete activities who still have the referenced object.
|
||||
# Or it doesn't contain objects which can be referenced from the activities table
|
||||
# => in that case you can add/remove the table to/from this (sorted) list.
|
||||
|
||||
assert Repo.query!(
|
||||
"SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE';"
|
||||
).rows
|
||||
|> Enum.sort() == [
|
||||
["activities"],
|
||||
["announcement_read_relationships"],
|
||||
["announcements"],
|
||||
["apps"],
|
||||
["backups"],
|
||||
["bookmark_folders"],
|
||||
["bookmarks"],
|
||||
["chat_message_references"],
|
||||
["chats"],
|
||||
["config"],
|
||||
["conversation_participation_recipient_ships"],
|
||||
["conversation_participations"],
|
||||
["conversations"],
|
||||
["counter_cache"],
|
||||
["data_migration_failed_ids"],
|
||||
["data_migrations"],
|
||||
["deliveries"],
|
||||
["filters"],
|
||||
["following_relationships"],
|
||||
["hashtags"],
|
||||
["hashtags_objects"],
|
||||
["instances"],
|
||||
["lists"],
|
||||
["markers"],
|
||||
["mfa_tokens"],
|
||||
["moderation_log"],
|
||||
["notifications"],
|
||||
["oauth_authorizations"],
|
||||
["oauth_tokens"],
|
||||
["oban_jobs"],
|
||||
["oban_peers"],
|
||||
["objects"],
|
||||
["password_reset_tokens"],
|
||||
["push_subscriptions"],
|
||||
["registrations"],
|
||||
["report_notes"],
|
||||
["rich_media_card"],
|
||||
["rules"],
|
||||
["scheduled_activities"],
|
||||
["schema_migrations"],
|
||||
["thread_mutes"],
|
||||
["user_follows_hashtag"],
|
||||
# ["user_frontend_setting_profiles"], # not in pleroma
|
||||
["user_invite_tokens"],
|
||||
["user_notes"],
|
||||
["user_relationships"],
|
||||
["users"]
|
||||
]
|
||||
end
|
||||
|
||||
test "it prunes orphaned activities with the --prune-orphaned-activities" do
|
||||
# Add a remote activity which references an Object
|
||||
%Object{} |> Map.merge(%{data: %{"id" => "object_for_activity"}}) |> Repo.insert()
|
||||
|
||||
%Activity{}
|
||||
|> Map.merge(%{
|
||||
local: false,
|
||||
data: %{"id" => "remote_activity_with_object", "object" => "object_for_activity"}
|
||||
})
|
||||
|> Repo.insert()
|
||||
|
||||
# Add a remote activity which references an activity
|
||||
%Activity{}
|
||||
|> Map.merge(%{
|
||||
local: false,
|
||||
data: %{
|
||||
"id" => "remote_activity_with_activity",
|
||||
"object" => "remote_activity_with_object"
|
||||
}
|
||||
})
|
||||
|> Repo.insert()
|
||||
|
||||
# Add a remote activity which references an Actor
|
||||
%User{} |> Map.merge(%{ap_id: "actor"}) |> Repo.insert()
|
||||
|
||||
%Activity{}
|
||||
|> Map.merge(%{
|
||||
local: false,
|
||||
data: %{"id" => "remote_activity_with_actor", "object" => "actor"}
|
||||
})
|
||||
|> Repo.insert()
|
||||
|
||||
# Add a remote activity without existing referenced object, activity or actor
|
||||
%Activity{}
|
||||
|> Map.merge(%{
|
||||
local: false,
|
||||
data: %{
|
||||
"id" => "remote_activity_without_existing_referenced_object",
|
||||
"object" => "non_existing"
|
||||
}
|
||||
})
|
||||
|> Repo.insert()
|
||||
|
||||
# Add a local activity without existing referenced object, activity or actor
|
||||
%Activity{}
|
||||
|> Map.merge(%{
|
||||
local: true,
|
||||
data: %{"id" => "local_activity_with_actor", "object" => "non_existing"}
|
||||
})
|
||||
|> Repo.insert()
|
||||
|
||||
# The remote activities without existing reference,
|
||||
# and only the remote activities without existing reference, are deleted
|
||||
# if, and only if, we provide the --prune-orphaned-activities option
|
||||
assert length(Repo.all(Activity)) == 5
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects"])
|
||||
assert length(Repo.all(Activity)) == 5
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects", "--prune-orphaned-activities"])
|
||||
activities = Repo.all(Activity)
|
||||
|
||||
assert "remote_activity_without_existing_referenced_object" not in Enum.map(
|
||||
activities,
|
||||
fn a -> a.data["id"] end
|
||||
)
|
||||
|
||||
assert length(activities) == 4
|
||||
end
|
||||
|
||||
test "it prunes orphaned activities with the --prune-orphaned-activities when the objects are referenced from an array" do
|
||||
%Object{} |> Map.merge(%{data: %{"id" => "existing_object"}}) |> Repo.insert()
|
||||
%User{} |> Map.merge(%{ap_id: "existing_actor"}) |> Repo.insert()
|
||||
|
||||
# Multiple objects, one object exists (keep)
|
||||
%Activity{}
|
||||
|> Map.merge(%{
|
||||
local: false,
|
||||
data: %{
|
||||
"id" => "remote_activity_existing_object",
|
||||
"object" => ["non_ existing_object", "existing_object"]
|
||||
}
|
||||
})
|
||||
|> Repo.insert()
|
||||
|
||||
# Multiple objects, one actor exists (keep)
|
||||
%Activity{}
|
||||
|> Map.merge(%{
|
||||
local: false,
|
||||
data: %{
|
||||
"id" => "remote_activity_existing_actor",
|
||||
"object" => ["non_ existing_object", "existing_actor"]
|
||||
}
|
||||
})
|
||||
|> Repo.insert()
|
||||
|
||||
# Multiple objects, one activity exists (keep)
|
||||
%Activity{}
|
||||
|> Map.merge(%{
|
||||
local: false,
|
||||
data: %{
|
||||
"id" => "remote_activity_existing_activity",
|
||||
"object" => ["non_ existing_object", "remote_activity_existing_actor"]
|
||||
}
|
||||
})
|
||||
|> Repo.insert()
|
||||
|
||||
# Multiple objects none exist (prune)
|
||||
%Activity{}
|
||||
|> Map.merge(%{
|
||||
local: false,
|
||||
data: %{
|
||||
"id" => "remote_activity_without_existing_referenced_object",
|
||||
"object" => ["owo", "whats_this"]
|
||||
}
|
||||
})
|
||||
|> Repo.insert()
|
||||
|
||||
assert length(Repo.all(Activity)) == 4
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects"])
|
||||
assert length(Repo.all(Activity)) == 4
|
||||
Mix.Tasks.Pleroma.Database.run(["prune_objects", "--prune-orphaned-activities"])
|
||||
activities = Repo.all(Activity)
|
||||
assert length(activities) == 3
|
||||
|
||||
assert "remote_activity_without_existing_referenced_object" not in Enum.map(
|
||||
activities,
|
||||
fn a -> a.data["id"] end
|
||||
)
|
||||
|
||||
assert length(activities) == 3
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -104,7 +586,7 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
|
|||
{:ok, %{id: id, object: object}} = CommonAPI.post(user, %{status: "test"})
|
||||
{:ok, %{object: object2}} = CommonAPI.post(user, %{status: "test test"})
|
||||
|
||||
CommonAPI.favorite(user2, id)
|
||||
CommonAPI.favorite(id, user2)
|
||||
|
||||
likes = %{
|
||||
"first" =>
|
||||
|
|
@ -141,10 +623,12 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
|
|||
|
||||
expires_at = DateTime.add(DateTime.utc_now(), 60 * 61)
|
||||
|
||||
Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
|
||||
activity_id: activity_id3,
|
||||
expires_at: expires_at
|
||||
})
|
||||
Pleroma.Workers.PurgeExpiredActivity.enqueue(
|
||||
%{
|
||||
activity_id: activity_id3
|
||||
},
|
||||
scheduled_at: expires_at
|
||||
)
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["ensure_expiration"])
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mix.Tasks.Pleroma.UploadsTest do
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Upload
|
||||
use Pleroma.DataCase
|
||||
use Pleroma.DataCase, async: false
|
||||
|
||||
import Mock
|
||||
|
||||
setup_all do
|
||||
prep_uploads()
|
||||
Mix.shell(Mix.Shell.Process)
|
||||
|
||||
on_exit(fn ->
|
||||
|
|
@ -18,6 +20,8 @@ defmodule Mix.Tasks.Pleroma.UploadsTest do
|
|||
:ok
|
||||
end
|
||||
|
||||
setup do: clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
|
||||
describe "running migrate_local" do
|
||||
test "uploads migrated" do
|
||||
with_mock Upload,
|
||||
|
|
@ -53,4 +57,15 @@ defmodule Mix.Tasks.Pleroma.UploadsTest do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp prep_uploads do
|
||||
upload_dir = Config.get([Pleroma.Uploaders.Local, :uploads])
|
||||
|
||||
if not File.exists?(upload_dir) || File.ls!(upload_dir) == [] do
|
||||
File.mkdir_p(upload_dir)
|
||||
|
||||
Path.join([upload_dir, "file.txt"])
|
||||
|> File.touch()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ defmodule Pleroma.ActivityTest do
|
|||
{:ok, %{id: id, object: %{data: %{"id" => obj_id}}}} =
|
||||
Pleroma.Web.CommonAPI.post(user, %{status: "cofe"})
|
||||
|
||||
Pleroma.Web.CommonAPI.favorite(another, id)
|
||||
Pleroma.Web.CommonAPI.favorite(id, another)
|
||||
|
||||
assert obj_id
|
||||
|> Pleroma.Activity.Queries.by_object_id()
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ defmodule Pleroma.ConfigDBTest do
|
|||
test "proxy tuple with domain" do
|
||||
assert ConfigDB.to_elixir_types(%{
|
||||
"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]
|
||||
}) == {:proxy_url, {:socks5, 'domain.com', 1234}}
|
||||
}) == {:proxy_url, {:socks5, ~c"domain.com", 1234}}
|
||||
end
|
||||
|
||||
test "proxy tuple with ip" do
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.LanguageCodeTest do
|
|||
test "errors for invalid language code" do
|
||||
assert {:error, :invalid_language} = LanguageCode.cast("ru_RU")
|
||||
assert {:error, :invalid_language} = LanguageCode.cast(" ")
|
||||
assert {:error, :invalid_language} = LanguageCode.cast("en-US\n")
|
||||
end
|
||||
|
||||
test "errors for non-text" do
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ defmodule Pleroma.Gun.ConnectionPoolTest do
|
|||
end
|
||||
end
|
||||
|
||||
@tag :erratic
|
||||
test "connection limit is respected with concurrent requests" do
|
||||
clear_config([:connections_pool, :max_connections]) do
|
||||
clear_config([:connections_pool, :max_connections], 1)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ defmodule Pleroma.HTMLTest do
|
|||
<span class="h-card"><a class="u-url mention animate-spin">@<span>foo</span></a></span>
|
||||
"""
|
||||
|
||||
@mention_hashtags_sample """
|
||||
<a href="https://mastodon.example/tags/linux" class="mention hashtag" rel="tag">#<span>linux</span></a>
|
||||
"""
|
||||
|
||||
describe "StripTags scrubber" do
|
||||
test "works as expected" do
|
||||
expected = """
|
||||
|
|
@ -126,6 +130,15 @@ defmodule Pleroma.HTMLTest do
|
|||
Pleroma.HTML.Scrubber.TwitterText
|
||||
)
|
||||
end
|
||||
|
||||
test "does allow mention hashtags" do
|
||||
expected = """
|
||||
<a href="https://mastodon.example/tags/linux" class="mention hashtag" rel="tag">#<span>linux</span></a>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@mention_hashtags_sample, Pleroma.HTML.Scrubber.Default)
|
||||
end
|
||||
end
|
||||
|
||||
describe "default scrubber" do
|
||||
|
|
@ -189,6 +202,15 @@ defmodule Pleroma.HTMLTest do
|
|||
Pleroma.HTML.Scrubber.Default
|
||||
)
|
||||
end
|
||||
|
||||
test "does allow mention hashtags" do
|
||||
expected = """
|
||||
<a href="https://mastodon.example/tags/linux" class="mention hashtag" rel="tag">#<span>linux</span></a>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@mention_hashtags_sample, Pleroma.HTML.Scrubber.Default)
|
||||
end
|
||||
end
|
||||
|
||||
describe "extract_first_external_url_from_object" do
|
||||
|
|
|
|||
|
|
@ -55,23 +55,23 @@ defmodule Pleroma.HTTP.AdapterHelper.GunTest do
|
|||
|
||||
uri = URI.parse("https://some-domain.com")
|
||||
opts = Gun.options([receive_conn: false], uri)
|
||||
assert opts[:proxy] == {'localhost', 8123}
|
||||
assert opts[:proxy] == {~c"localhost", 8123}
|
||||
end
|
||||
|
||||
test "parses tuple proxy scheme host and port" do
|
||||
clear_config([:http, :proxy_url], {:socks, 'localhost', 1234})
|
||||
clear_config([:http, :proxy_url], {:socks, ~c"localhost", 1234})
|
||||
|
||||
uri = URI.parse("https://some-domain.com")
|
||||
opts = Gun.options([receive_conn: false], uri)
|
||||
assert opts[:proxy] == {:socks, 'localhost', 1234}
|
||||
assert opts[:proxy] == {:socks, ~c"localhost", 1234}
|
||||
end
|
||||
|
||||
test "passed opts have more weight than defaults" do
|
||||
clear_config([:http, :proxy_url], {:socks5, 'localhost', 1234})
|
||||
clear_config([:http, :proxy_url], {:socks5, ~c"localhost", 1234})
|
||||
uri = URI.parse("https://some-domain.com")
|
||||
opts = Gun.options([receive_conn: false, proxy: {'example.com', 4321}], uri)
|
||||
opts = Gun.options([receive_conn: false, proxy: {~c"example.com", 4321}], uri)
|
||||
|
||||
assert opts[:proxy] == {'example.com', 4321}
|
||||
assert opts[:proxy] == {~c"example.com", 4321}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ defmodule Pleroma.HTTP.AdapterHelperTest do
|
|||
end
|
||||
|
||||
test "localhost with port" do
|
||||
assert AdapterHelper.format_proxy("localhost:8123") == {'localhost', 8123}
|
||||
assert AdapterHelper.format_proxy("localhost:8123") == {~c"localhost", 8123}
|
||||
end
|
||||
|
||||
test "tuple" do
|
||||
assert AdapterHelper.format_proxy({:socks4, :localhost, 9050}) ==
|
||||
{:socks4, 'localhost', 9050}
|
||||
{:socks4, ~c"localhost", 9050}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -268,6 +268,17 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
end)
|
||||
end
|
||||
|
||||
test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
|
||||
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
|
||||
|
||||
capture_log(fn ->
|
||||
assert {:error, %WebSockex.RequestError{code: 401}} =
|
||||
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
|
||||
|
||||
Process.sleep(30)
|
||||
end)
|
||||
end
|
||||
|
||||
test "accepts valid token on client-sent event", %{token: token} do
|
||||
assert {:ok, pid} = start_socket()
|
||||
|
||||
|
|
@ -404,7 +415,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
|
||||
test "receives private statuses", %{user: reading_user, token: token} do
|
||||
user = insert(:user)
|
||||
CommonAPI.follow(reading_user, user)
|
||||
CommonAPI.follow(user, reading_user)
|
||||
|
||||
{:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
||||
|
||||
|
|
@ -431,7 +442,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
|
||||
test "receives edits", %{user: reading_user, token: token} do
|
||||
user = insert(:user)
|
||||
CommonAPI.follow(reading_user, user)
|
||||
CommonAPI.follow(user, reading_user)
|
||||
|
||||
{:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
||||
|
||||
|
|
@ -440,7 +451,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
|
||||
assert_receive {:text, _raw_json}, 1_000
|
||||
|
||||
{:ok, _} = CommonAPI.update(user, activity, %{status: "mew mew", visibility: "private"})
|
||||
{:ok, _} = CommonAPI.update(activity, user, %{status: "mew mew", visibility: "private"})
|
||||
|
||||
assert_receive {:text, raw_json}, 1_000
|
||||
|
||||
|
|
@ -459,7 +470,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
|
||||
test "receives notifications", %{user: reading_user, token: token} do
|
||||
user = insert(:user)
|
||||
CommonAPI.follow(reading_user, user)
|
||||
CommonAPI.follow(user, reading_user)
|
||||
|
||||
{:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
||||
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@ defmodule Pleroma.JobQueueMonitorTest do
|
|||
queue: "background",
|
||||
stack: [
|
||||
{Pleroma.Workers.BackgroundWorker, :perform, 2,
|
||||
[file: 'lib/pleroma/workers/background_worker.ex', line: 31]},
|
||||
[file: ~c"lib/pleroma/workers/background_worker.ex", line: 31]},
|
||||
{Oban.Queue.Executor, :safe_call, 1,
|
||||
[file: 'lib/oban/queue/executor.ex', line: 42]},
|
||||
{:timer, :tc, 3, [file: 'timer.erl', line: 197]},
|
||||
{Oban.Queue.Executor, :call, 2, [file: 'lib/oban/queue/executor.ex', line: 23]},
|
||||
{Task.Supervised, :invoke_mfa, 2, [file: 'lib/task/supervised.ex', line: 90]},
|
||||
{:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}
|
||||
[file: ~c"lib/oban/queue/executor.ex", line: 42]},
|
||||
{:timer, :tc, 3, [file: ~c"timer.erl", line: 197]},
|
||||
{Oban.Queue.Executor, :call, 2, [file: ~c"lib/oban/queue/executor.ex", line: 23]},
|
||||
{Task.Supervised, :invoke_mfa, 2, [file: ~c"lib/task/supervised.ex", line: 90]},
|
||||
{:proc_lib, :init_p_do_apply, 3, [file: ~c"proc_lib.erl", line: 249]}
|
||||
],
|
||||
worker: "Pleroma.Workers.BackgroundWorker"
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ defmodule Pleroma.MigrationHelper.NotificationBackfillTest do
|
|||
{:ok, post} = CommonAPI.post(user, %{status: "yeah, @#{other_user.nickname}"})
|
||||
{:ok, chat} = CommonAPI.post_chat_message(user, other_user, "yo")
|
||||
{:ok, react} = CommonAPI.react_with_emoji(post.id, other_user, "☕")
|
||||
{:ok, like} = CommonAPI.favorite(other_user, post.id)
|
||||
{:ok, like} = CommonAPI.favorite(post.id, other_user)
|
||||
{:ok, react_2} = CommonAPI.react_with_emoji(post.id, other_user, "☕")
|
||||
|
||||
data =
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ defmodule Pleroma.NotificationTest do
|
|||
{:ok, [notification]} = Notification.create_notifications(status)
|
||||
|
||||
assert notification.user_id == subscriber.id
|
||||
assert notification.type == "status"
|
||||
end
|
||||
|
||||
test "does not create a notification for subscribed users if status is a reply" do
|
||||
|
|
@ -136,6 +137,21 @@ defmodule Pleroma.NotificationTest do
|
|||
assert Enum.empty?(subscriber_notifications)
|
||||
end
|
||||
|
||||
test "does not create subscriber notification if mentioned" do
|
||||
user = insert(:user)
|
||||
subscriber = insert(:user)
|
||||
|
||||
User.subscribe(subscriber, user)
|
||||
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "mentioning @#{subscriber.nickname}"})
|
||||
{:ok, [notification] = notifications} = Notification.create_notifications(status)
|
||||
|
||||
assert length(notifications) == 1
|
||||
|
||||
assert notification.user_id == subscriber.id
|
||||
assert notification.type == "mention"
|
||||
end
|
||||
|
||||
test "it sends edited notifications to those who repeated a status" do
|
||||
user = insert(:user)
|
||||
repeated_user = insert(:user)
|
||||
|
|
@ -149,7 +165,7 @@ defmodule Pleroma.NotificationTest do
|
|||
{:ok, _activity_two} = CommonAPI.repeat(activity_one.id, repeated_user)
|
||||
|
||||
{:ok, _edit_activity} =
|
||||
CommonAPI.update(user, activity_one, %{
|
||||
CommonAPI.update(activity_one, user, %{
|
||||
status: "hey @#{other_user.nickname}! mew mew"
|
||||
})
|
||||
|
||||
|
|
@ -164,8 +180,8 @@ defmodule Pleroma.NotificationTest do
|
|||
question = insert(:question, user: user1)
|
||||
activity = insert(:question_activity, question: question)
|
||||
|
||||
{:ok, _, _} = CommonAPI.vote(user2, question, [0])
|
||||
{:ok, _, _} = CommonAPI.vote(user3, question, [1])
|
||||
{:ok, _, _} = CommonAPI.vote(question, user2, [0])
|
||||
{:ok, _, _} = CommonAPI.vote(question, user3, [1])
|
||||
|
||||
{:ok, notifications} = Notification.create_poll_notifications(activity)
|
||||
|
||||
|
|
@ -193,7 +209,7 @@ defmodule Pleroma.NotificationTest do
|
|||
notification_settings: %Pleroma.User.NotificationSetting{block_from_strangers: true}
|
||||
)
|
||||
|
||||
CommonAPI.follow(follower, followed)
|
||||
CommonAPI.follow(followed, follower)
|
||||
{:ok, activity} = CommonAPI.post(follower, %{status: "hey @#{followed.nickname}"})
|
||||
refute Notification.create_notification(activity, followed)
|
||||
end
|
||||
|
|
@ -206,7 +222,7 @@ defmodule Pleroma.NotificationTest do
|
|||
notification_settings: %Pleroma.User.NotificationSetting{block_from_strangers: true}
|
||||
)
|
||||
|
||||
CommonAPI.follow(receiver, poster)
|
||||
CommonAPI.follow(poster, receiver)
|
||||
{:ok, activity} = CommonAPI.post(poster, %{status: "hey @#{receiver.nickname}"})
|
||||
assert Notification.create_notification(activity, receiver)
|
||||
end
|
||||
|
|
@ -222,7 +238,7 @@ defmodule Pleroma.NotificationTest do
|
|||
user = insert(:user)
|
||||
subscriber = insert(:user)
|
||||
|
||||
{:ok, _, _, _} = CommonAPI.follow(subscriber, user)
|
||||
{:ok, _, _, _} = CommonAPI.follow(user, subscriber)
|
||||
User.subscribe(subscriber, user)
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "Akariiiin"})
|
||||
{:ok, [_notif]} = Notification.create_notifications(status)
|
||||
|
|
@ -279,7 +295,7 @@ defmodule Pleroma.NotificationTest do
|
|||
insert(:filter, user: user, phrase: "tesla", hide: true)
|
||||
|
||||
{:ok, activity_one} = CommonAPI.post(user, %{status: "wow tesla"})
|
||||
{:ok, activity_two} = CommonAPI.favorite(other_user, activity_one.id)
|
||||
{:ok, activity_two} = CommonAPI.favorite(activity_one.id, other_user)
|
||||
|
||||
{:ok, [notification]} = Notification.create_notifications(activity_two)
|
||||
|
||||
|
|
@ -293,7 +309,7 @@ defmodule Pleroma.NotificationTest do
|
|||
user = insert(:user)
|
||||
followed_user = insert(:user, is_locked: false)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(followed_user, user)
|
||||
assert FollowingRelationship.following?(user, followed_user)
|
||||
assert [notification] = Notification.for_user(followed_user)
|
||||
|
||||
|
|
@ -308,7 +324,7 @@ defmodule Pleroma.NotificationTest do
|
|||
user = insert(:user)
|
||||
followed_user = insert(:user, is_locked: true)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(followed_user, user)
|
||||
refute FollowingRelationship.following?(user, followed_user)
|
||||
assert [notification] = Notification.for_user(followed_user)
|
||||
|
||||
|
|
@ -323,19 +339,22 @@ defmodule Pleroma.NotificationTest do
|
|||
|> Repo.preload(:activity)
|
||||
|
||||
assert %{type: "follow"} =
|
||||
NotificationView.render("show.json", notification: notification, for: followed_user)
|
||||
NotificationView.render("show.json",
|
||||
notification: notification,
|
||||
for: followed_user
|
||||
)
|
||||
end
|
||||
|
||||
test "it doesn't create a notification for follow-unfollow-follow chains" do
|
||||
user = insert(:user)
|
||||
followed_user = insert(:user, is_locked: false)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(followed_user, user)
|
||||
assert FollowingRelationship.following?(user, followed_user)
|
||||
assert [notification] = Notification.for_user(followed_user)
|
||||
|
||||
CommonAPI.unfollow(user, followed_user)
|
||||
{:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
|
||||
CommonAPI.unfollow(followed_user, user)
|
||||
{:ok, _, _, _activity_dupe} = CommonAPI.follow(followed_user, user)
|
||||
|
||||
notification_id = notification.id
|
||||
assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
|
||||
|
|
@ -344,7 +363,7 @@ defmodule Pleroma.NotificationTest do
|
|||
test "dismisses the notification on follow request rejection" do
|
||||
user = insert(:user, is_locked: true)
|
||||
follower = insert(:user)
|
||||
{:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, _follow_activity} = CommonAPI.follow(user, follower)
|
||||
assert [_notification] = Notification.for_user(user)
|
||||
{:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
|
||||
assert [] = Notification.for_user(user)
|
||||
|
|
@ -449,9 +468,7 @@ defmodule Pleroma.NotificationTest do
|
|||
status: "hey yet again @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
[_, read_notification] = Notification.set_read_up_to(other_user, n2.id)
|
||||
|
||||
assert read_notification.activity.object
|
||||
Notification.set_read_up_to(other_user, n2.id)
|
||||
|
||||
[n3, n2, n1] = Notification.for_user(other_user)
|
||||
|
||||
|
|
@ -600,7 +617,7 @@ defmodule Pleroma.NotificationTest do
|
|||
status: "hey @#{other_user.nickname}!"
|
||||
})
|
||||
|
||||
{:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
|
||||
{:ok, activity_two} = CommonAPI.favorite(activity_one.id, third_user)
|
||||
|
||||
enabled_receivers = Notification.get_notified_from_activity(activity_two)
|
||||
|
||||
|
|
@ -676,7 +693,7 @@ defmodule Pleroma.NotificationTest do
|
|||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
|
||||
|
||||
{:ok, _} = CommonAPI.add_mute(other_user, activity)
|
||||
{:ok, _} = CommonAPI.add_mute(activity, other_user)
|
||||
|
||||
{:ok, same_context_activity} =
|
||||
CommonAPI.post(user, %{
|
||||
|
|
@ -731,7 +748,7 @@ defmodule Pleroma.NotificationTest do
|
|||
{:ok, _activity_two} = CommonAPI.repeat(activity_one.id, repeated_user)
|
||||
|
||||
{:ok, edit_activity} =
|
||||
CommonAPI.update(user, activity_one, %{
|
||||
CommonAPI.update(activity_one, user, %{
|
||||
status: "hey @#{other_user.nickname}! mew mew"
|
||||
})
|
||||
|
||||
|
|
@ -751,7 +768,7 @@ defmodule Pleroma.NotificationTest do
|
|||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
|
||||
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(activity.id, other_user)
|
||||
|
||||
assert length(Notification.for_user(user)) == 1
|
||||
|
||||
|
|
@ -768,7 +785,7 @@ defmodule Pleroma.NotificationTest do
|
|||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
|
||||
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(activity.id, other_user)
|
||||
|
||||
assert length(Notification.for_user(user)) == 1
|
||||
|
||||
|
|
@ -823,7 +840,7 @@ defmodule Pleroma.NotificationTest do
|
|||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
|
||||
{:error, :not_found} = CommonAPI.favorite(other_user, activity.id)
|
||||
{:error, :not_found} = CommonAPI.favorite(activity.id, other_user)
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
end
|
||||
|
|
@ -845,22 +862,6 @@ defmodule Pleroma.NotificationTest do
|
|||
assert Enum.empty?(Notification.for_user(user))
|
||||
end
|
||||
|
||||
test "replying to a deleted post without tagging does not generate a notification" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "test post"})
|
||||
{:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
|
||||
|
||||
{:ok, _reply_activity} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "test reply",
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
assert Enum.empty?(Notification.for_user(user))
|
||||
end
|
||||
|
||||
test "notifications are deleted if a local user is deleted" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
|
@ -1089,7 +1090,7 @@ defmodule Pleroma.NotificationTest do
|
|||
another_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Give me my cofe!"})
|
||||
{:ok, _} = CommonAPI.favorite(another_user, activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(activity.id, another_user)
|
||||
|
||||
assert length(Notification.for_user(user)) == 1
|
||||
end
|
||||
|
|
@ -1100,7 +1101,7 @@ defmodule Pleroma.NotificationTest do
|
|||
|
||||
insert(:filter, user: followed_user, phrase: "test", hide: true)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(followed_user, user)
|
||||
refute FollowingRelationship.following?(user, followed_user)
|
||||
assert [notification] = Notification.for_user(followed_user)
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,6 @@ defmodule Pleroma.Object.FetcherTest do
|
|||
:ok
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it works when fetching the OP actor errors out" do
|
||||
# Here we simulate a case where the author of the OP can't be read
|
||||
assert {:ok, _} =
|
||||
|
|
@ -101,7 +100,7 @@ defmodule Pleroma.Object.FetcherTest do
|
|||
test "it returns thread depth exceeded error if thread depth is exceeded" do
|
||||
clear_config([:instance, :federation_incoming_replies_max_depth], 0)
|
||||
|
||||
assert {:error, :allowed_depth} = Fetcher.fetch_object_from_id(@ap_id, depth: 1)
|
||||
assert {:allowed_depth, false} = Fetcher.fetch_object_from_id(@ap_id, depth: 1)
|
||||
end
|
||||
|
||||
test "it fetches object if max thread depth is restricted to 0 and depth is not specified" do
|
||||
|
|
@ -119,15 +118,18 @@ defmodule Pleroma.Object.FetcherTest do
|
|||
|
||||
describe "actor origin containment" do
|
||||
test "it rejects objects with a bogus origin" do
|
||||
{:error, _} = Fetcher.fetch_object_from_id("https://info.pleroma.site/activity.json")
|
||||
{:containment, :error} =
|
||||
Fetcher.fetch_object_from_id("https://info.pleroma.site/activity.json")
|
||||
end
|
||||
|
||||
test "it rejects objects when attributedTo is wrong (variant 1)" do
|
||||
{:error, _} = Fetcher.fetch_object_from_id("https://info.pleroma.site/activity2.json")
|
||||
{:containment, :error} =
|
||||
Fetcher.fetch_object_from_id("https://info.pleroma.site/activity2.json")
|
||||
end
|
||||
|
||||
test "it rejects objects when attributedTo is wrong (variant 2)" do
|
||||
{:error, _} = Fetcher.fetch_object_from_id("https://info.pleroma.site/activity3.json")
|
||||
{:containment, :error} =
|
||||
Fetcher.fetch_object_from_id("https://info.pleroma.site/activity3.json")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -151,14 +153,14 @@ defmodule Pleroma.Object.FetcherTest do
|
|||
clear_config([:mrf_keyword, :reject], ["yeah"])
|
||||
clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy])
|
||||
|
||||
assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} ==
|
||||
assert {:transmogrifier, {:reject, "[KeywordPolicy] Matches with rejected keyword"}} ==
|
||||
Fetcher.fetch_object_from_id(
|
||||
"http://mastodon.example.org/@admin/99541947525187367"
|
||||
)
|
||||
end
|
||||
|
||||
test "it does not fetch a spoofed object uploaded on an instance as an attachment" do
|
||||
assert {:error, _} =
|
||||
assert {:fetch, {:error, {:content_type, "application/json"}}} =
|
||||
Fetcher.fetch_object_from_id(
|
||||
"https://patch.cx/media/03ca3c8b4ac3ddd08bf0f84be7885f2f88de0f709112131a22d83650819e36c2.json"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,12 +6,10 @@ defmodule Pleroma.ObjectTest do
|
|||
use Pleroma.DataCase
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Hashtag
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
|
|
@ -176,8 +174,9 @@ defmodule Pleroma.ObjectTest do
|
|||
|
||||
filename = Path.basename(href)
|
||||
|
||||
assert {:ok, files} = File.ls(uploads_dir)
|
||||
assert filename in files
|
||||
expected_path = Path.join([uploads_dir, Pleroma.Upload.Filter.Dedupe.shard_path(filename)])
|
||||
|
||||
assert File.exists?(expected_path)
|
||||
|
||||
Object.delete(note)
|
||||
|
||||
|
|
@ -185,8 +184,7 @@ defmodule Pleroma.ObjectTest do
|
|||
|
||||
assert Object.get_by_id(note.id).data["deleted"]
|
||||
assert Object.get_by_id(attachment.id) == nil
|
||||
assert {:ok, files} = File.ls(uploads_dir)
|
||||
refute filename in files
|
||||
refute File.exists?(expected_path)
|
||||
end
|
||||
|
||||
test "with objects that have legacy data.url attribute" do
|
||||
|
|
@ -282,148 +280,6 @@ defmodule Pleroma.ObjectTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "get_by_id_and_maybe_refetch" do
|
||||
setup do
|
||||
mock(fn
|
||||
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/poll_original.json"),
|
||||
headers: HttpRequestMock.activitypub_object_headers()
|
||||
}
|
||||
|
||||
env ->
|
||||
apply(HttpRequestMock, :request, [env])
|
||||
end)
|
||||
|
||||
mock_modified = fn resp ->
|
||||
mock(fn
|
||||
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
|
||||
resp
|
||||
|
||||
env ->
|
||||
apply(HttpRequestMock, :request, [env])
|
||||
end)
|
||||
end
|
||||
|
||||
on_exit(fn -> mock(fn env -> apply(HttpRequestMock, :request, [env]) end) end)
|
||||
|
||||
[mock_modified: mock_modified]
|
||||
end
|
||||
|
||||
test "refetches if the time since the last refetch is greater than the interval", %{
|
||||
mock_modified: mock_modified
|
||||
} do
|
||||
%Object{} =
|
||||
object =
|
||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
||||
fetch: true
|
||||
)
|
||||
|
||||
Object.set_cache(object)
|
||||
|
||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
|
||||
mock_modified.(%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/poll_modified.json"),
|
||||
headers: HttpRequestMock.activitypub_object_headers()
|
||||
})
|
||||
|
||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
||||
assert updated_object == object_in_cache
|
||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
|
||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
|
||||
end
|
||||
|
||||
test "returns the old object if refetch fails", %{mock_modified: mock_modified} do
|
||||
%Object{} =
|
||||
object =
|
||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
||||
fetch: true
|
||||
)
|
||||
|
||||
Object.set_cache(object)
|
||||
|
||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
|
||||
assert capture_log(fn ->
|
||||
mock_modified.(%Tesla.Env{status: 404, body: ""})
|
||||
|
||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
||||
assert updated_object == object_in_cache
|
||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
end) =~
|
||||
"[error] Couldn't refresh https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"
|
||||
end
|
||||
|
||||
test "does not refetch if the time since the last refetch is greater than the interval", %{
|
||||
mock_modified: mock_modified
|
||||
} do
|
||||
%Object{} =
|
||||
object =
|
||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
||||
fetch: true
|
||||
)
|
||||
|
||||
Object.set_cache(object)
|
||||
|
||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
|
||||
mock_modified.(%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/poll_modified.json"),
|
||||
headers: HttpRequestMock.activitypub_object_headers()
|
||||
})
|
||||
|
||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
|
||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
||||
assert updated_object == object_in_cache
|
||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
end
|
||||
|
||||
test "preserves internal fields on refetch", %{mock_modified: mock_modified} do
|
||||
%Object{} =
|
||||
object =
|
||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
||||
fetch: true
|
||||
)
|
||||
|
||||
Object.set_cache(object)
|
||||
|
||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||
|
||||
user = insert(:user)
|
||||
activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
||||
{:ok, activity} = CommonAPI.favorite(user, activity.id)
|
||||
object = Object.get_by_ap_id(activity.data["object"])
|
||||
|
||||
assert object.data["like_count"] == 1
|
||||
|
||||
mock_modified.(%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/poll_modified.json"),
|
||||
headers: HttpRequestMock.activitypub_object_headers()
|
||||
})
|
||||
|
||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
||||
assert updated_object == object_in_cache
|
||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
|
||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
|
||||
|
||||
assert updated_object.data["like_count"] == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe ":hashtags association" do
|
||||
test "Hashtag records are created with Object record and updated on its change" do
|
||||
user = insert(:user)
|
||||
|
|
|
|||
19
test/pleroma/release_task_test.exs
Normal file
19
test/pleroma/release_task_test.exs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ReleaseTaskTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.ReleaseTasks
|
||||
|
||||
test "finding the module" do
|
||||
task = "search.meilisearch"
|
||||
assert Mix.Tasks.Pleroma.Search.Meilisearch == ReleaseTasks.find_module(task)
|
||||
|
||||
task = "user"
|
||||
assert Mix.Tasks.Pleroma.User == ReleaseTasks.find_module(task)
|
||||
|
||||
refute ReleaseTasks.find_module("doesnt.exist")
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Repo.Migrations.PublisherMigrationChangeTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
import Pleroma.Tests.Helpers
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Workers.PublisherWorker
|
||||
|
||||
setup_all do: require_migration("20240729163838_publisher_job_change")
|
||||
|
||||
describe "up/0" do
|
||||
test "migrates publisher jobs to new format", %{migration: migration} do
|
||||
user = insert(:user)
|
||||
|
||||
%Activity{id: activity_id, data: %{"id" => ap_id}} =
|
||||
insert(:note_activity, user: user)
|
||||
|
||||
{:ok, %{id: job_id}} =
|
||||
PublisherWorker.new(%{
|
||||
"actor_id" => user.id,
|
||||
"json" => "{}",
|
||||
"id" => ap_id,
|
||||
"inbox" => "https://example.com/inbox",
|
||||
"unreachable_since" => nil
|
||||
})
|
||||
|> Oban.insert()
|
||||
|
||||
assert [%{id: ^job_id, args: %{"id" => ^ap_id}}] = all_enqueued(worker: PublisherWorker)
|
||||
|
||||
assert migration.up() == :ok
|
||||
|
||||
assert_enqueued(
|
||||
worker: PublisherWorker,
|
||||
args: %{"id" => ap_id, "activity_id" => activity_id}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -18,7 +18,7 @@ defmodule Pleroma.ResilienceTest do
|
|||
other_user = insert(:user)
|
||||
|
||||
{:ok, post_one} = CommonAPI.post(user, %{status: "Here is a post"})
|
||||
{:ok, like} = CommonAPI.favorite(other_user, post_one.id)
|
||||
{:ok, like} = CommonAPI.favorite(post_one.id, other_user)
|
||||
|
||||
%{
|
||||
user: user,
|
||||
|
|
@ -90,7 +90,7 @@ defmodule Pleroma.ResilienceTest do
|
|||
|> json_response(200)
|
||||
|
||||
# Favoriting again doesn't hurt
|
||||
{:ok, _like_two} = CommonAPI.favorite(other_user, post.id)
|
||||
{:ok, _like_two} = CommonAPI.favorite(post.id, other_user)
|
||||
|
||||
post = Repo.get(Activity, post.id)
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ defmodule Pleroma.ScheduledActivityTest do
|
|||
{:ok, sa1} = ScheduledActivity.create(user, attrs)
|
||||
{:ok, sa2} = ScheduledActivity.create(user, attrs)
|
||||
|
||||
jobs =
|
||||
Repo.all(from(j in Oban.Job, where: j.queue == "scheduled_activities", select: j.args))
|
||||
jobs = Repo.all(from(j in Oban.Job, where: j.queue == "federator_outgoing", select: j.args))
|
||||
|
||||
assert jobs == [%{"activity_id" => sa1.id}, %{"activity_id" => sa2.id}]
|
||||
end
|
||||
|
|
|
|||
17
test/pleroma/schema_test.exs
Normal file
17
test/pleroma/schema_test.exs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.SchemaTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.Repo
|
||||
|
||||
test "No unindexed foreign keys" do
|
||||
query = File.read!("test/fixtures/unindexed_fk.sql")
|
||||
|
||||
{:ok, result} = Repo.query(query)
|
||||
|
||||
assert Enum.empty?(result.rows)
|
||||
end
|
||||
end
|
||||
49
test/pleroma/search/healthcheck_test.exs
Normal file
49
test/pleroma/search/healthcheck_test.exs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Search.HealthcheckTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
import Tesla.Mock
|
||||
|
||||
alias Pleroma.Search.Healthcheck
|
||||
|
||||
@good1 "http://good1.example.com/healthz"
|
||||
@good2 "http://good2.example.com/health"
|
||||
@bad "http://bad.example.com/healthy"
|
||||
|
||||
setup do
|
||||
mock(fn
|
||||
%{method: :get, url: @good1} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: ""
|
||||
}
|
||||
|
||||
%{method: :get, url: @good2} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: ""
|
||||
}
|
||||
|
||||
%{method: :get, url: @bad} ->
|
||||
%Tesla.Env{
|
||||
status: 503,
|
||||
body: ""
|
||||
}
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "true for 200 responses" do
|
||||
assert Healthcheck.check([@good1])
|
||||
assert Healthcheck.check([@good1, @good2])
|
||||
end
|
||||
|
||||
test "false if any response is not a 200" do
|
||||
refute Healthcheck.check([@bad])
|
||||
refute Healthcheck.check([@good1, @bad])
|
||||
end
|
||||
end
|
||||
199
test/pleroma/search/qdrant_search_test.exs
Normal file
199
test/pleroma/search/qdrant_search_test.exs
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Search.QdrantSearchTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mox
|
||||
|
||||
alias Pleroma.Search.QdrantSearch
|
||||
alias Pleroma.UnstubbedConfigMock, as: Config
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Workers.SearchIndexingWorker
|
||||
|
||||
describe "Qdrant search" do
|
||||
test "returns the correct healthcheck endpoints" do
|
||||
# No openai healthcheck URL
|
||||
Config
|
||||
|> expect(:get, 2, fn
|
||||
[Pleroma.Search.QdrantSearch, key], nil ->
|
||||
%{qdrant_url: "https://qdrant.url"}[key]
|
||||
end)
|
||||
|
||||
[health_endpoint] = QdrantSearch.healthcheck_endpoints()
|
||||
|
||||
assert "https://qdrant.url/healthz" == health_endpoint
|
||||
|
||||
# Set openai healthcheck URL
|
||||
Config
|
||||
|> expect(:get, 2, fn
|
||||
[Pleroma.Search.QdrantSearch, key], nil ->
|
||||
%{qdrant_url: "https://qdrant.url", openai_healthcheck_url: "https://openai.url/health"}[
|
||||
key
|
||||
]
|
||||
end)
|
||||
|
||||
[_, health_endpoint] = QdrantSearch.healthcheck_endpoints()
|
||||
|
||||
assert "https://openai.url/health" == health_endpoint
|
||||
end
|
||||
|
||||
test "searches for a term by encoding it and sending it to qdrant" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "guys i just don't wanna leave the swamp",
|
||||
visibility: "public"
|
||||
})
|
||||
|
||||
Config
|
||||
|> expect(:get, 3, fn
|
||||
[Pleroma.Search, :module], nil ->
|
||||
QdrantSearch
|
||||
|
||||
[Pleroma.Search.QdrantSearch, key], nil ->
|
||||
%{
|
||||
openai_model: "a_model",
|
||||
openai_url: "https://openai.url",
|
||||
qdrant_url: "https://qdrant.url"
|
||||
}[key]
|
||||
end)
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://openai.url/v1/embeddings", method: :post} ->
|
||||
Tesla.Mock.json(%{
|
||||
data: [%{embedding: [1, 2, 3]}]
|
||||
})
|
||||
|
||||
%{url: "https://qdrant.url/collections/posts/points/search", method: :post, body: body} ->
|
||||
data = Jason.decode!(body)
|
||||
refute data["filter"]
|
||||
|
||||
Tesla.Mock.json(%{
|
||||
result: [%{"id" => activity.id |> FlakeId.from_string() |> Ecto.UUID.cast!()}]
|
||||
})
|
||||
end)
|
||||
|
||||
results = QdrantSearch.search(nil, "guys i just don't wanna leave the swamp", %{})
|
||||
|
||||
assert results == [activity]
|
||||
end
|
||||
|
||||
test "for a given actor, ask for only relevant matches" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "guys i just don't wanna leave the swamp",
|
||||
visibility: "public"
|
||||
})
|
||||
|
||||
Config
|
||||
|> expect(:get, 3, fn
|
||||
[Pleroma.Search, :module], nil ->
|
||||
QdrantSearch
|
||||
|
||||
[Pleroma.Search.QdrantSearch, key], nil ->
|
||||
%{
|
||||
openai_model: "a_model",
|
||||
openai_url: "https://openai.url",
|
||||
qdrant_url: "https://qdrant.url"
|
||||
}[key]
|
||||
end)
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://openai.url/v1/embeddings", method: :post} ->
|
||||
Tesla.Mock.json(%{
|
||||
data: [%{embedding: [1, 2, 3]}]
|
||||
})
|
||||
|
||||
%{url: "https://qdrant.url/collections/posts/points/search", method: :post, body: body} ->
|
||||
data = Jason.decode!(body)
|
||||
|
||||
assert data["filter"] == %{
|
||||
"must" => [%{"key" => "actor", "match" => %{"value" => user.ap_id}}]
|
||||
}
|
||||
|
||||
Tesla.Mock.json(%{
|
||||
result: [%{"id" => activity.id |> FlakeId.from_string() |> Ecto.UUID.cast!()}]
|
||||
})
|
||||
end)
|
||||
|
||||
results =
|
||||
QdrantSearch.search(nil, "guys i just don't wanna leave the swamp", %{author: user})
|
||||
|
||||
assert results == [activity]
|
||||
end
|
||||
|
||||
test "indexes a public post on creation, deletes from the index on deletion" do
|
||||
user = insert(:user)
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :post, url: "https://openai.url/v1/embeddings"} ->
|
||||
send(self(), "posted_to_openai")
|
||||
|
||||
Tesla.Mock.json(%{
|
||||
data: [%{embedding: [1, 2, 3]}]
|
||||
})
|
||||
|
||||
%{method: :put, url: "https://qdrant.url/collections/posts/points", body: body} ->
|
||||
send(self(), "posted_to_qdrant")
|
||||
|
||||
data = Jason.decode!(body)
|
||||
%{"points" => [%{"vector" => vector, "payload" => payload}]} = data
|
||||
|
||||
assert vector == [1, 2, 3]
|
||||
assert payload["actor"]
|
||||
assert payload["published_at"]
|
||||
|
||||
Tesla.Mock.json("ok")
|
||||
|
||||
%{method: :post, url: "https://qdrant.url/collections/posts/points/delete"} ->
|
||||
send(self(), "deleted_from_qdrant")
|
||||
Tesla.Mock.json("ok")
|
||||
end)
|
||||
|
||||
Config
|
||||
|> expect(:get, 6, fn
|
||||
[Pleroma.Search, :module], nil ->
|
||||
QdrantSearch
|
||||
|
||||
[Pleroma.Search.QdrantSearch, key], nil ->
|
||||
%{
|
||||
openai_model: "a_model",
|
||||
openai_url: "https://openai.url",
|
||||
qdrant_url: "https://qdrant.url"
|
||||
}[key]
|
||||
end)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "guys i just don't wanna leave the swamp",
|
||||
visibility: "public"
|
||||
})
|
||||
|
||||
args = %{"op" => "add_to_index", "activity" => activity.id}
|
||||
|
||||
assert_enqueued(
|
||||
worker: SearchIndexingWorker,
|
||||
args: args
|
||||
)
|
||||
|
||||
assert :ok = perform_job(SearchIndexingWorker, args)
|
||||
assert_received("posted_to_openai")
|
||||
assert_received("posted_to_qdrant")
|
||||
|
||||
{:ok, _} = CommonAPI.delete(activity.id, user)
|
||||
|
||||
delete_args = %{"op" => "remove_from_index", "object" => activity.object.id}
|
||||
assert_enqueued(worker: SearchIndexingWorker, args: delete_args)
|
||||
assert :ok = perform_job(SearchIndexingWorker, delete_args)
|
||||
|
||||
assert_received("deleted_from_qdrant")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -67,6 +67,14 @@ defmodule Pleroma.SignatureTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "get_actor_id/1" do
|
||||
test "it returns actor id" do
|
||||
ap_id = "https://mastodon.social/users/lambadalambda"
|
||||
|
||||
assert Signature.get_actor_id(make_fake_conn(ap_id)) == {:ok, ap_id}
|
||||
end
|
||||
end
|
||||
|
||||
describe "sign/2" do
|
||||
test "it returns signature headers" do
|
||||
user =
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@ defmodule Pleroma.StatsTest do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
_ = CommonAPI.follow(user, other_user)
|
||||
CommonAPI.favorite(other_user, activity.id)
|
||||
_ = CommonAPI.follow(other_user, user)
|
||||
CommonAPI.favorite(activity.id, other_user)
|
||||
CommonAPI.repeat(activity.id, other_user)
|
||||
|
||||
assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 0} =
|
||||
|
|
|
|||
|
|
@ -34,6 +34,20 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadataTest do
|
|||
assert meta.blurhash == "eXJi-E:SwCEm5rCmn$+YWYn+15K#5A$xxCi{SiV]s*W:Efa#s.jE-T"
|
||||
end
|
||||
|
||||
test "it gets dimensions for grayscale images" do
|
||||
upload = %Pleroma.Upload{
|
||||
name: "break_analyze.png",
|
||||
content_type: "image/png",
|
||||
path: Path.absname("test/fixtures/break_analyze.png"),
|
||||
tempfile: Path.absname("test/fixtures/break_analyze.png")
|
||||
}
|
||||
|
||||
{:ok, :filtered, meta} = AnalyzeMetadata.filter(upload)
|
||||
|
||||
assert %{width: 1410, height: 2048} = meta
|
||||
assert is_nil(meta.blurhash)
|
||||
end
|
||||
|
||||
test "adds the dimensions for videos" do
|
||||
upload = %Pleroma.Upload{
|
||||
name: "coolvideo.mp4",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ defmodule Pleroma.Upload.Filter.DedupeTest do
|
|||
|
||||
@shasum "e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781"
|
||||
|
||||
test "generates a shard path for a shasum" do
|
||||
assert "e3/03/97/" <> _path = Dedupe.shard_path(@shasum)
|
||||
end
|
||||
|
||||
test "adds shasum" do
|
||||
File.cp!(
|
||||
"test/fixtures/image.jpg",
|
||||
|
|
@ -23,10 +27,12 @@ defmodule Pleroma.Upload.Filter.DedupeTest do
|
|||
tempfile: Path.absname("test/fixtures/image_tmp.jpg")
|
||||
}
|
||||
|
||||
expected_path = Dedupe.shard_path(@shasum <> ".jpg")
|
||||
|
||||
assert {
|
||||
:ok,
|
||||
:filtered,
|
||||
%Pleroma.Upload{id: @shasum, path: @shasum <> ".jpg"}
|
||||
%Pleroma.Upload{id: @shasum, path: ^expected_path}
|
||||
} = Dedupe.filter(upload)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,29 +9,31 @@ defmodule Pleroma.Upload.Filter.Exiftool.StripLocationTest do
|
|||
test "apply exiftool filter" do
|
||||
assert Pleroma.Utils.command_available?("exiftool")
|
||||
|
||||
File.cp!(
|
||||
"test/fixtures/DSCN0010.jpg",
|
||||
"test/fixtures/DSCN0010_tmp.jpg"
|
||||
)
|
||||
~w{jpg png}
|
||||
|> Enum.map(fn type ->
|
||||
File.cp!(
|
||||
"test/fixtures/DSCN0010.#{type}",
|
||||
"test/fixtures/DSCN0010_tmp.#{type}"
|
||||
)
|
||||
|
||||
upload = %Pleroma.Upload{
|
||||
name: "image_with_GPS_data.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/DSCN0010.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/DSCN0010_tmp.jpg")
|
||||
}
|
||||
upload = %Pleroma.Upload{
|
||||
name: "image_with_GPS_data.#{type}",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/DSCN0010.#{type}"),
|
||||
tempfile: Path.absname("test/fixtures/DSCN0010_tmp.#{type}")
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.StripLocation.filter(upload) == {:ok, :filtered}
|
||||
assert Filter.Exiftool.StripLocation.filter(upload) == {:ok, :filtered}
|
||||
|
||||
{exif_original, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010.jpg"])
|
||||
{exif_filtered, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010_tmp.jpg"])
|
||||
{exif_original, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010.#{type}"])
|
||||
{exif_filtered, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010_tmp.#{type}"])
|
||||
|
||||
refute exif_original == exif_filtered
|
||||
assert String.match?(exif_original, ~r/GPS/)
|
||||
refute String.match?(exif_filtered, ~r/GPS/)
|
||||
assert String.match?(exif_original, ~r/GPS/)
|
||||
refute String.match?(exif_filtered, ~r/GPS/)
|
||||
end)
|
||||
end
|
||||
|
||||
test "verify webp, heic, svg files are skipped" do
|
||||
test "verify webp, heic, svg files are skipped" do
|
||||
uploads =
|
||||
~w{webp heic svg svg+xml}
|
||||
|> Enum.map(fn type ->
|
||||
|
|
|
|||
|
|
@ -149,6 +149,9 @@ defmodule Pleroma.UploadTest do
|
|||
|
||||
test "copies the file to the configured folder with deduping" do
|
||||
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
||||
expected_filename = "e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781.jpg"
|
||||
|
||||
expected_path = Pleroma.Upload.Filter.Dedupe.shard_path(expected_filename)
|
||||
|
||||
file = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
|
|
@ -159,8 +162,7 @@ defmodule Pleroma.UploadTest do
|
|||
{:ok, data} = Upload.store(file, filters: [Pleroma.Upload.Filter.Dedupe])
|
||||
|
||||
assert List.first(data["url"])["href"] ==
|
||||
Pleroma.Upload.base_url() <>
|
||||
"e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781.jpg"
|
||||
Path.join([Pleroma.Upload.base_url(), expected_path])
|
||||
end
|
||||
|
||||
test "copies the file to the configured folder without deduping" do
|
||||
|
|
|
|||
155
test/pleroma/uploaders/ipfs_test.exs
Normal file
155
test/pleroma/uploaders/ipfs_test.exs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Uploaders.IPFSTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Uploaders.IPFS
|
||||
alias Tesla.Multipart
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
alias Pleroma.UnstubbedConfigMock, as: Config
|
||||
|
||||
describe "get_file/1" do
|
||||
setup do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Upload, :uploader] -> Pleroma.Uploaders.IPFS end)
|
||||
|> expect(:get, fn [Pleroma.Upload, :base_url] -> nil end)
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS, :public_endpoint] -> nil end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "it returns path to ipfs file with cid as subdomain" do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS, :get_gateway_url] ->
|
||||
"https://{CID}.ipfs.mydomain.com"
|
||||
end)
|
||||
|
||||
assert IPFS.get_file("testcid") == {
|
||||
:ok,
|
||||
{:url, "https://testcid.ipfs.mydomain.com"}
|
||||
}
|
||||
end
|
||||
|
||||
test "it returns path to ipfs file with cid as path" do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS, :get_gateway_url] ->
|
||||
"https://ipfs.mydomain.com/ipfs/{CID}"
|
||||
end)
|
||||
|
||||
assert IPFS.get_file("testcid") == {
|
||||
:ok,
|
||||
{:url, "https://ipfs.mydomain.com/ipfs/testcid"}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "put_file/1" do
|
||||
setup do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS, :post_gateway_url] ->
|
||||
"http://localhost:5001"
|
||||
end)
|
||||
|
||||
file_upload = %Pleroma.Upload{
|
||||
name: "image-tet.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: "test_folder/image-tet.jpg",
|
||||
tempfile: Path.absname("test/instance_static/add/shortcode.png")
|
||||
}
|
||||
|
||||
mp =
|
||||
Multipart.new()
|
||||
|> Multipart.add_content_type_param("charset=utf-8")
|
||||
|> Multipart.add_file(file_upload.tempfile)
|
||||
|
||||
[file_upload: file_upload, mp: mp]
|
||||
end
|
||||
|
||||
test "save file", %{file_upload: file_upload} do
|
||||
with_mock Pleroma.HTTP,
|
||||
post: fn "http://localhost:5001/api/v0/add",
|
||||
_mp,
|
||||
[],
|
||||
params: ["cid-version": "1"],
|
||||
pool: :upload ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"{\"Name\":\"image-tet.jpg\",\"Size\":\"5000\", \"Hash\":\"bafybeicrh7ltzx52yxcwrvxxckfmwhqdgsb6qym6dxqm2a4ymsakeshwoi\"}"
|
||||
}}
|
||||
end do
|
||||
assert IPFS.put_file(file_upload) ==
|
||||
{:ok, {:file, "bafybeicrh7ltzx52yxcwrvxxckfmwhqdgsb6qym6dxqm2a4ymsakeshwoi"}}
|
||||
end
|
||||
end
|
||||
|
||||
test "returns error", %{file_upload: file_upload} do
|
||||
with_mock Pleroma.HTTP,
|
||||
post: fn "http://localhost:5001/api/v0/add",
|
||||
_mp,
|
||||
[],
|
||||
params: ["cid-version": "1"],
|
||||
pool: :upload ->
|
||||
{:error, "IPFS Gateway upload failed"}
|
||||
end do
|
||||
assert capture_log(fn ->
|
||||
assert IPFS.put_file(file_upload) == {:error, "IPFS Gateway upload failed"}
|
||||
end) =~ "Elixir.Pleroma.Uploaders.IPFS: {:error, \"IPFS Gateway upload failed\"}"
|
||||
end
|
||||
end
|
||||
|
||||
test "returns error if JSON decode fails", %{file_upload: file_upload} do
|
||||
with_mock Pleroma.HTTP, [],
|
||||
post: fn "http://localhost:5001/api/v0/add",
|
||||
_mp,
|
||||
[],
|
||||
params: ["cid-version": "1"],
|
||||
pool: :upload ->
|
||||
{:ok, %Tesla.Env{status: 200, body: "invalid"}}
|
||||
end do
|
||||
assert capture_log(fn ->
|
||||
assert IPFS.put_file(file_upload) == {:error, "JSON decode failed"}
|
||||
end) =~
|
||||
"Elixir.Pleroma.Uploaders.IPFS: {:error, %Jason.DecodeError"
|
||||
end
|
||||
end
|
||||
|
||||
test "returns error if JSON body doesn't contain Hash key", %{file_upload: file_upload} do
|
||||
with_mock Pleroma.HTTP, [],
|
||||
post: fn "http://localhost:5001/api/v0/add",
|
||||
_mp,
|
||||
[],
|
||||
params: ["cid-version": "1"],
|
||||
pool: :upload ->
|
||||
{:ok, %Tesla.Env{status: 200, body: "{\"key\": \"value\"}"}}
|
||||
end do
|
||||
assert IPFS.put_file(file_upload) == {:error, "JSON doesn't contain Hash key"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_file/1" do
|
||||
setup do
|
||||
Config
|
||||
|> expect(:get, fn [Pleroma.Uploaders.IPFS, :post_gateway_url] ->
|
||||
"http://localhost:5001"
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test_with_mock "deletes file", Pleroma.HTTP,
|
||||
post: fn "http://localhost:5001/api/v0/files/rm", "", [], params: [arg: "image.jpg"] ->
|
||||
{:ok, %{status: 204}}
|
||||
end do
|
||||
assert :ok = IPFS.delete_file("image.jpg")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.User.BackupAsyncTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
import Pleroma.Factory
|
||||
import Mox
|
||||
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.User.Backup
|
||||
alias Pleroma.User.Backup.ProcessorMock
|
||||
|
||||
setup do
|
||||
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
|
||||
|
||||
{:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
%{backup: backup}
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it handles unrecoverable exceptions", %{backup: backup} do
|
||||
ProcessorMock
|
||||
|> expect(:do_process, fn _, _ ->
|
||||
raise "mock exception"
|
||||
end)
|
||||
|
||||
ConfigMock
|
||||
|> stub_with(Pleroma.Config)
|
||||
|
||||
{:error, %{backup: backup, reason: :exit}} = Backup.process(backup, ProcessorMock)
|
||||
|
||||
assert backup.state == :failed
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it handles timeouts", %{backup: backup} do
|
||||
ProcessorMock
|
||||
|> expect(:do_process, fn _, _ ->
|
||||
Process.sleep(:timer.seconds(4))
|
||||
end)
|
||||
|
||||
ConfigMock
|
||||
|> expect(:get, fn [Pleroma.User.Backup, :process_wait_time] -> :timer.seconds(2) end)
|
||||
|
||||
{:error, %{backup: backup, reason: :timeout}} = Backup.process(backup, ProcessorMock)
|
||||
|
||||
assert backup.state == :failed
|
||||
end
|
||||
end
|
||||
|
|
@ -6,7 +6,6 @@ defmodule Pleroma.User.BackupTest do
|
|||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.DataCase
|
||||
|
||||
import Mock
|
||||
import Pleroma.Factory
|
||||
import Swoosh.TestAssertions
|
||||
import Mox
|
||||
|
|
@ -16,7 +15,6 @@ defmodule Pleroma.User.BackupTest do
|
|||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Uploaders.S3.ExAwsMock
|
||||
alias Pleroma.User.Backup
|
||||
alias Pleroma.User.Backup.ProcessorMock
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Workers.BackupWorker
|
||||
|
||||
|
|
@ -28,79 +26,56 @@ defmodule Pleroma.User.BackupTest do
|
|||
ConfigMock
|
||||
|> stub_with(Pleroma.Config)
|
||||
|
||||
ProcessorMock
|
||||
|> stub_with(Pleroma.User.Backup.Processor)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "it does not requrie enabled email" do
|
||||
clear_config([Pleroma.Emails.Mailer, :enabled], false)
|
||||
user = insert(:user)
|
||||
assert {:ok, _} = Backup.create(user)
|
||||
assert {:ok, _} = Backup.user(user)
|
||||
end
|
||||
|
||||
test "it does not require user's email" do
|
||||
user = insert(:user, %{email: nil})
|
||||
assert {:ok, _} = Backup.create(user)
|
||||
assert {:ok, _} = Backup.user(user)
|
||||
end
|
||||
|
||||
test "it creates a backup record and an Oban job" do
|
||||
%{id: user_id} = user = insert(:user)
|
||||
assert {:ok, %Oban.Job{args: args}} = Backup.create(user)
|
||||
user = insert(:user)
|
||||
assert {:ok, %Backup{} = backup} = Backup.user(user)
|
||||
assert {:ok, %Oban.Job{args: args}} = Backup.schedule_backup(backup)
|
||||
assert_enqueued(worker: BackupWorker, args: args)
|
||||
|
||||
backup = Backup.get(args["backup_id"])
|
||||
assert %Backup{user_id: ^user_id, processed: false, file_size: 0, state: :pending} = backup
|
||||
backup = Backup.get_by_id(args["backup_id"])
|
||||
assert %Backup{processed: false, file_size: 0} = backup
|
||||
end
|
||||
|
||||
test "it return an error if the export limit is over" do
|
||||
%{id: user_id} = user = insert(:user)
|
||||
user = insert(:user)
|
||||
limit_days = Pleroma.Config.get([Backup, :limit_days])
|
||||
assert {:ok, %Oban.Job{args: args}} = Backup.create(user)
|
||||
backup = Backup.get(args["backup_id"])
|
||||
assert %Backup{user_id: ^user_id, processed: false, file_size: 0} = backup
|
||||
{:ok, first_backup} = Backup.user(user)
|
||||
{:ok, _run_backup} = Backup.run(first_backup)
|
||||
|
||||
assert Backup.create(user) == {:error, "Last export was less than #{limit_days} days ago"}
|
||||
assert Backup.user(user) == {:error, "Last export was less than #{limit_days} days ago"}
|
||||
end
|
||||
|
||||
test "it process a backup record" do
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
%{id: user_id} = user = insert(:user)
|
||||
|
||||
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, args)
|
||||
assert {:ok, %Backup{id: backup_id}} = Backup.user(user)
|
||||
|
||||
oban_args = %{"op" => "process", "backup_id" => backup_id}
|
||||
|
||||
assert {:ok, backup} = perform_job(BackupWorker, oban_args)
|
||||
assert backup.file_size > 0
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id, state: :complete} = backup
|
||||
assert match?(%Backup{id: ^backup_id, processed: true, user_id: ^user_id}, backup)
|
||||
|
||||
delete_job_args = %{"op" => "delete", "backup_id" => backup_id}
|
||||
|
||||
assert_enqueued(worker: BackupWorker, args: delete_job_args)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, delete_job_args)
|
||||
refute Backup.get(backup_id)
|
||||
|
||||
email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup)
|
||||
|
||||
assert_email_sent(
|
||||
to: {user.name, user.email},
|
||||
html_body: email.html_body
|
||||
)
|
||||
end
|
||||
|
||||
test "it updates states of the backup" do
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
%{id: user_id} = user = insert(:user)
|
||||
|
||||
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, args)
|
||||
assert backup.file_size > 0
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id, state: :complete} = backup
|
||||
|
||||
delete_job_args = %{"op" => "delete", "backup_id" => backup_id}
|
||||
|
||||
assert_enqueued(worker: BackupWorker, args: delete_job_args)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, delete_job_args)
|
||||
refute Backup.get(backup_id)
|
||||
refute Backup.get_by_id(backup_id)
|
||||
|
||||
email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup)
|
||||
|
||||
|
|
@ -114,10 +89,15 @@ defmodule Pleroma.User.BackupTest do
|
|||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
%{id: user_id} = user = insert(:user, %{email: nil})
|
||||
|
||||
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, args)
|
||||
assert backup.file_size > 0
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup
|
||||
assert {:ok, %Backup{} = backup} = Backup.user(user)
|
||||
|
||||
expected_args = %{"op" => "process", "backup_id" => backup.id}
|
||||
|
||||
assert_enqueued(worker: BackupWorker, args: %{"backup_id" => backup.id})
|
||||
assert {:ok, completed_backup} = perform_job(BackupWorker, expected_args)
|
||||
assert completed_backup.file_size > 0
|
||||
assert completed_backup.processed
|
||||
assert completed_backup.user_id == user_id
|
||||
|
||||
assert_no_email_sent()
|
||||
end
|
||||
|
|
@ -127,10 +107,13 @@ defmodule Pleroma.User.BackupTest do
|
|||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
%{id: user_id} = user = insert(:user)
|
||||
|
||||
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, args)
|
||||
assert {:ok, %Backup{id: backup_id}} = Backup.user(user)
|
||||
|
||||
oban_args = %{"op" => "process", "backup_id" => backup_id}
|
||||
|
||||
assert {:ok, backup} = perform_job(BackupWorker, oban_args)
|
||||
assert backup.file_size > 0
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup
|
||||
assert match?(%Backup{id: ^backup_id, processed: true, user_id: ^user_id}, backup)
|
||||
|
||||
assert_no_email_sent()
|
||||
end
|
||||
|
|
@ -139,10 +122,15 @@ defmodule Pleroma.User.BackupTest do
|
|||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
%{id: user_id} = user = insert(:user, %{email: ""})
|
||||
|
||||
assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user)
|
||||
assert {:ok, backup} = perform_job(BackupWorker, args)
|
||||
assert {:ok, %Backup{id: backup_id} = backup} = Backup.user(user)
|
||||
|
||||
expected_args = %{"op" => "process", "backup_id" => backup.id}
|
||||
|
||||
assert_enqueued(worker: BackupWorker, args: expected_args)
|
||||
|
||||
assert {:ok, backup} = perform_job(BackupWorker, expected_args)
|
||||
assert backup.file_size > 0
|
||||
assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup
|
||||
assert match?(%Backup{id: ^backup_id, processed: true, user_id: ^user_id}, backup)
|
||||
|
||||
assert_no_email_sent()
|
||||
end
|
||||
|
|
@ -152,16 +140,13 @@ defmodule Pleroma.User.BackupTest do
|
|||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
user = insert(:user)
|
||||
|
||||
assert {:ok, job1} = Backup.create(user)
|
||||
|
||||
assert {:ok, %Backup{}} = ObanHelpers.perform(job1)
|
||||
assert {:ok, job2} = Backup.create(user)
|
||||
assert Pleroma.Repo.aggregate(Backup, :count) == 2
|
||||
assert {:ok, backup2} = ObanHelpers.perform(job2)
|
||||
assert {:ok, %{id: backup_one_id}} = Backup.user(user)
|
||||
assert {:ok, %{id: _backup_two_id}} = Backup.user(user)
|
||||
|
||||
# Run the backups
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert [^backup2] = Pleroma.Repo.all(Backup)
|
||||
assert_enqueued(worker: BackupWorker, args: %{"op" => "delete", "backup_id" => backup_one_id})
|
||||
end
|
||||
|
||||
test "it creates a zip archive with user data" do
|
||||
|
|
@ -177,18 +162,21 @@ defmodule Pleroma.User.BackupTest do
|
|||
{:ok, %{object: %{data: %{"id" => id3}}} = status3} =
|
||||
CommonAPI.post(user, %{status: "status3"})
|
||||
|
||||
CommonAPI.favorite(user, status1.id)
|
||||
CommonAPI.favorite(user, status2.id)
|
||||
CommonAPI.favorite(status1.id, user)
|
||||
CommonAPI.favorite(status2.id, user)
|
||||
|
||||
Bookmark.create(user.id, status2.id)
|
||||
Bookmark.create(user.id, status3.id)
|
||||
|
||||
CommonAPI.follow(user, other_user)
|
||||
CommonAPI.follow(other_user, user)
|
||||
|
||||
assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
assert {:ok, path} = Backup.export(backup, self())
|
||||
assert {:ok, zipfile} = :zip.zip_open(String.to_charlist(path), [:memory])
|
||||
assert {:ok, {'actor.json', json}} = :zip.zip_get('actor.json', zipfile)
|
||||
assert {:ok, backup} = Backup.user(user)
|
||||
assert {:ok, run_backup} = Backup.run(backup)
|
||||
|
||||
tempfile = Path.join([run_backup.tempdir, run_backup.file_name])
|
||||
|
||||
assert {:ok, zipfile} = :zip.zip_open(String.to_charlist(tempfile), [:memory])
|
||||
assert {:ok, {~c"actor.json", json}} = :zip.zip_get(~c"actor.json", zipfile)
|
||||
|
||||
assert %{
|
||||
"@context" => [
|
||||
|
|
@ -197,13 +185,13 @@ defmodule Pleroma.User.BackupTest do
|
|||
%{"@language" => "und"}
|
||||
],
|
||||
"bookmarks" => "bookmarks.json",
|
||||
"followers" => "http://cofe.io/users/cofe/followers",
|
||||
"following" => "http://cofe.io/users/cofe/following",
|
||||
"followers" => "followers.json",
|
||||
"following" => "following.json",
|
||||
"id" => "http://cofe.io/users/cofe",
|
||||
"inbox" => "http://cofe.io/users/cofe/inbox",
|
||||
"likes" => "likes.json",
|
||||
"name" => "Cofe",
|
||||
"outbox" => "http://cofe.io/users/cofe/outbox",
|
||||
"outbox" => "outbox.json",
|
||||
"preferredUsername" => "cofe",
|
||||
"publicKey" => %{
|
||||
"id" => "http://cofe.io/users/cofe#main-key",
|
||||
|
|
@ -213,7 +201,7 @@ defmodule Pleroma.User.BackupTest do
|
|||
"url" => "http://cofe.io/users/cofe"
|
||||
} = Jason.decode!(json)
|
||||
|
||||
assert {:ok, {'outbox.json', json}} = :zip.zip_get('outbox.json', zipfile)
|
||||
assert {:ok, {~c"outbox.json", json}} = :zip.zip_get(~c"outbox.json", zipfile)
|
||||
|
||||
assert %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
|
|
@ -244,7 +232,7 @@ defmodule Pleroma.User.BackupTest do
|
|||
"type" => "OrderedCollection"
|
||||
} = Jason.decode!(json)
|
||||
|
||||
assert {:ok, {'likes.json', json}} = :zip.zip_get('likes.json', zipfile)
|
||||
assert {:ok, {~c"likes.json", json}} = :zip.zip_get(~c"likes.json", zipfile)
|
||||
|
||||
assert %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
|
|
@ -254,7 +242,7 @@ defmodule Pleroma.User.BackupTest do
|
|||
"type" => "OrderedCollection"
|
||||
} = Jason.decode!(json)
|
||||
|
||||
assert {:ok, {'bookmarks.json', json}} = :zip.zip_get('bookmarks.json', zipfile)
|
||||
assert {:ok, {~c"bookmarks.json", json}} = :zip.zip_get(~c"bookmarks.json", zipfile)
|
||||
|
||||
assert %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
|
|
@ -264,7 +252,7 @@ defmodule Pleroma.User.BackupTest do
|
|||
"type" => "OrderedCollection"
|
||||
} = Jason.decode!(json)
|
||||
|
||||
assert {:ok, {'following.json', json}} = :zip.zip_get('following.json', zipfile)
|
||||
assert {:ok, {~c"following.json", json}} = :zip.zip_get(~c"following.json", zipfile)
|
||||
|
||||
assert %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
|
|
@ -275,56 +263,34 @@ defmodule Pleroma.User.BackupTest do
|
|||
} = Jason.decode!(json)
|
||||
|
||||
:zip.zip_close(zipfile)
|
||||
File.rm!(path)
|
||||
File.rm_rf!(run_backup.tempdir)
|
||||
end
|
||||
|
||||
test "it counts the correct number processed" do
|
||||
test "correct number processed" do
|
||||
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
|
||||
|
||||
Enum.map(1..120, fn i ->
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "status #{i}"})
|
||||
CommonAPI.favorite(user, status.id)
|
||||
CommonAPI.favorite(status.id, user)
|
||||
Bookmark.create(user.id, status.id)
|
||||
end)
|
||||
|
||||
assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
{:ok, backup} = Backup.process(backup)
|
||||
{:ok, backup} = Backup.run(backup)
|
||||
|
||||
assert backup.processed_number == 1 + 120 + 120 + 120
|
||||
zip_path = Path.join([backup.tempdir, backup.file_name])
|
||||
|
||||
Backup.delete(backup)
|
||||
end
|
||||
assert {:ok, zipfile} = :zip.zip_open(String.to_charlist(zip_path), [:memory])
|
||||
|
||||
test "it handles errors" do
|
||||
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
|
||||
backup_parts = [~c"likes.json", ~c"bookmarks.json", ~c"outbox.json"]
|
||||
|
||||
Enum.map(1..120, fn i ->
|
||||
{:ok, _status} = CommonAPI.post(user, %{status: "status #{i}"})
|
||||
Enum.each(backup_parts, fn part ->
|
||||
assert {:ok, {_part, part_json}} = :zip.zip_get(part, zipfile)
|
||||
{:ok, decoded_part} = Jason.decode(part_json)
|
||||
assert decoded_part["totalItems"] == 120
|
||||
end)
|
||||
|
||||
assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
|
||||
with_mock Pleroma.Web.ActivityPub.Transmogrifier,
|
||||
[:passthrough],
|
||||
prepare_outgoing: fn data ->
|
||||
object =
|
||||
data["object"]
|
||||
|> Pleroma.Object.normalize(fetch: false)
|
||||
|> Map.get(:data)
|
||||
|
||||
data = data |> Map.put("object", object)
|
||||
|
||||
if String.contains?(data["object"]["content"], "119"),
|
||||
do: raise(%Postgrex.Error{}),
|
||||
else: {:ok, data}
|
||||
end do
|
||||
{:ok, backup} = Backup.process(backup)
|
||||
assert backup.processed
|
||||
assert backup.state == :complete
|
||||
assert backup.processed_number == 1 + 119
|
||||
|
||||
Backup.delete(backup)
|
||||
end
|
||||
Backup.delete_archive(backup)
|
||||
end
|
||||
|
||||
describe "it uploads and deletes a backup archive" do
|
||||
|
|
@ -337,18 +303,17 @@ defmodule Pleroma.User.BackupTest do
|
|||
{:ok, status1} = CommonAPI.post(user, %{status: "status1"})
|
||||
{:ok, status2} = CommonAPI.post(user, %{status: "status2"})
|
||||
{:ok, status3} = CommonAPI.post(user, %{status: "status3"})
|
||||
CommonAPI.favorite(user, status1.id)
|
||||
CommonAPI.favorite(user, status2.id)
|
||||
CommonAPI.favorite(status1.id, user)
|
||||
CommonAPI.favorite(status2.id, user)
|
||||
Bookmark.create(user.id, status2.id)
|
||||
Bookmark.create(user.id, status3.id)
|
||||
|
||||
assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
assert {:ok, path} = Backup.export(backup, self())
|
||||
|
||||
[path: path, backup: backup]
|
||||
[backup: backup]
|
||||
end
|
||||
|
||||
test "S3", %{path: path, backup: backup} do
|
||||
test "S3", %{backup: backup} do
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.S3)
|
||||
clear_config([Pleroma.Uploaders.S3, :streaming_enabled], false)
|
||||
|
||||
|
|
@ -358,15 +323,17 @@ defmodule Pleroma.User.BackupTest do
|
|||
%{http_method: :delete} -> {:ok, %{status_code: 204}}
|
||||
end)
|
||||
|
||||
assert {:ok, %Pleroma.Upload{}} = Backup.upload(backup, path)
|
||||
assert {:ok, _backup} = Backup.delete(backup)
|
||||
assert {:ok, backup} = Backup.run(backup)
|
||||
assert {:ok, %Backup{processed: true}} = Backup.upload(backup)
|
||||
assert {:ok, _backup} = Backup.delete_archive(backup)
|
||||
end
|
||||
|
||||
test "Local", %{path: path, backup: backup} do
|
||||
test "Local", %{backup: backup} do
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
|
||||
assert {:ok, %Pleroma.Upload{}} = Backup.upload(backup, path)
|
||||
assert {:ok, _backup} = Backup.delete(backup)
|
||||
assert {:ok, backup} = Backup.run(backup)
|
||||
assert {:ok, %Backup{processed: true}} = Backup.upload(backup)
|
||||
assert {:ok, _backup} = Backup.delete_archive(backup)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,11 +25,12 @@ defmodule Pleroma.User.ImportTest do
|
|||
user3.nickname
|
||||
]
|
||||
|
||||
{:ok, job} = User.Import.follow_import(user1, identifiers)
|
||||
{:ok, jobs} = User.Import.follows_import(user1, identifiers)
|
||||
|
||||
for job <- jobs do
|
||||
assert {:ok, %User{}} = ObanHelpers.perform(job)
|
||||
end
|
||||
|
||||
assert {:ok, result} = ObanHelpers.perform(job)
|
||||
assert is_list(result)
|
||||
assert result == [refresh_record(user2), refresh_record(user3)]
|
||||
assert User.following?(user1, user2)
|
||||
assert User.following?(user1, user3)
|
||||
end
|
||||
|
|
@ -44,11 +45,12 @@ defmodule Pleroma.User.ImportTest do
|
|||
user3.nickname
|
||||
]
|
||||
|
||||
{:ok, job} = User.Import.blocks_import(user1, identifiers)
|
||||
{:ok, jobs} = User.Import.blocks_import(user1, identifiers)
|
||||
|
||||
for job <- jobs do
|
||||
assert {:ok, %User{}} = ObanHelpers.perform(job)
|
||||
end
|
||||
|
||||
assert {:ok, result} = ObanHelpers.perform(job)
|
||||
assert is_list(result)
|
||||
assert result == [user2, user3]
|
||||
assert User.blocks?(user1, user2)
|
||||
assert User.blocks?(user1, user3)
|
||||
end
|
||||
|
|
@ -63,11 +65,12 @@ defmodule Pleroma.User.ImportTest do
|
|||
user3.nickname
|
||||
]
|
||||
|
||||
{:ok, job} = User.Import.mutes_import(user1, identifiers)
|
||||
{:ok, jobs} = User.Import.mutes_import(user1, identifiers)
|
||||
|
||||
for job <- jobs do
|
||||
assert {:ok, %User{}} = ObanHelpers.perform(job)
|
||||
end
|
||||
|
||||
assert {:ok, result} = ObanHelpers.perform(job)
|
||||
assert is_list(result)
|
||||
assert result == [user2, user3]
|
||||
assert User.mutes?(user1, user2)
|
||||
assert User.mutes?(user1, user3)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -182,8 +182,8 @@ defmodule Pleroma.UserTest do
|
|||
locked = insert(:user, is_locked: true)
|
||||
follower = insert(:user)
|
||||
|
||||
CommonAPI.follow(follower, unlocked)
|
||||
CommonAPI.follow(follower, locked)
|
||||
CommonAPI.follow(unlocked, follower)
|
||||
CommonAPI.follow(locked, follower)
|
||||
|
||||
assert [] = User.get_follow_requests(unlocked)
|
||||
assert [activity] = User.get_follow_requests(locked)
|
||||
|
|
@ -196,9 +196,9 @@ defmodule Pleroma.UserTest do
|
|||
pending_follower = insert(:user)
|
||||
accepted_follower = insert(:user)
|
||||
|
||||
CommonAPI.follow(pending_follower, locked)
|
||||
CommonAPI.follow(pending_follower, locked)
|
||||
CommonAPI.follow(accepted_follower, locked)
|
||||
CommonAPI.follow(locked, pending_follower)
|
||||
CommonAPI.follow(locked, pending_follower)
|
||||
CommonAPI.follow(locked, accepted_follower)
|
||||
|
||||
Pleroma.FollowingRelationship.update(accepted_follower, locked, :follow_accept)
|
||||
|
||||
|
|
@ -209,7 +209,7 @@ defmodule Pleroma.UserTest do
|
|||
locked = insert(:user, is_locked: true)
|
||||
pending_follower = insert(:user, %{is_active: false})
|
||||
|
||||
CommonAPI.follow(pending_follower, locked)
|
||||
CommonAPI.follow(locked, pending_follower)
|
||||
|
||||
refute pending_follower.is_active
|
||||
assert [] = User.get_follow_requests(locked)
|
||||
|
|
@ -219,7 +219,7 @@ defmodule Pleroma.UserTest do
|
|||
followed = insert(:user, is_locked: true)
|
||||
follower = insert(:user)
|
||||
|
||||
CommonAPI.follow(follower, followed)
|
||||
CommonAPI.follow(followed, follower)
|
||||
assert [_activity] = User.get_follow_requests(followed)
|
||||
|
||||
{:ok, _user_relationship} = User.block(followed, follower)
|
||||
|
|
@ -877,109 +877,19 @@ defmodule Pleroma.UserTest do
|
|||
setup do: clear_config([Pleroma.Web.WebFinger, :update_nickname_on_user_fetch], true)
|
||||
|
||||
test "for mastodon" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{subdomain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/masto-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a/collections/featured"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
File.read!("test/fixtures/users_mock/masto_featured.json")
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
|> String.replace("{{nickname}}", "a"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
ap_id = "a@example.com"
|
||||
ap_id = "a@mastodon.example"
|
||||
{:ok, fetched_user} = User.get_or_fetch(ap_id)
|
||||
|
||||
assert fetched_user.ap_id == "https://sub.example.com/users/a"
|
||||
assert fetched_user.nickname == "a@example.com"
|
||||
assert fetched_user.ap_id == "https://sub.mastodon.example/users/a"
|
||||
assert fetched_user.nickname == "a@mastodon.example"
|
||||
end
|
||||
|
||||
test "for pleroma" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 302,
|
||||
headers: [{"location", "https://sub.example.com/.well-known/host-meta"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/host-meta"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-host-meta.xml"
|
||||
|> File.read!()
|
||||
|> String.replace("{{domain}}", "sub.example.com")
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/.well-known/webfinger?resource=acct:a@example.com"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-webfinger.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "example.com")
|
||||
|> String.replace("{{subdomain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/jrd+json"}]
|
||||
}
|
||||
|
||||
%{url: "https://sub.example.com/users/a"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
"test/fixtures/webfinger/pleroma-user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "a")
|
||||
|> String.replace("{{domain}}", "sub.example.com"),
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
ap_id = "a@example.com"
|
||||
ap_id = "a@pleroma.example"
|
||||
{:ok, fetched_user} = User.get_or_fetch(ap_id)
|
||||
|
||||
assert fetched_user.ap_id == "https://sub.example.com/users/a"
|
||||
assert fetched_user.nickname == "a@example.com"
|
||||
assert fetched_user.ap_id == "https://sub.pleroma.example/users/a"
|
||||
assert fetched_user.nickname == "a@pleroma.example"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1016,7 +926,6 @@ defmodule Pleroma.UserTest do
|
|||
assert user == fetched_user
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns nil if no user could be fetched" do
|
||||
{:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistent@social.heldscal.la")
|
||||
assert fetched_user == "not found nonexistent@social.heldscal.la"
|
||||
|
|
@ -1043,9 +952,16 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
{:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
|
||||
|
||||
assert user.inbox
|
||||
# Oban job was generated to refresh the stale user
|
||||
assert_enqueued(worker: "Pleroma.Workers.UserRefreshWorker", args: %{"ap_id" => user.ap_id})
|
||||
|
||||
refute user.last_refreshed_at == orig_user.last_refreshed_at
|
||||
# Run job to refresh the user; just capture its output instead of fetching it again
|
||||
assert {:ok, updated_user} =
|
||||
perform_job(Pleroma.Workers.UserRefreshWorker, %{"ap_id" => user.ap_id})
|
||||
|
||||
assert updated_user.inbox
|
||||
|
||||
refute updated_user.last_refreshed_at == orig_user.last_refreshed_at
|
||||
end
|
||||
|
||||
test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
|
||||
|
|
@ -1073,7 +989,6 @@ defmodule Pleroma.UserTest do
|
|||
assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it returns the old user if stale, but unfetchable" do
|
||||
a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
|
||||
|
||||
|
|
@ -1160,6 +1075,21 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
refute cs.valid?
|
||||
end
|
||||
|
||||
test "it truncates fields" do
|
||||
clear_config([:instance, :max_remote_account_fields], 2)
|
||||
|
||||
fields = [
|
||||
%{"name" => "One", "value" => "Uno"},
|
||||
%{"name" => "Two", "value" => "Dos"},
|
||||
%{"name" => "Three", "value" => "Tres"}
|
||||
]
|
||||
|
||||
cs = User.remote_user_changeset(@valid_remote |> Map.put(:fields, fields))
|
||||
|
||||
assert [%{"name" => "One", "value" => "Uno"}, %{"name" => "Two", "value" => "Dos"}] ==
|
||||
Ecto.Changeset.get_field(cs, :fields)
|
||||
end
|
||||
end
|
||||
|
||||
describe "followers and friends" do
|
||||
|
|
@ -1611,7 +1541,7 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
|
||||
|
||||
assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
|
||||
assert [%{activity | thread_muted?: CommonAPI.thread_muted?(activity, user2)}] ==
|
||||
ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
|
||||
user: user2
|
||||
})
|
||||
|
|
@ -1776,8 +1706,8 @@ defmodule Pleroma.UserTest do
|
|||
object_two = insert(:note, user: follower)
|
||||
activity_two = insert(:note_activity, user: follower, note: object_two)
|
||||
|
||||
{:ok, like} = CommonAPI.favorite(user, activity_two.id)
|
||||
{:ok, like_two} = CommonAPI.favorite(follower, activity.id)
|
||||
{:ok, like} = CommonAPI.favorite(activity_two.id, user)
|
||||
{:ok, like_two} = CommonAPI.favorite(activity.id, follower)
|
||||
{:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
|
||||
|
||||
{:ok, job} = User.delete(user)
|
||||
|
|
@ -2894,6 +2824,20 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "get_familiar_followers/3" do
|
||||
test "returns familiar followers for a pair of users" do
|
||||
user1 = insert(:user)
|
||||
%{id: id2} = user2 = insert(:user)
|
||||
user3 = insert(:user)
|
||||
_user4 = insert(:user)
|
||||
|
||||
User.follow(user1, user2)
|
||||
User.follow(user2, user3)
|
||||
|
||||
assert [%{id: ^id2}] = User.get_familiar_followers(user3, user1)
|
||||
end
|
||||
end
|
||||
|
||||
describe "account endorsements" do
|
||||
test "it pins people" do
|
||||
user = insert(:user)
|
||||
|
|
@ -2975,4 +2919,74 @@ defmodule Pleroma.UserTest do
|
|||
|
||||
assert [%{"verified_at" => ^verified_at}] = user.fields
|
||||
end
|
||||
|
||||
describe "follow_hashtag/2" do
|
||||
test "should follow a hashtag" do
|
||||
user = insert(:user)
|
||||
hashtag = insert(:hashtag)
|
||||
|
||||
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
|
||||
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
|
||||
assert user.followed_hashtags |> Enum.count() == 1
|
||||
assert hashtag.name in Enum.map(user.followed_hashtags, fn %{name: name} -> name end)
|
||||
end
|
||||
|
||||
test "should not follow a hashtag twice" do
|
||||
user = insert(:user)
|
||||
hashtag = insert(:hashtag)
|
||||
|
||||
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
|
||||
|
||||
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
|
||||
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
|
||||
assert user.followed_hashtags |> Enum.count() == 1
|
||||
assert hashtag.name in Enum.map(user.followed_hashtags, fn %{name: name} -> name end)
|
||||
end
|
||||
|
||||
test "can follow multiple hashtags" do
|
||||
user = insert(:user)
|
||||
hashtag = insert(:hashtag)
|
||||
other_hashtag = insert(:hashtag)
|
||||
|
||||
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
|
||||
assert {:ok, _} = user |> User.follow_hashtag(other_hashtag)
|
||||
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
|
||||
assert user.followed_hashtags |> Enum.count() == 2
|
||||
assert hashtag.name in Enum.map(user.followed_hashtags, fn %{name: name} -> name end)
|
||||
assert other_hashtag.name in Enum.map(user.followed_hashtags, fn %{name: name} -> name end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "unfollow_hashtag/2" do
|
||||
test "should unfollow a hashtag" do
|
||||
user = insert(:user)
|
||||
hashtag = insert(:hashtag)
|
||||
|
||||
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
|
||||
assert {:ok, _} = user |> User.unfollow_hashtag(hashtag)
|
||||
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
|
||||
assert user.followed_hashtags |> Enum.count() == 0
|
||||
end
|
||||
|
||||
test "should not error when trying to unfollow a hashtag twice" do
|
||||
user = insert(:user)
|
||||
hashtag = insert(:hashtag)
|
||||
|
||||
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
|
||||
assert {:ok, _} = user |> User.unfollow_hashtag(hashtag)
|
||||
assert {:ok, _} = user |> User.unfollow_hashtag(hashtag)
|
||||
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
|
||||
assert user.followed_hashtags |> Enum.count() == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -573,7 +573,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert Activity.get_by_ap_id(data["id"])
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it inserts an incoming activity into the database" <>
|
||||
"even if we can't fetch the user but have it in our db",
|
||||
%{conn: conn} do
|
||||
|
|
@ -657,9 +656,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert_receive {:mix_shell, :info, ["https://relay.mastodon.host/actor"]}
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "without valid signature, " <>
|
||||
"it only accepts Create activities and requires enabled federation",
|
||||
"it accepts Create activities and requires enabled federation",
|
||||
%{conn: conn} do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
||||
non_create_data = File.read!("test/fixtures/mastodon-announce.json") |> Jason.decode!()
|
||||
|
|
@ -686,6 +684,54 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|> json_response(400)
|
||||
end
|
||||
|
||||
# When activity is delivered to the inbox and we cannot immediately verify signature
|
||||
# we capture all the params and process it later in the Oban job.
|
||||
# Once we begin processing it through Oban we risk fetching the actor to validate the
|
||||
# activity which just leads to inserting a new user to process a Delete not relevant to us.
|
||||
test "Activities of certain types from an unknown actor are discarded", %{conn: conn} do
|
||||
example_bad_types =
|
||||
Pleroma.Constants.activity_types() --
|
||||
Pleroma.Constants.allowed_activity_types_from_strangers()
|
||||
|
||||
Enum.each(example_bad_types, fn bad_type ->
|
||||
params =
|
||||
%{
|
||||
"type" => bad_type,
|
||||
"actor" => "https://unknown.mastodon.instance/users/somebody"
|
||||
}
|
||||
|> Jason.encode!()
|
||||
|
||||
conn
|
||||
|> assign(:valid_signature, false)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/inbox", params)
|
||||
|> json_response(400)
|
||||
|
||||
assert all_enqueued() == []
|
||||
end)
|
||||
end
|
||||
|
||||
test "Unknown activity types are discarded", %{conn: conn} do
|
||||
unknown_types = ["Poke", "Read", "Dazzle"]
|
||||
|
||||
Enum.each(unknown_types, fn bad_type ->
|
||||
params =
|
||||
%{
|
||||
"type" => bad_type,
|
||||
"actor" => "https://unknown.mastodon.instance/users/somebody"
|
||||
}
|
||||
|> Jason.encode!()
|
||||
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/inbox", params)
|
||||
|> json_response(400)
|
||||
|
||||
assert all_enqueued() == []
|
||||
end)
|
||||
end
|
||||
|
||||
test "accepts Add/Remove activities", %{conn: conn} do
|
||||
object_id = "c61d6733-e256-4fe1-ab13-1e369789423f"
|
||||
|
||||
|
|
@ -1080,7 +1126,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert Instances.reachable?(sender_host)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it removes all follower collections but actor's", %{conn: conn} do
|
||||
[actor, recipient] = insert_pair(:user)
|
||||
|
||||
|
|
@ -1143,7 +1188,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert json_response(ret_conn, 200)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "forwarded report", %{conn: conn} do
|
||||
admin = insert(:user, is_admin: true)
|
||||
actor = insert(:user, local: false)
|
||||
|
|
@ -1219,7 +1263,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "forwarded report from mastodon", %{conn: conn} do
|
||||
admin = insert(:user, is_admin: true)
|
||||
actor = insert(:user, local: false)
|
||||
|
|
@ -1229,7 +1272,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|
||||
note = insert(:note_activity, user: reported_user)
|
||||
|
||||
Pleroma.Web.CommonAPI.favorite(another, note.id)
|
||||
Pleroma.Web.CommonAPI.favorite(note.id, another)
|
||||
|
||||
mock_json_body =
|
||||
"test/fixtures/mastodon/application_actor.json"
|
||||
|
|
@ -1277,6 +1320,27 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
html_body: ~r/#{note.data["object"]}/i
|
||||
)
|
||||
end
|
||||
|
||||
test "it accepts an incoming Block", %{conn: conn, data: data} do
|
||||
user = insert(:user)
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("type", "Block")
|
||||
|> Map.put("to", [user.ap_id])
|
||||
|> Map.put("cc", [])
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:valid_signature, true)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/users/#{user.nickname}/inbox", data)
|
||||
|
||||
assert "ok" == json_response(conn, 200)
|
||||
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||
assert Activity.get_by_ap_id(data["id"])
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /users/:nickname/outbox" do
|
||||
|
|
@ -1407,7 +1471,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
|
||||
assert question = Object.normalize(activity, fetch: false)
|
||||
|
||||
{:ok, [activity], _object} = CommonAPI.vote(voter, question, [1])
|
||||
{:ok, [activity], _object} = CommonAPI.vote(question, voter, [1])
|
||||
|
||||
assert outbox_get =
|
||||
conn
|
||||
|
|
@ -1580,6 +1644,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
assert json_response(conn, 403)
|
||||
end
|
||||
|
||||
test "it rejects update activity of object from other actor", %{conn: conn} do
|
||||
note_activity = insert(:note_activity)
|
||||
note_object = Object.normalize(note_activity, fetch: false)
|
||||
user = insert(:user)
|
||||
|
||||
data = %{
|
||||
type: "Update",
|
||||
object: %{
|
||||
id: note_object.data["id"]
|
||||
}
|
||||
}
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> put_req_header("content-type", "application/activity+json")
|
||||
|> post("/users/#{user.nickname}/outbox", data)
|
||||
|
||||
assert json_response(conn, 400)
|
||||
assert note_object == Object.normalize(note_activity, fetch: false)
|
||||
end
|
||||
|
||||
test "it increases like count when receiving a like action", %{conn: conn} do
|
||||
note_activity = insert(:note_activity)
|
||||
note_object = Object.normalize(note_activity, fetch: false)
|
||||
|
|
@ -1752,7 +1838,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
%{conn: conn} do
|
||||
user = insert(:user, hide_followers: true)
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|
|
@ -1848,7 +1934,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
|||
%{conn: conn} do
|
||||
user = insert(:user, hide_follows: true)
|
||||
other_user = insert(:user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -232,12 +232,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
|
||||
assert user.avatar == %{
|
||||
"type" => "Image",
|
||||
"url" => [%{"href" => "https://jk.nipponalba.scot/images/profile.jpg"}]
|
||||
"url" => [%{"href" => "https://jk.nipponalba.scot/images/profile.jpg"}],
|
||||
"name" => "profile picture"
|
||||
}
|
||||
|
||||
assert user.banner == %{
|
||||
"type" => "Image",
|
||||
"url" => [%{"href" => "https://jk.nipponalba.scot/images/profile.jpg"}]
|
||||
"url" => [%{"href" => "https://jk.nipponalba.scot/images/profile.jpg"}],
|
||||
"name" => "profile picture"
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -291,9 +293,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
body: featured_data,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
Tesla.Mock.mock_global(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: ^object_url
|
||||
|
|
@ -306,7 +306,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end)
|
||||
|
||||
{:ok, user} = ActivityPub.make_user_from_ap_id(ap_id)
|
||||
Process.sleep(50)
|
||||
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.RemoteFetcherWorker,
|
||||
args: %{
|
||||
"op" => "fetch_remote",
|
||||
"id" => object_url,
|
||||
"depth" => 1
|
||||
}
|
||||
)
|
||||
|
||||
# wait for oban
|
||||
Pleroma.Tests.ObanHelpers.perform_all()
|
||||
|
||||
assert user.featured_address == featured_url
|
||||
assert Map.has_key?(user.pinned_objects, object_url)
|
||||
|
|
@ -368,9 +379,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
body: featured_data,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
Tesla.Mock.mock_global(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: ^object_url
|
||||
|
|
@ -383,7 +392,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end)
|
||||
|
||||
{:ok, user} = ActivityPub.make_user_from_ap_id(ap_id)
|
||||
Process.sleep(50)
|
||||
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.RemoteFetcherWorker,
|
||||
args: %{
|
||||
"op" => "fetch_remote",
|
||||
"id" => object_url,
|
||||
"depth" => 1
|
||||
}
|
||||
)
|
||||
|
||||
# wait for oban
|
||||
Pleroma.Tests.ObanHelpers.perform_all()
|
||||
|
||||
assert user.featured_address == featured_url
|
||||
assert Map.has_key?(user.pinned_objects, object_url)
|
||||
|
|
@ -414,6 +434,35 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
|
||||
assert user.birthday == ~D[2001-02-12]
|
||||
end
|
||||
|
||||
test "fetches avatar description" do
|
||||
user_id = "https://example.com/users/marcin"
|
||||
|
||||
user_data =
|
||||
"test/fixtures/users_mock/user.json"
|
||||
|> File.read!()
|
||||
|> String.replace("{{nickname}}", "marcin")
|
||||
|> Jason.decode!()
|
||||
|> Map.delete("featured")
|
||||
|> Map.update("icon", %{}, fn image -> Map.put(image, "name", "image description") end)
|
||||
|> Jason.encode!()
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: ^user_id
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: user_data,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
{:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
|
||||
|
||||
assert user.avatar["name"] == "image description"
|
||||
end
|
||||
end
|
||||
|
||||
test "it fetches the appropriate tag-restricted posts" do
|
||||
|
|
@ -818,6 +867,33 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "fetch activities for followed hashtags" do
|
||||
test "it should return public activities that reference a given hashtag" do
|
||||
hashtag = insert(:hashtag, name: "tenshi")
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, normally_visible} =
|
||||
CommonAPI.post(other_user, %{status: "hello :)", visibility: "public"})
|
||||
|
||||
{:ok, public} = CommonAPI.post(user, %{status: "maji #tenshi", visibility: "public"})
|
||||
{:ok, _unrelated} = CommonAPI.post(user, %{status: "dai #tensh", visibility: "public"})
|
||||
{:ok, unlisted} = CommonAPI.post(user, %{status: "maji #tenshi", visibility: "unlisted"})
|
||||
{:ok, _private} = CommonAPI.post(user, %{status: "maji #tenshi", visibility: "private"})
|
||||
|
||||
activities =
|
||||
ActivityPub.fetch_activities([other_user.follower_address], %{
|
||||
followed_hashtags: [hashtag.id]
|
||||
})
|
||||
|
||||
assert length(activities) == 3
|
||||
normal_id = normally_visible.id
|
||||
public_id = public.id
|
||||
unlisted_id = unlisted.id
|
||||
assert [%{id: ^normal_id}, %{id: ^public_id}, %{id: ^unlisted_id}] = activities
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch activities in context" do
|
||||
test "retrieves activities that have a given context" do
|
||||
{:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
|
||||
|
|
@ -1020,7 +1096,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
refute activity in activities
|
||||
|
||||
followed_user = insert(:user)
|
||||
CommonAPI.follow(user, followed_user)
|
||||
CommonAPI.follow(followed_user, user)
|
||||
{:ok, repeat_activity} = CommonAPI.repeat(activity.id, followed_user)
|
||||
|
||||
activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true})
|
||||
|
|
@ -1153,7 +1229,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
note_two = insert(:note, data: %{"context" => "suya.."})
|
||||
activity_two = insert(:note_activity, note: note_two)
|
||||
|
||||
{:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
|
||||
{:ok, _activity_two} = CommonAPI.add_mute(activity_two, user)
|
||||
|
||||
assert [_activity_one] = ActivityPub.fetch_activities([], %{muting_user: user})
|
||||
end
|
||||
|
|
@ -1164,7 +1240,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
note_two = insert(:note, data: %{"context" => "suya.."})
|
||||
activity_two = insert(:note_activity, note: note_two)
|
||||
|
||||
{:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
|
||||
{:ok, _activity_two} = CommonAPI.add_mute(activity_two, user)
|
||||
|
||||
assert [_activity_two, _activity_one] =
|
||||
ActivityPub.fetch_activities([], %{muting_user: user, with_muted: true})
|
||||
|
|
@ -1340,7 +1416,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
activity = insert(:note_activity)
|
||||
user = insert(:user)
|
||||
booster = insert(:user)
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, booster)
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(booster, user)
|
||||
|
||||
{:ok, activity} = CommonAPI.repeat(activity.id, booster)
|
||||
|
||||
|
|
@ -1353,8 +1429,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
activity = insert(:note_activity)
|
||||
user = insert(:user)
|
||||
booster = insert(:user)
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, booster)
|
||||
{:ok, _reblog_mute} = CommonAPI.show_reblogs(user, booster)
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(booster, user)
|
||||
{:ok, _reblog_mute} = CommonAPI.show_reblogs(booster, user)
|
||||
|
||||
{:ok, activity} = CommonAPI.repeat(activity.id, booster)
|
||||
|
||||
|
|
@ -1434,7 +1510,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
follower = insert(:user)
|
||||
followed = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(followed, follower)
|
||||
|
||||
with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
|
||||
assert {:error, :reverted} = ActivityPub.unfollow(follower, followed)
|
||||
|
|
@ -1451,7 +1527,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
follower = insert(:user)
|
||||
followed = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(followed, follower)
|
||||
{:ok, activity} = ActivityPub.unfollow(follower, followed)
|
||||
|
||||
assert activity.data["type"] == "Undo"
|
||||
|
|
@ -1468,7 +1544,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
follower = insert(:user)
|
||||
followed = insert(:user, %{is_locked: true})
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(followed, follower)
|
||||
{:ok, activity} = ActivityPub.unfollow(follower, followed)
|
||||
|
||||
assert activity.data["type"] == "Undo"
|
||||
|
|
@ -1836,14 +1912,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
{:ok, a4} = CommonAPI.post(user2, %{status: "Agent Smith "})
|
||||
{:ok, a5} = CommonAPI.post(user1, %{status: "Red or Blue "})
|
||||
|
||||
{:ok, _} = CommonAPI.favorite(user, a4.id)
|
||||
{:ok, _} = CommonAPI.favorite(other_user, a3.id)
|
||||
{:ok, _} = CommonAPI.favorite(user, a3.id)
|
||||
{:ok, _} = CommonAPI.favorite(other_user, a5.id)
|
||||
{:ok, _} = CommonAPI.favorite(user, a5.id)
|
||||
{:ok, _} = CommonAPI.favorite(other_user, a4.id)
|
||||
{:ok, _} = CommonAPI.favorite(user, a1.id)
|
||||
{:ok, _} = CommonAPI.favorite(other_user, a1.id)
|
||||
{:ok, _} = CommonAPI.favorite(a4.id, user)
|
||||
{:ok, _} = CommonAPI.favorite(a3.id, other_user)
|
||||
{:ok, _} = CommonAPI.favorite(a3.id, user)
|
||||
{:ok, _} = CommonAPI.favorite(a5.id, other_user)
|
||||
{:ok, _} = CommonAPI.favorite(a5.id, user)
|
||||
{:ok, _} = CommonAPI.favorite(a4.id, other_user)
|
||||
{:ok, _} = CommonAPI.favorite(a1.id, user)
|
||||
{:ok, _} = CommonAPI.favorite(a1.id, other_user)
|
||||
result = ActivityPub.fetch_favourites(user)
|
||||
|
||||
assert Enum.map(result, & &1.id) == [a1.id, a5.id, a3.id, a4.id]
|
||||
|
|
@ -2687,7 +2763,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
assert user.name == " "
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "pin_data_from_featured_collection will ignore unsupported values" do
|
||||
assert %{} ==
|
||||
ActivityPub.pin_data_from_featured_collection(%{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
alias Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicy
|
||||
|
||||
test "it allows posts without mentions" do
|
||||
user = insert(:user, local: false)
|
||||
assert user.note_count == 0
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
{:ok, _message} = AntiMentionSpamPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it allows posts from users with followers, posts, and age" do
|
||||
user =
|
||||
insert(:user,
|
||||
local: false,
|
||||
follower_count: 1,
|
||||
note_count: 1,
|
||||
inserted_at: ~N[1970-01-01 00:00:00]
|
||||
)
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
{:ok, _message} = AntiMentionSpamPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it allows posts from local users" do
|
||||
user = insert(:user, local: true)
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
{:ok, _message} = AntiMentionSpamPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "it rejects posts with mentions from users without followers" do
|
||||
user = insert(:user, local: false, follower_count: 0)
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"actor" => user.ap_id,
|
||||
"object" => %{
|
||||
"to" => ["https://pleroma.soykaf.com/users/1"],
|
||||
"cc" => ["https://pleroma.soykaf.com/users/1"],
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
}
|
||||
|
||||
{:reject, _message} = AntiMentionSpamPolicy.filter(message)
|
||||
end
|
||||
end
|
||||
117
test/pleroma/web/activity_pub/mrf/fo_direct_reply_test.exs
Normal file
117
test/pleroma/web/activity_pub/mrf/fo_direct_reply_test.exs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.FODirectReplyTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.MRF.FODirectReply
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
test "replying to followers-only/private is changed to direct" do
|
||||
batman = insert(:user, nickname: "batman")
|
||||
robin = insert(:user, nickname: "robin")
|
||||
|
||||
{:ok, post} =
|
||||
CommonAPI.post(batman, %{
|
||||
status: "Has anyone seen Selina Kyle's latest selfies?",
|
||||
visibility: "private"
|
||||
})
|
||||
|
||||
reply = %{
|
||||
"type" => "Create",
|
||||
"actor" => robin.ap_id,
|
||||
"to" => [batman.ap_id, robin.follower_address],
|
||||
"cc" => [],
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"actor" => robin.ap_id,
|
||||
"content" => "@batman 🤤 ❤️ 🐈⬛",
|
||||
"to" => [batman.ap_id, robin.follower_address],
|
||||
"cc" => [],
|
||||
"inReplyTo" => Object.normalize(post).data["id"]
|
||||
}
|
||||
}
|
||||
|
||||
expected_to = [batman.ap_id]
|
||||
expected_cc = []
|
||||
|
||||
assert {:ok, filtered} = FODirectReply.filter(reply)
|
||||
|
||||
assert expected_to == filtered["to"]
|
||||
assert expected_cc == filtered["cc"]
|
||||
assert expected_to == filtered["object"]["to"]
|
||||
assert expected_cc == filtered["object"]["cc"]
|
||||
end
|
||||
|
||||
test "replies to unlisted posts are unmodified" do
|
||||
batman = insert(:user, nickname: "batman")
|
||||
robin = insert(:user, nickname: "robin")
|
||||
|
||||
{:ok, post} =
|
||||
CommonAPI.post(batman, %{
|
||||
status: "Has anyone seen Selina Kyle's latest selfies?",
|
||||
visibility: "unlisted"
|
||||
})
|
||||
|
||||
reply = %{
|
||||
"type" => "Create",
|
||||
"actor" => robin.ap_id,
|
||||
"to" => [batman.ap_id, robin.follower_address],
|
||||
"cc" => [],
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"actor" => robin.ap_id,
|
||||
"content" => "@batman 🤤 ❤️ 🐈<200d>⬛",
|
||||
"to" => [batman.ap_id, robin.follower_address],
|
||||
"cc" => [],
|
||||
"inReplyTo" => Object.normalize(post).data["id"]
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, filtered} = FODirectReply.filter(reply)
|
||||
|
||||
assert match?(^filtered, reply)
|
||||
end
|
||||
|
||||
test "replies to public posts are unmodified" do
|
||||
batman = insert(:user, nickname: "batman")
|
||||
robin = insert(:user, nickname: "robin")
|
||||
|
||||
{:ok, post} =
|
||||
CommonAPI.post(batman, %{status: "Has anyone seen Selina Kyle's latest selfies?"})
|
||||
|
||||
reply = %{
|
||||
"type" => "Create",
|
||||
"actor" => robin.ap_id,
|
||||
"to" => [batman.ap_id, robin.follower_address],
|
||||
"cc" => [],
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"actor" => robin.ap_id,
|
||||
"content" => "@batman 🤤 ❤️ 🐈<200d>⬛",
|
||||
"to" => [batman.ap_id, robin.follower_address],
|
||||
"cc" => [],
|
||||
"inReplyTo" => Object.normalize(post).data["id"]
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, filtered} = FODirectReply.filter(reply)
|
||||
|
||||
assert match?(^filtered, reply)
|
||||
end
|
||||
|
||||
test "non-reply posts are unmodified" do
|
||||
batman = insert(:user, nickname: "batman")
|
||||
|
||||
{:ok, post} = CommonAPI.post(batman, %{status: "To the Batmobile!"})
|
||||
|
||||
assert {:ok, filtered} = FODirectReply.filter(post)
|
||||
|
||||
assert match?(^filtered, post)
|
||||
end
|
||||
end
|
||||
267
test/pleroma/web/activity_pub/mrf/nsfw_api_policy_test.exs
Normal file
267
test/pleroma/web/activity_pub/mrf/nsfw_api_policy_test.exs
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicyTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Constants
|
||||
alias Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
@policy :mrf_nsfw_api
|
||||
|
||||
@sfw_url "https://kittens.co/kitty.gif"
|
||||
@nsfw_url "https://b00bies.com/nsfw.jpg"
|
||||
@timeout_url "http://time.out/i.jpg"
|
||||
|
||||
setup_all do
|
||||
clear_config(@policy,
|
||||
url: "http://127.0.0.1:5000/",
|
||||
threshold: 0.7,
|
||||
mark_sensitive: true,
|
||||
unlist: false,
|
||||
reject: false
|
||||
)
|
||||
end
|
||||
|
||||
setup do
|
||||
Tesla.Mock.mock(fn
|
||||
# NSFW URL
|
||||
%{method: :get, url: "http://127.0.0.1:5000/?url=#{@nsfw_url}"} ->
|
||||
%Tesla.Env{status: 200, body: ~s({"score":0.99772077798843384,"url":"#{@nsfw_url}"})}
|
||||
|
||||
# SFW URL
|
||||
%{method: :get, url: "http://127.0.0.1:5000/?url=#{@sfw_url}"} ->
|
||||
%Tesla.Env{status: 200, body: ~s({"score":0.00011714912398019806,"url":"#{@sfw_url}"})}
|
||||
|
||||
# Timeout URL
|
||||
%{method: :get, url: "http://127.0.0.1:5000/?url=#{@timeout_url}"} ->
|
||||
{:error, :timeout}
|
||||
|
||||
# Fallback URL
|
||||
%{method: :get, url: "http://127.0.0.1:5000/?url=" <> url} ->
|
||||
body =
|
||||
~s({"error_code":500,"error_reason":"[Errno -2] Name or service not known","url":"#{url}"})
|
||||
|
||||
%Tesla.Env{status: 500, body: body}
|
||||
end)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "build_request_url/1" do
|
||||
test "it works" do
|
||||
expected = "http://127.0.0.1:5000/?url=https://b00bies.com/nsfw.jpg"
|
||||
assert NsfwApiPolicy.build_request_url(@nsfw_url) == expected
|
||||
end
|
||||
|
||||
test "it adds a trailing slash" do
|
||||
clear_config([@policy, :url], "http://localhost:5000")
|
||||
|
||||
expected = "http://localhost:5000/?url=https://b00bies.com/nsfw.jpg"
|
||||
assert NsfwApiPolicy.build_request_url(@nsfw_url) == expected
|
||||
end
|
||||
|
||||
test "it adds a trailing slash preserving the path" do
|
||||
clear_config([@policy, :url], "http://localhost:5000/nsfw_api")
|
||||
|
||||
expected = "http://localhost:5000/nsfw_api/?url=https://b00bies.com/nsfw.jpg"
|
||||
assert NsfwApiPolicy.build_request_url(@nsfw_url) == expected
|
||||
end
|
||||
end
|
||||
|
||||
describe "parse_url/1" do
|
||||
test "returns decoded JSON from the API server" do
|
||||
expected = %{"score" => 0.99772077798843384, "url" => @nsfw_url}
|
||||
assert NsfwApiPolicy.parse_url(@nsfw_url) == {:ok, expected}
|
||||
end
|
||||
|
||||
test "warns when the API server fails" do
|
||||
expected = "[NsfwApiPolicy]: The API server failed. Skipping."
|
||||
assert capture_log(fn -> NsfwApiPolicy.parse_url(@timeout_url) end) =~ expected
|
||||
end
|
||||
|
||||
test "returns {:error, _} tuple when the API server fails" do
|
||||
capture_log(fn ->
|
||||
assert {:error, _} = NsfwApiPolicy.parse_url(@timeout_url)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "check_url_nsfw/1" do
|
||||
test "returns {:nsfw, _} tuple" do
|
||||
expected = {:nsfw, %{url: @nsfw_url, score: 0.99772077798843384, threshold: 0.7}}
|
||||
assert NsfwApiPolicy.check_url_nsfw(@nsfw_url) == expected
|
||||
end
|
||||
|
||||
test "returns {:sfw, _} tuple" do
|
||||
expected = {:sfw, %{url: @sfw_url, score: 0.00011714912398019806, threshold: 0.7}}
|
||||
assert NsfwApiPolicy.check_url_nsfw(@sfw_url) == expected
|
||||
end
|
||||
|
||||
test "returns {:sfw, _} on failure" do
|
||||
expected = {:sfw, %{url: @timeout_url, score: nil, threshold: 0.7}}
|
||||
|
||||
capture_log(fn ->
|
||||
assert NsfwApiPolicy.check_url_nsfw(@timeout_url) == expected
|
||||
end)
|
||||
end
|
||||
|
||||
test "works with map URL" do
|
||||
expected = {:nsfw, %{url: @nsfw_url, score: 0.99772077798843384, threshold: 0.7}}
|
||||
assert NsfwApiPolicy.check_url_nsfw(%{"href" => @nsfw_url}) == expected
|
||||
end
|
||||
end
|
||||
|
||||
describe "check_attachment_nsfw/1" do
|
||||
test "returns {:nsfw, _} if any items are NSFW" do
|
||||
attachment = %{"url" => [%{"href" => @nsfw_url}, @nsfw_url, @sfw_url]}
|
||||
assert NsfwApiPolicy.check_attachment_nsfw(attachment) == {:nsfw, attachment}
|
||||
end
|
||||
|
||||
test "returns {:sfw, _} if all items are SFW" do
|
||||
attachment = %{"url" => [%{"href" => @sfw_url}, @sfw_url, @sfw_url]}
|
||||
assert NsfwApiPolicy.check_attachment_nsfw(attachment) == {:sfw, attachment}
|
||||
end
|
||||
|
||||
test "works with binary URL" do
|
||||
attachment = %{"url" => @nsfw_url}
|
||||
assert NsfwApiPolicy.check_attachment_nsfw(attachment) == {:nsfw, attachment}
|
||||
end
|
||||
end
|
||||
|
||||
describe "check_object_nsfw/1" do
|
||||
test "returns {:nsfw, _} if any items are NSFW" do
|
||||
object = %{"attachment" => [%{"url" => [%{"href" => @nsfw_url}, @sfw_url]}]}
|
||||
assert NsfwApiPolicy.check_object_nsfw(object) == {:nsfw, object}
|
||||
end
|
||||
|
||||
test "returns {:sfw, _} if all items are SFW" do
|
||||
object = %{"attachment" => [%{"url" => [%{"href" => @sfw_url}, @sfw_url]}]}
|
||||
assert NsfwApiPolicy.check_object_nsfw(object) == {:sfw, object}
|
||||
end
|
||||
|
||||
test "works with embedded object" do
|
||||
object = %{"object" => %{"attachment" => [%{"url" => [%{"href" => @nsfw_url}, @sfw_url]}]}}
|
||||
assert NsfwApiPolicy.check_object_nsfw(object) == {:nsfw, object}
|
||||
end
|
||||
end
|
||||
|
||||
describe "unlist/1" do
|
||||
test "unlist addressing" do
|
||||
user = insert(:user)
|
||||
|
||||
object = %{
|
||||
"to" => [Constants.as_public()],
|
||||
"cc" => [user.follower_address, "https://hello.world/users/alex"],
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
expected = %{
|
||||
"to" => [user.follower_address],
|
||||
"cc" => [Constants.as_public(), "https://hello.world/users/alex"],
|
||||
"actor" => user.ap_id
|
||||
}
|
||||
|
||||
assert NsfwApiPolicy.unlist(object) == expected
|
||||
end
|
||||
|
||||
test "raise if user isn't found" do
|
||||
object = %{
|
||||
"to" => [Constants.as_public()],
|
||||
"cc" => [],
|
||||
"actor" => "https://hello.world/users/alex"
|
||||
}
|
||||
|
||||
assert_raise(RuntimeError, fn ->
|
||||
NsfwApiPolicy.unlist(object)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
describe "mark_sensitive/1" do
|
||||
test "adds nsfw tag and marks sensitive" do
|
||||
object = %{"tag" => ["yolo"]}
|
||||
expected = %{"tag" => ["yolo", "nsfw"], "sensitive" => true}
|
||||
assert NsfwApiPolicy.mark_sensitive(object) == expected
|
||||
end
|
||||
|
||||
test "works with embedded object" do
|
||||
object = %{"object" => %{"tag" => ["yolo"]}}
|
||||
expected = %{"object" => %{"tag" => ["yolo", "nsfw"], "sensitive" => true}}
|
||||
assert NsfwApiPolicy.mark_sensitive(object) == expected
|
||||
end
|
||||
end
|
||||
|
||||
describe "filter/1" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
||||
nsfw_object = %{
|
||||
"to" => [Constants.as_public()],
|
||||
"cc" => [user.follower_address],
|
||||
"actor" => user.ap_id,
|
||||
"attachment" => [%{"url" => @nsfw_url}]
|
||||
}
|
||||
|
||||
sfw_object = %{
|
||||
"to" => [Constants.as_public()],
|
||||
"cc" => [user.follower_address],
|
||||
"actor" => user.ap_id,
|
||||
"attachment" => [%{"url" => @sfw_url}]
|
||||
}
|
||||
|
||||
%{user: user, nsfw_object: nsfw_object, sfw_object: sfw_object}
|
||||
end
|
||||
|
||||
test "passes SFW object through", %{sfw_object: object} do
|
||||
{:ok, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "passes NSFW object through when actions are disabled", %{nsfw_object: object} do
|
||||
clear_config([@policy, :mark_sensitive], false)
|
||||
clear_config([@policy, :unlist], false)
|
||||
clear_config([@policy, :reject], false)
|
||||
{:ok, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "passes NSFW object through when :threshold is 1", %{nsfw_object: object} do
|
||||
clear_config([@policy, :reject], true)
|
||||
clear_config([@policy, :threshold], 1)
|
||||
{:ok, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "rejects SFW object through when :threshold is 0", %{sfw_object: object} do
|
||||
clear_config([@policy, :reject], true)
|
||||
clear_config([@policy, :threshold], 0)
|
||||
{:reject, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "rejects NSFW when :reject is enabled", %{nsfw_object: object} do
|
||||
clear_config([@policy, :reject], true)
|
||||
{:reject, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "passes NSFW through when :reject is disabled", %{nsfw_object: object} do
|
||||
clear_config([@policy, :reject], false)
|
||||
{:ok, _} = NsfwApiPolicy.filter(object)
|
||||
end
|
||||
|
||||
test "unlists NSFW when :unlist is enabled", %{user: user, nsfw_object: object} do
|
||||
clear_config([@policy, :unlist], true)
|
||||
{:ok, object} = NsfwApiPolicy.filter(object)
|
||||
assert object["to"] == [user.follower_address]
|
||||
end
|
||||
|
||||
test "passes NSFW through when :unlist is disabled", %{nsfw_object: object} do
|
||||
clear_config([@policy, :unlist], false)
|
||||
{:ok, object} = NsfwApiPolicy.filter(object)
|
||||
assert object["to"] == [Constants.as_public()]
|
||||
end
|
||||
end
|
||||
end
|
||||
140
test/pleroma/web/activity_pub/mrf/quiet_reply_test.exs
Normal file
140
test/pleroma/web/activity_pub/mrf/quiet_reply_test.exs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.QuietReplyTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.MRF.QuietReply
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
test "replying to public post is forced to be quiet" do
|
||||
batman = insert(:user, nickname: "batman")
|
||||
robin = insert(:user, nickname: "robin")
|
||||
|
||||
{:ok, post} = CommonAPI.post(batman, %{status: "To the Batmobile!"})
|
||||
|
||||
reply = %{
|
||||
"type" => "Create",
|
||||
"actor" => robin.ap_id,
|
||||
"to" => [
|
||||
batman.ap_id,
|
||||
Pleroma.Constants.as_public()
|
||||
],
|
||||
"cc" => [robin.follower_address],
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"actor" => robin.ap_id,
|
||||
"content" => "@batman Wait up, I forgot my spandex!",
|
||||
"to" => [
|
||||
batman.ap_id,
|
||||
Pleroma.Constants.as_public()
|
||||
],
|
||||
"cc" => [robin.follower_address],
|
||||
"inReplyTo" => Object.normalize(post).data["id"]
|
||||
}
|
||||
}
|
||||
|
||||
expected_to = [batman.ap_id, robin.follower_address]
|
||||
expected_cc = [Pleroma.Constants.as_public()]
|
||||
|
||||
assert {:ok, filtered} = QuietReply.filter(reply)
|
||||
|
||||
assert expected_to == filtered["to"]
|
||||
assert expected_cc == filtered["cc"]
|
||||
assert expected_to == filtered["object"]["to"]
|
||||
assert expected_cc == filtered["object"]["cc"]
|
||||
end
|
||||
|
||||
test "replying to unlisted post is unmodified" do
|
||||
batman = insert(:user, nickname: "batman")
|
||||
robin = insert(:user, nickname: "robin")
|
||||
|
||||
{:ok, post} = CommonAPI.post(batman, %{status: "To the Batmobile!", visibility: "private"})
|
||||
|
||||
reply = %{
|
||||
"type" => "Create",
|
||||
"actor" => robin.ap_id,
|
||||
"to" => [batman.ap_id],
|
||||
"cc" => [],
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"actor" => robin.ap_id,
|
||||
"content" => "@batman Wait up, I forgot my spandex!",
|
||||
"to" => [batman.ap_id],
|
||||
"cc" => [],
|
||||
"inReplyTo" => Object.normalize(post).data["id"]
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, filtered} = QuietReply.filter(reply)
|
||||
|
||||
assert match?(^filtered, reply)
|
||||
end
|
||||
|
||||
test "replying direct is unmodified" do
|
||||
batman = insert(:user, nickname: "batman")
|
||||
robin = insert(:user, nickname: "robin")
|
||||
|
||||
{:ok, post} = CommonAPI.post(batman, %{status: "To the Batmobile!"})
|
||||
|
||||
reply = %{
|
||||
"type" => "Create",
|
||||
"actor" => robin.ap_id,
|
||||
"to" => [batman.ap_id],
|
||||
"cc" => [],
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"actor" => robin.ap_id,
|
||||
"content" => "@batman Wait up, I forgot my spandex!",
|
||||
"to" => [batman.ap_id],
|
||||
"cc" => [],
|
||||
"inReplyTo" => Object.normalize(post).data["id"]
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, filtered} = QuietReply.filter(reply)
|
||||
|
||||
assert match?(^filtered, reply)
|
||||
end
|
||||
|
||||
test "replying followers-only is unmodified" do
|
||||
batman = insert(:user, nickname: "batman")
|
||||
robin = insert(:user, nickname: "robin")
|
||||
|
||||
{:ok, post} = CommonAPI.post(batman, %{status: "To the Batmobile!"})
|
||||
|
||||
reply = %{
|
||||
"type" => "Create",
|
||||
"actor" => robin.ap_id,
|
||||
"to" => [batman.ap_id, robin.follower_address],
|
||||
"cc" => [],
|
||||
"object" => %{
|
||||
"type" => "Note",
|
||||
"actor" => robin.ap_id,
|
||||
"content" => "@batman Wait up, I forgot my spandex!",
|
||||
"to" => [batman.ap_id, robin.follower_address],
|
||||
"cc" => [],
|
||||
"inReplyTo" => Object.normalize(post).data["id"]
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, filtered} = QuietReply.filter(reply)
|
||||
|
||||
assert match?(^filtered, reply)
|
||||
end
|
||||
|
||||
test "non-reply posts are unmodified" do
|
||||
batman = insert(:user, nickname: "batman")
|
||||
|
||||
{:ok, post} = CommonAPI.post(batman, %{status: "To the Batmobile!"})
|
||||
|
||||
assert {:ok, filtered} = QuietReply.filter(post)
|
||||
|
||||
assert match?(^filtered, post)
|
||||
end
|
||||
end
|
||||
155
test/pleroma/web/activity_pub/mrf/remote_report_policy_test.exs
Normal file
155
test/pleroma/web/activity_pub/mrf/remote_report_policy_test.exs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
defmodule Pleroma.Web.ActivityPub.MRF.RemoteReportPolicyTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.Web.ActivityPub.MRF.RemoteReportPolicy
|
||||
|
||||
setup do
|
||||
clear_config([:mrf_remote_report, :reject_all], false)
|
||||
end
|
||||
|
||||
test "doesn't impact local report" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], true)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "http://localhost:4001/actor",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "rejects anonymous report if `reject_anonymous: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], true)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/actor",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "preserves anonymous report if `reject_anonymous: false`" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/actor",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "rejects report on third party if `reject_third_party: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_third_party], true)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "preserves report on first party if `reject_third_party: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_third_party], true)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["http://localhost:4001/actor"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "preserves report on third party if `reject_third_party: false`" do
|
||||
clear_config([:mrf_remote_report, :reject_third_party], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "rejects empty message report if `reject_empty_message: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "rejects empty message report (\"\") if `reject_empty_message: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["https://mastodon.online/users/Gargron"],
|
||||
"content" => ""
|
||||
}
|
||||
|
||||
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "preserves empty message report if `reject_empty_message: false`" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "preserves anonymous, empty message report with all settings disabled" do
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/actor",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
|
||||
test "reject remote report if `reject_all: true`" do
|
||||
clear_config([:mrf_remote_report, :reject_all], true)
|
||||
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||
|
||||
activity = %{
|
||||
"type" => "Flag",
|
||||
"actor" => "https://mastodon.social/users/Gargron",
|
||||
"content" => "Transphobia",
|
||||
"object" => ["https://mastodon.online/users/Gargron"]
|
||||
}
|
||||
|
||||
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||
end
|
||||
end
|
||||
|
|
@ -252,6 +252,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
remote_message = build_remote_message()
|
||||
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
assert SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "activity has a matching host" do
|
||||
|
|
@ -260,6 +261,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
remote_message = build_remote_message()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_message)
|
||||
refute SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "activity matches with wildcard domain" do
|
||||
|
|
@ -268,6 +270,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
remote_message = build_remote_message()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_message)
|
||||
refute SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "actor has a matching host" do
|
||||
|
|
@ -276,6 +279,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
remote_user = build_remote_user()
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_user)
|
||||
refute SimplePolicy.id_filter(remote_user["id"])
|
||||
end
|
||||
|
||||
test "reject Announce when object would be rejected" do
|
||||
|
|
@ -288,6 +292,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
}
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(announce)
|
||||
# Note: Non-Applicable for id_filter/1
|
||||
end
|
||||
|
||||
test "reject by URI object" do
|
||||
|
|
@ -300,6 +305,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
}
|
||||
|
||||
assert {:reject, _} = SimplePolicy.filter(announce)
|
||||
# Note: Non-Applicable for id_filter/1
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -318,7 +324,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
following_user = insert(:user)
|
||||
non_following_user = insert(:user)
|
||||
|
||||
{:ok, _, _, _} = CommonAPI.follow(following_user, actor)
|
||||
{:ok, _, _, _} = CommonAPI.follow(actor, following_user)
|
||||
|
||||
activity = %{
|
||||
"actor" => actor.ap_id,
|
||||
|
|
@ -370,6 +376,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
assert SimplePolicy.id_filter(local_message["actor"])
|
||||
assert SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "is not empty but activity doesn't have a matching host" do
|
||||
|
|
@ -380,6 +388,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert {:reject, _} = SimplePolicy.filter(remote_message)
|
||||
assert SimplePolicy.id_filter(local_message["actor"])
|
||||
refute SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "activity has a matching host" do
|
||||
|
|
@ -390,6 +400,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
assert SimplePolicy.id_filter(local_message["actor"])
|
||||
assert SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "activity matches with wildcard domain" do
|
||||
|
|
@ -400,6 +412,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
|
||||
assert SimplePolicy.filter(local_message) == {:ok, local_message}
|
||||
assert SimplePolicy.filter(remote_message) == {:ok, remote_message}
|
||||
assert SimplePolicy.id_filter(local_message["actor"])
|
||||
assert SimplePolicy.id_filter(remote_message["actor"])
|
||||
end
|
||||
|
||||
test "actor has a matching host" do
|
||||
|
|
@ -408,6 +422,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
|
|||
remote_user = build_remote_user()
|
||||
|
||||
assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
|
||||
assert SimplePolicy.id_filter(remote_user["id"])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ defmodule Pleroma.Web.ActivityPub.MRFTest do
|
|||
refute MRF.subdomain_match?(regexes, "example.com")
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "logs sensible error on accidental wildcard" do
|
||||
assert_raise Regex.CompileError, fn ->
|
||||
assert capture_log(MRF.subdomains_regex(["*unsafe.tld"])) =~
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
|
|||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = Pleroma.Web.CommonAPI.post(user, %{status: "mew mew :dinosaur:"})
|
||||
{:ok, edit} = Pleroma.Web.CommonAPI.update(user, activity, %{status: "edited :blank:"})
|
||||
{:ok, edit} = Pleroma.Web.CommonAPI.update(activity, user, %{status: "edited :blank:"})
|
||||
|
||||
{:ok, %{"object" => external_rep}} =
|
||||
Pleroma.Web.ActivityPub.Transmogrifier.prepare_outgoing(edit.data)
|
||||
|
|
@ -128,6 +128,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
|
|||
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
|
||||
end
|
||||
|
||||
test "a Note with validated likes collection validates" do
|
||||
insert(:user, ap_id: "https://pol.social/users/mkljczk")
|
||||
|
||||
%{"object" => note} =
|
||||
"test/fixtures/mastodon-update-with-likes.json"
|
||||
|> File.read!()
|
||||
|> Jason.decode!()
|
||||
|
||||
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
|
||||
end
|
||||
|
||||
test "Fedibird quote post" do
|
||||
insert(:user, ap_id: "https://fedibird.com/users/noellabo")
|
||||
|
||||
|
|
|
|||
|
|
@ -27,19 +27,22 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do
|
|||
end
|
||||
|
||||
test "works with honkerific attachments" do
|
||||
attachment = %{
|
||||
honk = %{
|
||||
"mediaType" => "",
|
||||
"name" => "",
|
||||
"summary" => "298p3RG7j27tfsZ9RQ.jpg",
|
||||
"summary" => "Select your spirit chonk",
|
||||
"name" => "298p3RG7j27tfsZ9RQ.jpg",
|
||||
"type" => "Document",
|
||||
"url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg"
|
||||
}
|
||||
|
||||
assert {:ok, attachment} =
|
||||
AttachmentValidator.cast_and_validate(attachment)
|
||||
honk
|
||||
|> AttachmentValidator.cast_and_validate()
|
||||
|> Ecto.Changeset.apply_action(:insert)
|
||||
|
||||
assert attachment.mediaType == "application/octet-stream"
|
||||
assert attachment.summary == "Select your spirit chonk"
|
||||
assert attachment.name == "298p3RG7j27tfsZ9RQ.jpg"
|
||||
end
|
||||
|
||||
test "works with an unknown but valid mime type" do
|
||||
|
|
|
|||
|
|
@ -22,5 +22,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.FollowValidationTest do
|
|||
test "validates a basic follow object", %{valid_follow: valid_follow} do
|
||||
assert {:ok, _follow, []} = ObjectValidator.validate(valid_follow, [])
|
||||
end
|
||||
|
||||
test "supports a nil cc", %{valid_follow: valid_follow} do
|
||||
valid_follow_with_nil_cc = Map.put(valid_follow, "cc", nil)
|
||||
assert {:ok, _follow, []} = ObjectValidator.validate(valid_follow_with_nil_cc, [])
|
||||
end
|
||||
|
||||
test "supports an empty cc", %{valid_follow: valid_follow} do
|
||||
valid_follow_with_empty_cc = Map.put(valid_follow, "cc", [])
|
||||
assert {:ok, _follow, []} = ObjectValidator.validate(valid_follow_with_empty_cc, [])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.LikeValidationTest do
|
|||
user: user,
|
||||
post_activity: post_activity
|
||||
} do
|
||||
_like = CommonAPI.favorite(user, post_activity.id)
|
||||
_like = CommonAPI.favorite(post_activity.id, user)
|
||||
|
||||
refute LikeValidator.cast_and_validate(valid_like).valid?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UndoHandlingTest do
|
|||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
|
||||
{:ok, like} = CommonAPI.favorite(user, post_activity.id)
|
||||
{:ok, like} = CommonAPI.favorite(post_activity.id, user)
|
||||
{:ok, valid_like_undo, []} = Builder.undo(user, like)
|
||||
|
||||
%{user: user, like: like, valid_like_undo: valid_like_undo}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UpdateHandlingTest do
|
|||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = Pleroma.Web.CommonAPI.post(user, %{status: "mew mew :dinosaur:"})
|
||||
{:ok, edit} = Pleroma.Web.CommonAPI.update(user, activity, %{status: "edited :blank:"})
|
||||
{:ok, edit} = Pleroma.Web.CommonAPI.update(activity, user, %{status: "edited :blank:"})
|
||||
{:ok, external_rep} = Pleroma.Web.ActivityPub.Transmogrifier.prepare_outgoing(edit.data)
|
||||
%{external_rep: external_rep}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
|
|
@ -13,6 +14,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
alias Pleroma.Activity
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.Web.ActivityPub.Publisher
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
|
|
@ -137,6 +139,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
test "publish to url with with different ports" do
|
||||
inbox80 = "http://42.site/users/nick1/inbox"
|
||||
inbox42 = "http://42.site:42/users/nick1/inbox"
|
||||
activity = insert(:note_activity)
|
||||
|
||||
mock(fn
|
||||
%{method: :post, url: "http://42.site:42/users/nick1/inbox"} ->
|
||||
|
|
@ -146,53 +149,40 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
{:ok, %Tesla.Env{status: 200, body: "port 80"}}
|
||||
end)
|
||||
|
||||
actor = insert(:user)
|
||||
_actor = insert(:user)
|
||||
|
||||
assert {:ok, %{body: "port 42"}} =
|
||||
Publisher.publish_one(%{
|
||||
Publisher.prepare_one(%{
|
||||
inbox: inbox42,
|
||||
json: "{}",
|
||||
actor: actor,
|
||||
id: 1,
|
||||
activity_id: activity.id,
|
||||
unreachable_since: true
|
||||
})
|
||||
|> Publisher.publish_one()
|
||||
|
||||
assert {:ok, %{body: "port 80"}} =
|
||||
Publisher.publish_one(%{
|
||||
Publisher.prepare_one(%{
|
||||
inbox: inbox80,
|
||||
json: "{}",
|
||||
actor: actor,
|
||||
id: 1,
|
||||
activity_id: activity.id,
|
||||
unreachable_since: true
|
||||
})
|
||||
end
|
||||
|
||||
test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",
|
||||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
inbox = "http://200.site/users/nick1/inbox"
|
||||
|
||||
assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
|
||||
assert called(Instances.set_reachable(inbox))
|
||||
|> Publisher.publish_one()
|
||||
end
|
||||
|
||||
test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is set",
|
||||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
_actor = insert(:user)
|
||||
inbox = "http://200.site/users/nick1/inbox"
|
||||
activity = insert(:note_activity)
|
||||
|
||||
assert {:ok, _} =
|
||||
Publisher.publish_one(%{
|
||||
Publisher.prepare_one(%{
|
||||
inbox: inbox,
|
||||
json: "{}",
|
||||
actor: actor,
|
||||
id: 1,
|
||||
unreachable_since: NaiveDateTime.utc_now()
|
||||
activity_id: activity.id,
|
||||
unreachable_since: NaiveDateTime.utc_now() |> NaiveDateTime.to_string()
|
||||
})
|
||||
|> Publisher.publish_one()
|
||||
|
||||
assert called(Instances.set_reachable(inbox))
|
||||
end
|
||||
|
|
@ -201,31 +191,32 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
_actor = insert(:user)
|
||||
inbox = "http://200.site/users/nick1/inbox"
|
||||
activity = insert(:note_activity)
|
||||
|
||||
assert {:ok, _} =
|
||||
Publisher.publish_one(%{
|
||||
Publisher.prepare_one(%{
|
||||
inbox: inbox,
|
||||
json: "{}",
|
||||
actor: actor,
|
||||
id: 1,
|
||||
activity_id: activity.id,
|
||||
unreachable_since: nil
|
||||
})
|
||||
|> Publisher.publish_one()
|
||||
|
||||
refute called(Instances.set_reachable(inbox))
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test_with_mock "calls `Instances.set_unreachable` on target inbox on non-2xx HTTP response code",
|
||||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
_actor = insert(:user)
|
||||
inbox = "http://404.site/users/nick1/inbox"
|
||||
activity = insert(:note_activity)
|
||||
|
||||
assert {:discard, _} =
|
||||
Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
|
||||
assert {:cancel, _} =
|
||||
Publisher.prepare_one(%{inbox: inbox, activity_id: activity.id})
|
||||
|> Publisher.publish_one()
|
||||
|
||||
assert called(Instances.set_unreachable(inbox))
|
||||
end
|
||||
|
|
@ -234,12 +225,17 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
_actor = insert(:user)
|
||||
inbox = "http://connrefused.site/users/nick1/inbox"
|
||||
activity = insert(:note_activity)
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert {:error, _} =
|
||||
Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
|
||||
Publisher.prepare_one(%{
|
||||
inbox: inbox,
|
||||
activity_id: activity.id
|
||||
})
|
||||
|> Publisher.publish_one()
|
||||
end) =~ "connrefused"
|
||||
|
||||
assert called(Instances.set_unreachable(inbox))
|
||||
|
|
@ -249,10 +245,13 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
_actor = insert(:user)
|
||||
inbox = "http://200.site/users/nick1/inbox"
|
||||
activity = insert(:note_activity)
|
||||
|
||||
assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
|
||||
assert {:ok, _} =
|
||||
Publisher.prepare_one(%{inbox: inbox, activity_id: activity.id})
|
||||
|> Publisher.publish_one()
|
||||
|
||||
refute called(Instances.set_unreachable(inbox))
|
||||
end
|
||||
|
|
@ -261,18 +260,18 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
Instances,
|
||||
[:passthrough],
|
||||
[] do
|
||||
actor = insert(:user)
|
||||
_actor = insert(:user)
|
||||
inbox = "http://connrefused.site/users/nick1/inbox"
|
||||
activity = insert(:note_activity)
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert {:error, _} =
|
||||
Publisher.publish_one(%{
|
||||
Publisher.prepare_one(%{
|
||||
inbox: inbox,
|
||||
json: "{}",
|
||||
actor: actor,
|
||||
id: 1,
|
||||
unreachable_since: NaiveDateTime.utc_now()
|
||||
activity_id: activity.id,
|
||||
unreachable_since: NaiveDateTime.utc_now() |> NaiveDateTime.to_string()
|
||||
})
|
||||
|> Publisher.publish_one()
|
||||
end) =~ "connrefused"
|
||||
|
||||
refute called(Instances.set_unreachable(inbox))
|
||||
|
|
@ -307,13 +306,15 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
|
||||
assert res == :ok
|
||||
|
||||
assert not called(
|
||||
Publisher.enqueue_one(%{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: note_activity.data["id"]
|
||||
})
|
||||
)
|
||||
refute_enqueued(
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{
|
||||
"params" => %{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
activity_id: note_activity.id
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
test_with_mock "Publishes a non-public activity to non-quarantined instances.",
|
||||
|
|
@ -343,16 +344,16 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
|
||||
assert res == :ok
|
||||
|
||||
assert called(
|
||||
Publisher.enqueue_one(
|
||||
%{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: note_activity.data["id"]
|
||||
},
|
||||
priority: 1
|
||||
)
|
||||
)
|
||||
assert_enqueued(
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{
|
||||
"params" => %{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
activity_id: note_activity.id
|
||||
}
|
||||
},
|
||||
priority: 1
|
||||
)
|
||||
end
|
||||
|
||||
test_with_mock "Publishes to directly addressed actors with higher priority.",
|
||||
|
|
@ -371,8 +372,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
Publisher.enqueue_one(
|
||||
%{
|
||||
inbox: :_,
|
||||
actor_id: actor.id,
|
||||
id: note_activity.data["id"]
|
||||
activity_id: note_activity.id
|
||||
},
|
||||
priority: 0
|
||||
)
|
||||
|
|
@ -403,13 +403,15 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
res = Publisher.publish(actor, note_activity)
|
||||
assert res == :ok
|
||||
|
||||
assert called(
|
||||
Publisher.enqueue_one(%{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: note_activity.data["id"]
|
||||
})
|
||||
)
|
||||
assert_enqueued(
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{
|
||||
"params" => %{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
activity_id: note_activity.id
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
test_with_mock "publishes a delete activity to peers who signed fetch requests to the create acitvity/object.",
|
||||
|
|
@ -453,27 +455,69 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
|||
res = Publisher.publish(actor, delete)
|
||||
assert res == :ok
|
||||
|
||||
assert called(
|
||||
Publisher.enqueue_one(
|
||||
%{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: delete.data["id"]
|
||||
},
|
||||
priority: 1
|
||||
)
|
||||
)
|
||||
assert_enqueued(
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{
|
||||
"params" => %{
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
activity_id: delete.id
|
||||
}
|
||||
},
|
||||
priority: 1
|
||||
)
|
||||
|
||||
assert called(
|
||||
Publisher.enqueue_one(
|
||||
%{
|
||||
inbox: "https://domain2.com/users/nick1/inbox",
|
||||
actor_id: actor.id,
|
||||
id: delete.data["id"]
|
||||
},
|
||||
priority: 1
|
||||
)
|
||||
)
|
||||
assert_enqueued(
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{
|
||||
"params" => %{
|
||||
inbox: "https://domain2.com/users/nick1/inbox",
|
||||
activity_id: delete.id
|
||||
}
|
||||
},
|
||||
priority: 1
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "cc in prepared json for a follow request is an empty list" do
|
||||
user = insert(:user)
|
||||
remote_user = insert(:user, local: false)
|
||||
|
||||
{:ok, _, _, activity} = CommonAPI.follow(remote_user, user)
|
||||
|
||||
assert_enqueued(
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{
|
||||
"activity_id" => activity.id,
|
||||
"op" => "publish"
|
||||
}
|
||||
)
|
||||
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
expected_params =
|
||||
%{
|
||||
"activity_id" => activity.id,
|
||||
"inbox" => remote_user.inbox,
|
||||
"unreachable_since" => nil
|
||||
}
|
||||
|
||||
assert_enqueued(
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{
|
||||
"op" => "publish_one",
|
||||
"params" => expected_params
|
||||
}
|
||||
)
|
||||
|
||||
# params need to be atom keys for Publisher.prepare_one.
|
||||
# this is done in the Oban job.
|
||||
expected_params = Map.new(expected_params, fn {k, v} -> {String.to_atom(k), v} end)
|
||||
|
||||
%{json: json} = Publisher.prepare_one(expected_params)
|
||||
|
||||
{:ok, decoded} = Jason.decode(json)
|
||||
|
||||
assert decoded["cc"] == []
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
|
|||
test "returns activity" do
|
||||
user = insert(:user)
|
||||
service_actor = Relay.get_actor()
|
||||
CommonAPI.follow(service_actor, user)
|
||||
CommonAPI.follow(user, service_actor)
|
||||
assert "#{user.ap_id}/followers" in User.following(service_actor)
|
||||
assert {:ok, %Activity{} = activity} = Relay.unfollow(user.ap_id)
|
||||
assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay"
|
||||
|
|
@ -74,7 +74,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
|
|||
end)
|
||||
|
||||
service_actor = Relay.get_actor()
|
||||
CommonAPI.follow(service_actor, user)
|
||||
CommonAPI.follow(user, service_actor)
|
||||
assert "#{user.ap_id}/followers" in User.following(service_actor)
|
||||
|
||||
assert Pleroma.Repo.get_by(
|
||||
|
|
@ -113,7 +113,6 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
|
|||
assert Relay.publish(activity) == {:error, "Not implemented"}
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns error when activity not public" do
|
||||
activity = insert(:direct_note_activity)
|
||||
assert Relay.publish(activity) == {:error, false}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects.DeleteTest do
|
|||
|
||||
{:ok, op} = CommonAPI.post(other_user, %{status: "big oof"})
|
||||
{:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op})
|
||||
{:ok, favorite} = CommonAPI.favorite(user, post.id)
|
||||
{:ok, favorite} = CommonAPI.favorite(post.id, user)
|
||||
object = Object.normalize(post, fetch: false)
|
||||
{:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
|
||||
{:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
|
||||
|
|
|
|||
|
|
@ -54,20 +54,17 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
|||
[
|
||||
stream: fn _, _ -> nil end
|
||||
]
|
||||
},
|
||||
{
|
||||
Pleroma.Web.Push,
|
||||
[],
|
||||
[
|
||||
send: fn _ -> nil end
|
||||
]
|
||||
}
|
||||
]) do
|
||||
SideEffects.handle_after_transaction(meta)
|
||||
|
||||
assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification))
|
||||
assert called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_))
|
||||
assert called(Pleroma.Web.Push.send(notification))
|
||||
|
||||
assert_enqueued(
|
||||
worker: "Pleroma.Workers.WebPusherWorker",
|
||||
args: %{"notification_id" => notification.id, "op" => "web_push"}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -516,10 +513,10 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
|||
poster = insert(:user)
|
||||
user = insert(:user)
|
||||
{:ok, post} = CommonAPI.post(poster, %{status: "hey"})
|
||||
{:ok, like} = CommonAPI.favorite(user, post.id)
|
||||
{:ok, like} = CommonAPI.favorite(post.id, user)
|
||||
{:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
|
||||
{:ok, announce} = CommonAPI.repeat(post.id, user)
|
||||
{:ok, block} = CommonAPI.block(user, poster)
|
||||
{:ok, block} = CommonAPI.block(poster, user)
|
||||
|
||||
{:ok, undo_data, _meta} = Builder.undo(user, like)
|
||||
{:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
|
||||
|
|
@ -834,7 +831,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
|||
user = insert(:user)
|
||||
followed = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(user, followed)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(followed, user)
|
||||
|
||||
{:ok, reject_data, []} = Builder.reject(followed, follow_activity)
|
||||
{:ok, reject, _meta} = ActivityPub.persist(reject_data, local: true)
|
||||
|
|
@ -965,7 +962,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
|
|||
group: group,
|
||||
poster: poster
|
||||
} do
|
||||
{:ok, _} = CommonAPI.block(group, poster)
|
||||
{:ok, _} = CommonAPI.block(poster, group)
|
||||
create_activity_data = make_create.([group])
|
||||
{:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AcceptHandlingTest do
|
|||
{:ok, follower, followed} = User.follow(follower, followed)
|
||||
assert User.following?(follower, followed) == true
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(followed, follower)
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-accept-activity.json")
|
||||
|
|
@ -48,7 +48,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AcceptHandlingTest do
|
|||
follower = insert(:user)
|
||||
followed = insert(:user, is_locked: true)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(followed, follower)
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-accept-activity.json")
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do
|
|||
assert(Activity.get_create_by_object_ap_id(data["object"]))
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it works for incoming announces with an existing activity" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
|
|
@ -136,7 +135,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AnnounceHandlingTest do
|
|||
assert object.data["content"] == "this is a private toot"
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it rejects incoming announces with an inlined activity from another origin" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :get} -> %Tesla.Env{status: 404, body: ""}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.DeleteHandlingTest do
|
|||
assert match?({:error, _}, Transmogrifier.handle_incoming(data))
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it works for incoming user deletes" do
|
||||
%{ap_id: ap_id} = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiTagBuildingTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
|
||||
test "it encodes the id to be a valid url" do
|
||||
name = "hanapog"
|
||||
url = "https://misskey.local.live/emojis/hana pog.png"
|
||||
|
||||
tag = Transmogrifier.build_emoji_tag({name, url})
|
||||
|
||||
assert tag["id"] == "https://misskey.local.live/emojis/hana%20pog.png"
|
||||
end
|
||||
end
|
||||
|
|
@ -56,7 +56,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
|
|||
assert activity == returned_activity
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it fetches reply-to activities if we don't have them" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|
|
@ -104,7 +103,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
|
|||
end
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it does not crash if the object in inReplyTo can't be fetched" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|
|
@ -581,7 +579,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
|
|||
assert modified_object["inReplyTo"] == []
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns modified object when allowed incoming reply", %{data: data} do
|
||||
object_with_reply =
|
||||
Map.put(
|
||||
|
|
@ -767,7 +764,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
|
|||
assert modified.data["context"] == object.data["id"]
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "the reply note uses its parent's ID when context is missing and reply is unreachable" do
|
||||
insert(:user, ap_id: "https://mk.absturztau.be/users/8ozbzjs3o8")
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.RejectHandlingTest do
|
|||
followed = insert(:user, is_locked: true)
|
||||
|
||||
{:ok, follower, followed} = User.follow(follower, followed)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(followed, follower)
|
||||
|
||||
assert User.following?(follower, followed) == true
|
||||
|
||||
|
|
|
|||
|
|
@ -119,8 +119,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UserUpdateHandlingTest do
|
|||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
|
||||
assert user.fields == [
|
||||
%{"name" => "foo", "value" => "updated"},
|
||||
%{"name" => "foo1", "value" => "updated"}
|
||||
%{"name" => "foo", "value" => "bar"},
|
||||
%{"name" => "foo11", "value" => "bar11"}
|
||||
]
|
||||
|
||||
update_data =
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "everybody do the dinosaur :dinosaur:"})
|
||||
{:ok, update} = CommonAPI.update(user, activity, %{status: "mew mew :blank:"})
|
||||
{:ok, update} = CommonAPI.update(activity, user, %{status: "mew mew :blank:"})
|
||||
|
||||
{:ok, prepared} = Transmogrifier.prepare_outgoing(update.data)
|
||||
|
||||
|
|
@ -554,7 +554,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
end) =~ "Unsupported URI scheme"
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns {:ok, %Object{}} for success case" do
|
||||
assert {:ok, %Object{}} =
|
||||
Transmogrifier.get_obj_helper(
|
||||
|
|
@ -640,5 +639,14 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
processed = Transmogrifier.prepare_object(original)
|
||||
assert processed["formerRepresentations"] == original["formerRepresentations"]
|
||||
end
|
||||
|
||||
test "it uses contentMap to specify post language" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "Cześć", language: "pl"})
|
||||
object = Transmogrifier.prepare_object(activity.object.data)
|
||||
|
||||
assert %{"contentMap" => %{"pl" => "Cześć"}} = object
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
})
|
||||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
{:ok, votes, object} = CommonAPI.vote(other_user, object, [0, 1])
|
||||
{:ok, votes, object} = CommonAPI.vote(object, other_user, [0, 1])
|
||||
assert Enum.sort(Utils.get_existing_votes(other_user.ap_id, object)) == Enum.sort(votes)
|
||||
end
|
||||
|
||||
|
|
@ -233,8 +233,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
})
|
||||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
{:ok, [vote], object} = CommonAPI.vote(other_user, object, [0])
|
||||
{:ok, _activity} = CommonAPI.favorite(user, activity.id)
|
||||
{:ok, [vote], object} = CommonAPI.vote(object, other_user, [0])
|
||||
{:ok, _activity} = CommonAPI.favorite(activity.id, user)
|
||||
[fetched_vote] = Utils.get_existing_votes(other_user.ap_id, object)
|
||||
assert fetched_vote.id == vote.id
|
||||
end
|
||||
|
|
@ -245,8 +245,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
user = insert(:user, is_locked: true)
|
||||
follower = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(user, follower)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(user, follower)
|
||||
|
||||
data =
|
||||
follow_activity_two.data
|
||||
|
|
@ -267,8 +267,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
user = insert(:user)
|
||||
follower = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(user, follower)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(user, follower)
|
||||
|
||||
{:ok, follow_activity_two} =
|
||||
Utils.update_follow_state_for_all(follow_activity_two, "reject")
|
||||
|
|
@ -283,8 +283,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
user = insert(:user, is_locked: true)
|
||||
follower = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(user, follower)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(user, follower)
|
||||
|
||||
data =
|
||||
follow_activity_two.data
|
||||
|
|
@ -369,7 +369,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
|
||||
user = insert(:user)
|
||||
refute Utils.get_existing_like(user.ap_id, object)
|
||||
{:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
|
||||
{:ok, like_activity} = CommonAPI.favorite(note_activity.id, user)
|
||||
|
||||
assert ^like_activity = Utils.get_existing_like(user.ap_id, object)
|
||||
end
|
||||
|
|
@ -396,9 +396,9 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
user1 = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
|
||||
assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
|
||||
assert {:ok, %Activity{} = activity} = CommonAPI.block(user1, user2)
|
||||
assert {:ok, %Activity{} = _} = CommonAPI.block(user2, user1)
|
||||
assert {:ok, %Activity{} = _} = CommonAPI.block(user2, user1)
|
||||
assert {:ok, %Activity{} = activity} = CommonAPI.block(user2, user1)
|
||||
|
||||
assert Utils.fetch_latest_block(user1, user2) == activity
|
||||
end
|
||||
|
|
@ -560,7 +560,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
|||
target_account = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(posting_account, %{status: "foobar"})
|
||||
{:ok, like} = CommonAPI.favorite(target_account, activity.id)
|
||||
{:ok, like} = CommonAPI.favorite(activity.id, target_account)
|
||||
context = Utils.generate_context_id()
|
||||
content = "foobar"
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectViewTest do
|
|||
object = Object.normalize(note, fetch: false)
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, like_activity} = CommonAPI.favorite(user, note.id)
|
||||
{:ok, like_activity} = CommonAPI.favorite(note.id, user)
|
||||
|
||||
result = ObjectView.render("object.json", %{object: like_activity})
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,23 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
result = UserView.render("user.json", %{user: user})
|
||||
assert result["icon"]["url"] == "https://someurl"
|
||||
assert result["image"]["url"] == "https://somebanner"
|
||||
|
||||
refute result["icon"]["name"]
|
||||
refute result["image"]["name"]
|
||||
end
|
||||
|
||||
test "Avatar has a description if the user set one" do
|
||||
user =
|
||||
insert(:user,
|
||||
avatar: %{
|
||||
"url" => [%{"href" => "https://someurl"}],
|
||||
"name" => "a drawing of pleroma-tan using pleroma groups"
|
||||
}
|
||||
)
|
||||
|
||||
result = UserView.render("user.json", %{user: user})
|
||||
|
||||
assert result["icon"]["name"] == "a drawing of pleroma-tan using pleroma groups"
|
||||
end
|
||||
|
||||
test "renders an invisible user with the invisible property set to true" do
|
||||
|
|
@ -138,7 +155,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
test "sets totalItems to zero when followers are hidden" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
|
||||
user = Map.merge(user, %{hide_followers_count: true, hide_followers: true})
|
||||
refute UserView.render("followers.json", %{user: user}) |> Map.has_key?("totalItems")
|
||||
|
|
@ -147,7 +164,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
test "sets correct totalItems when followers are hidden but the follower counter is not" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
|
||||
user = Map.merge(user, %{hide_followers_count: false, hide_followers: true})
|
||||
assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user})
|
||||
|
|
@ -158,7 +175,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
test "sets totalItems to zero when follows are hidden" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
|
||||
user = Map.merge(user, %{hide_follows_count: true, hide_follows: true})
|
||||
assert %{"totalItems" => 0} = UserView.render("following.json", %{user: user})
|
||||
|
|
@ -167,7 +184,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
test "sets correct totalItems when follows are hidden but the follow counter is not" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
|
||||
user = Map.merge(user, %{hide_follows_count: false, hide_follows: true})
|
||||
assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})
|
||||
|
|
|
|||
|
|
@ -1096,9 +1096,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
|||
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup, admin.id)
|
||||
email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup)
|
||||
|
||||
assert String.contains?(
|
||||
email.html_body,
|
||||
"A full backup of your Pleroma account was requested"
|
||||
)
|
||||
|
||||
assert String.contains?(email.html_body, "Admin @#{admin.nickname} requested a full backup")
|
||||
assert_email_sent(to: {user.name, user.email}, html_body: email.html_body)
|
||||
|
||||
log_message = "@#{admin_nickname} requested account backup for @#{user_nickname}"
|
||||
|
|
|
|||
|
|
@ -194,7 +194,6 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|
|||
|
||||
setup do: clear_config(:configurable_from_database, true)
|
||||
|
||||
@tag capture_log: true
|
||||
test "create new config setting in db", %{conn: conn} do
|
||||
ueberauth = Application.get_env(:ueberauth, Ueberauth)
|
||||
on_exit(fn -> Application.put_env(:ueberauth, Ueberauth, ueberauth) end)
|
||||
|
|
@ -316,7 +315,6 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|
|||
assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "save configs setting without explicit key", %{conn: conn} do
|
||||
adapter = Application.get_env(:http, :adapter)
|
||||
send_user_agent = Application.get_env(:http, :send_user_agent)
|
||||
|
|
@ -611,52 +609,6 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|
|||
]
|
||||
end
|
||||
|
||||
test "saving full setting if value is in full_key_update list", %{conn: conn} do
|
||||
backends = Application.get_env(:logger, :backends)
|
||||
on_exit(fn -> Application.put_env(:logger, :backends, backends) end)
|
||||
|
||||
insert(:config,
|
||||
group: :logger,
|
||||
key: :backends,
|
||||
value: []
|
||||
)
|
||||
|
||||
Pleroma.Config.TransferTask.load_and_update_env([], false)
|
||||
|
||||
assert Application.get_env(:logger, :backends) == []
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/pleroma/admin/config", %{
|
||||
configs: [
|
||||
%{
|
||||
group: ":logger",
|
||||
key: ":backends",
|
||||
value: [":console"]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
assert json_response_and_validate_schema(conn, 200) == %{
|
||||
"configs" => [
|
||||
%{
|
||||
"group" => ":logger",
|
||||
"key" => ":backends",
|
||||
"value" => [
|
||||
":console"
|
||||
],
|
||||
"db" => [":backends"]
|
||||
}
|
||||
],
|
||||
"need_reboot" => false
|
||||
}
|
||||
|
||||
assert Application.get_env(:logger, :backends) == [
|
||||
:console
|
||||
]
|
||||
end
|
||||
|
||||
test "saving full setting if value is not keyword", %{conn: conn} do
|
||||
insert(:config,
|
||||
group: :tesla,
|
||||
|
|
@ -1229,7 +1181,6 @@ defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do
|
|||
assert ":proxy_url" in db
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "doesn't set keys not in the whitelist", %{conn: conn} do
|
||||
clear_config(:database_config_whitelist, [
|
||||
{:pleroma, :key1},
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
|
|||
# Create some activities to check they got deleted later
|
||||
follower = insert(:user)
|
||||
{:ok, _} = CommonAPI.post(user, %{status: "test"})
|
||||
{:ok, _, _, _} = CommonAPI.follow(user, follower)
|
||||
{:ok, _, _, _} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, _} = CommonAPI.follow(user, follower)
|
||||
user = Repo.get(User, user.id)
|
||||
assert user.note_count == 1
|
||||
assert user.follower_count == 1
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Rule
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
|
|
@ -22,7 +23,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Workers.PollWorker
|
||||
|
||||
import Ecto.Query, only: [from: 2]
|
||||
import Ecto.Query, only: [from: 2, where: 3]
|
||||
import Mock
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
|
|
@ -79,8 +80,8 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
setup do
|
||||
blocker = insert(:user)
|
||||
blocked = insert(:user, local: false)
|
||||
CommonAPI.follow(blocker, blocked)
|
||||
CommonAPI.follow(blocked, blocker)
|
||||
CommonAPI.follow(blocker, blocked)
|
||||
CommonAPI.accept_follow_request(blocker, blocked)
|
||||
CommonAPI.accept_follow_request(blocked, blocked)
|
||||
%{blocker: blocker, blocked: blocked}
|
||||
|
|
@ -94,7 +95,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
assert User.get_follow_state(blocker, blocked) == :follow_accept
|
||||
refute is_nil(Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(blocker, blocked))
|
||||
|
||||
assert {:ok, block} = CommonAPI.block(blocker, blocked)
|
||||
assert {:ok, block} = CommonAPI.block(blocked, blocker)
|
||||
|
||||
assert block.local
|
||||
assert User.blocks?(blocker, blocked)
|
||||
|
|
@ -119,7 +120,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _ -> nil end do
|
||||
assert {:ok, block} = CommonAPI.block(blocker, blocked)
|
||||
assert {:ok, block} = CommonAPI.block(blocked, blocker)
|
||||
|
||||
assert block.local
|
||||
assert User.blocks?(blocker, blocked)
|
||||
|
|
@ -323,7 +324,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
User.block(blocker, blocked)
|
||||
|
||||
assert User.blocks?(blocker, blocked)
|
||||
assert {:ok, :no_activity} == CommonAPI.unblock(blocker, blocked)
|
||||
assert {:ok, :no_activity} == CommonAPI.unblock(blocked, blocker)
|
||||
refute User.blocks?(blocker, blocked)
|
||||
end
|
||||
end
|
||||
|
|
@ -453,7 +454,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
users_serial
|
||||
|> Enum.map(fn user ->
|
||||
CommonAPI.favorite(user, activity.id)
|
||||
CommonAPI.favorite(activity.id, user)
|
||||
end)
|
||||
|
||||
object = Object.get_by_ap_id(activity.data["object"])
|
||||
|
|
@ -462,7 +463,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
users
|
||||
|> Enum.map(fn user ->
|
||||
Task.async(fn ->
|
||||
CommonAPI.favorite(user, activity.id)
|
||||
CommonAPI.favorite(activity.id, user)
|
||||
end)
|
||||
end)
|
||||
|> Enum.map(&Task.await/1)
|
||||
|
|
@ -954,7 +955,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
test "author can repeat own private statuses" do
|
||||
author = insert(:user)
|
||||
follower = insert(:user)
|
||||
CommonAPI.follow(follower, author)
|
||||
CommonAPI.follow(author, follower)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(author, %{status: "cofe", visibility: "private"})
|
||||
|
||||
|
|
@ -973,7 +974,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
{:ok, post_activity} = CommonAPI.post(other_user, %{status: "cofe"})
|
||||
|
||||
{:ok, %Activity{data: data}} = CommonAPI.favorite(user, post_activity.id)
|
||||
{:ok, %Activity{data: data}} = CommonAPI.favorite(post_activity.id, user)
|
||||
assert data["type"] == "Like"
|
||||
assert data["actor"] == user.ap_id
|
||||
assert data["object"] == post_activity.data["object"]
|
||||
|
|
@ -993,8 +994,8 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
other_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
|
||||
{:ok, %Activity{}} = CommonAPI.favorite(user, activity.id)
|
||||
assert {:ok, :already_liked} = CommonAPI.favorite(user, activity.id)
|
||||
{:ok, %Activity{}} = CommonAPI.favorite(activity.id, user)
|
||||
assert {:ok, :already_liked} = CommonAPI.favorite(activity.id, user)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1148,7 +1149,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
}
|
||||
)
|
||||
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(friend2, activity.id)
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(activity.id, friend2)
|
||||
{:ok, repeat_activity} = CommonAPI.repeat(activity.id, friend1)
|
||||
|
||||
assert Repo.aggregate(
|
||||
|
|
@ -1171,8 +1172,8 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
n.type == "mention" && n.activity_id == reply_activity.id
|
||||
end)
|
||||
|
||||
{:ok, _} = CommonAPI.add_mute(author, activity)
|
||||
assert CommonAPI.thread_muted?(author, activity)
|
||||
{:ok, _} = CommonAPI.add_mute(activity, author)
|
||||
assert CommonAPI.thread_muted?(activity, author)
|
||||
|
||||
assert Repo.aggregate(
|
||||
from(n in Notification, where: n.seen == false and n.user_id == ^friend1.id),
|
||||
|
|
@ -1196,13 +1197,13 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
end
|
||||
|
||||
test "add mute", %{user: user, activity: activity} do
|
||||
{:ok, _} = CommonAPI.add_mute(user, activity)
|
||||
assert CommonAPI.thread_muted?(user, activity)
|
||||
{:ok, _} = CommonAPI.add_mute(activity, user)
|
||||
assert CommonAPI.thread_muted?(activity, user)
|
||||
end
|
||||
|
||||
test "add expiring mute", %{user: user, activity: activity} do
|
||||
{:ok, _} = CommonAPI.add_mute(user, activity, %{expires_in: 60})
|
||||
assert CommonAPI.thread_muted?(user, activity)
|
||||
{:ok, _} = CommonAPI.add_mute(activity, user, %{expires_in: 60})
|
||||
assert CommonAPI.thread_muted?(activity, user)
|
||||
|
||||
worker = Pleroma.Workers.MuteExpireWorker
|
||||
args = %{"op" => "unmute_conversation", "user_id" => user.id, "activity_id" => activity.id}
|
||||
|
|
@ -1213,24 +1214,24 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
)
|
||||
|
||||
assert :ok = perform_job(worker, args)
|
||||
refute CommonAPI.thread_muted?(user, activity)
|
||||
refute CommonAPI.thread_muted?(activity, user)
|
||||
end
|
||||
|
||||
test "remove mute", %{user: user, activity: activity} do
|
||||
CommonAPI.add_mute(user, activity)
|
||||
{:ok, _} = CommonAPI.remove_mute(user, activity)
|
||||
refute CommonAPI.thread_muted?(user, activity)
|
||||
CommonAPI.add_mute(activity, user)
|
||||
{:ok, _} = CommonAPI.remove_mute(activity, user)
|
||||
refute CommonAPI.thread_muted?(activity, user)
|
||||
end
|
||||
|
||||
test "remove mute by ids", %{user: user, activity: activity} do
|
||||
CommonAPI.add_mute(user, activity)
|
||||
{:ok, _} = CommonAPI.remove_mute(user.id, activity.id)
|
||||
refute CommonAPI.thread_muted?(user, activity)
|
||||
CommonAPI.add_mute(activity, user)
|
||||
{:ok, _} = CommonAPI.remove_mute(activity.id, user.id)
|
||||
refute CommonAPI.thread_muted?(activity, user)
|
||||
end
|
||||
|
||||
test "check that mutes can't be duplicate", %{user: user, activity: activity} do
|
||||
CommonAPI.add_mute(user, activity)
|
||||
{:error, _} = CommonAPI.add_mute(user, activity)
|
||||
CommonAPI.add_mute(activity, user)
|
||||
{:error, _} = CommonAPI.add_mute(activity, user)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1403,14 +1404,14 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
end
|
||||
|
||||
test "add a reblog mute", %{muter: muter, muted: muted} do
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(muter, muted)
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(muted, muter)
|
||||
|
||||
assert User.showing_reblogs?(muter, muted) == false
|
||||
end
|
||||
|
||||
test "remove a reblog mute", %{muter: muter, muted: muted} do
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(muter, muted)
|
||||
{:ok, _reblog_mute} = CommonAPI.show_reblogs(muter, muted)
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(muted, muter)
|
||||
{:ok, _reblog_mute} = CommonAPI.show_reblogs(muted, muter)
|
||||
|
||||
assert User.showing_reblogs?(muter, muted) == true
|
||||
end
|
||||
|
|
@ -1419,7 +1420,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
describe "follow/2" do
|
||||
test "directly follows a non-locked local user" do
|
||||
[follower, followed] = insert_pair(:user)
|
||||
{:ok, follower, followed, _} = CommonAPI.follow(follower, followed)
|
||||
{:ok, followed, follower, _} = CommonAPI.follow(followed, follower)
|
||||
|
||||
assert User.following?(follower, followed)
|
||||
end
|
||||
|
|
@ -1428,24 +1429,24 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
describe "unfollow/2" do
|
||||
test "also unsubscribes a user" do
|
||||
[follower, followed] = insert_pair(:user)
|
||||
{:ok, follower, followed, _} = CommonAPI.follow(follower, followed)
|
||||
{:ok, followed, follower, _} = CommonAPI.follow(followed, follower)
|
||||
{:ok, _subscription} = User.subscribe(follower, followed)
|
||||
|
||||
assert User.subscribed_to?(follower, followed)
|
||||
|
||||
{:ok, follower} = CommonAPI.unfollow(follower, followed)
|
||||
{:ok, follower} = CommonAPI.unfollow(followed, follower)
|
||||
|
||||
refute User.subscribed_to?(follower, followed)
|
||||
end
|
||||
|
||||
test "also unpins a user" do
|
||||
[follower, followed] = insert_pair(:user)
|
||||
{:ok, follower, followed, _} = CommonAPI.follow(follower, followed)
|
||||
{:ok, followed, follower, _} = CommonAPI.follow(followed, follower)
|
||||
{:ok, _endorsement} = User.endorse(follower, followed)
|
||||
|
||||
assert User.endorses?(follower, followed)
|
||||
|
||||
{:ok, follower} = CommonAPI.unfollow(follower, followed)
|
||||
{:ok, follower} = CommonAPI.unfollow(followed, follower)
|
||||
|
||||
refute User.endorses?(follower, followed)
|
||||
end
|
||||
|
|
@ -1454,11 +1455,11 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
follower = insert(:user)
|
||||
followed = insert(:user, is_locked: true)
|
||||
|
||||
assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
|
||||
CommonAPI.follow(follower, followed)
|
||||
assert {:ok, followed, follower, %{id: activity_id, data: %{"state" => "pending"}}} =
|
||||
CommonAPI.follow(followed, follower)
|
||||
|
||||
assert User.get_follow_state(follower, followed) == :follow_pending
|
||||
assert {:ok, follower} = CommonAPI.unfollow(follower, followed)
|
||||
assert {:ok, follower} = CommonAPI.unfollow(followed, follower)
|
||||
assert User.get_follow_state(follower, followed) == nil
|
||||
|
||||
assert %{id: ^activity_id, data: %{"state" => "cancelled"}} =
|
||||
|
|
@ -1476,11 +1477,11 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
follower = insert(:user)
|
||||
followed = insert(:user, is_locked: true, local: false)
|
||||
|
||||
assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
|
||||
CommonAPI.follow(follower, followed)
|
||||
assert {:ok, followed, follower, %{id: activity_id, data: %{"state" => "pending"}}} =
|
||||
CommonAPI.follow(followed, follower)
|
||||
|
||||
assert User.get_follow_state(follower, followed) == :follow_pending
|
||||
assert {:ok, follower} = CommonAPI.unfollow(follower, followed)
|
||||
assert {:ok, follower} = CommonAPI.unfollow(followed, follower)
|
||||
assert User.get_follow_state(follower, followed) == nil
|
||||
|
||||
assert %{id: ^activity_id, data: %{"state" => "cancelled"}} =
|
||||
|
|
@ -1501,9 +1502,9 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
follower = insert(:user)
|
||||
follower_two = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity_three} = CommonAPI.follow(follower_two, user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(user, follower)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(user, follower)
|
||||
{:ok, _, _, follow_activity_three} = CommonAPI.follow(user, follower_two)
|
||||
|
||||
assert follow_activity.data["state"] == "pending"
|
||||
assert follow_activity_two.data["state"] == "pending"
|
||||
|
|
@ -1521,9 +1522,9 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
follower = insert(:user)
|
||||
follower_two = insert(:user)
|
||||
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
|
||||
{:ok, _, _, follow_activity_three} = CommonAPI.follow(follower_two, user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(user, follower)
|
||||
{:ok, _, _, follow_activity_two} = CommonAPI.follow(user, follower)
|
||||
{:ok, _, _, follow_activity_three} = CommonAPI.follow(user, follower_two)
|
||||
|
||||
assert follow_activity.data["state"] == "pending"
|
||||
assert follow_activity_two.data["state"] == "pending"
|
||||
|
|
@ -1558,9 +1559,9 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
{:ok, _, object} = CommonAPI.vote(other_user, object, [0])
|
||||
{:ok, _, object} = CommonAPI.vote(object, other_user, [0])
|
||||
|
||||
assert {:error, "Already voted"} == CommonAPI.vote(other_user, object, [1])
|
||||
assert {:error, "Already voted"} == CommonAPI.vote(object, other_user, [1])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1694,7 +1695,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do
|
||||
assert {:ok, %Activity{data: %{"type" => "Like"}} = activity} =
|
||||
CommonAPI.favorite(user, activity.id)
|
||||
CommonAPI.favorite(activity.id, user)
|
||||
|
||||
assert Visibility.local_public?(activity)
|
||||
refute called(Pleroma.Web.Federator.publish(activity))
|
||||
|
|
@ -1707,7 +1708,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "cofe", visibility: "local"})
|
||||
|
||||
{:ok, %Activity{}} = CommonAPI.favorite(user, activity.id)
|
||||
{:ok, %Activity{}} = CommonAPI.favorite(activity.id, user)
|
||||
|
||||
with_mock Pleroma.Web.Federator, publish: fn _ -> :ok end do
|
||||
assert {:ok, activity} = CommonAPI.unfavorite(activity.id, user)
|
||||
|
|
@ -1752,7 +1753,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "foo1", spoiler_text: "title 1"})
|
||||
|
||||
{:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2"})
|
||||
{:ok, updated} = CommonAPI.update(activity, user, %{status: "updated 2"})
|
||||
|
||||
updated_object = Object.normalize(updated)
|
||||
assert updated_object.data["content"] == "updated 2"
|
||||
|
|
@ -1766,7 +1767,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{status: "foo1", spoiler_text: "title 1", visibility: "private"})
|
||||
|
||||
{:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2"})
|
||||
{:ok, updated} = CommonAPI.update(activity, user, %{status: "updated 2"})
|
||||
|
||||
updated_object = Object.normalize(updated)
|
||||
assert updated_object.data["content"] == "updated 2"
|
||||
|
|
@ -1783,7 +1784,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{status: "foo1", spoiler_text: "title 1 :#{emoji1}:"})
|
||||
|
||||
{:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2 :#{emoji2}:"})
|
||||
{:ok, updated} = CommonAPI.update(activity, user, %{status: "updated 2 :#{emoji2}:"})
|
||||
|
||||
updated_object = Object.normalize(updated)
|
||||
assert updated_object.data["content"] == "updated 2 :#{emoji2}:"
|
||||
|
|
@ -1802,7 +1803,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
|
||||
with_mock Pleroma.Web.Federator,
|
||||
publish: fn _p -> nil end do
|
||||
{:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2 :#{emoji2}:"})
|
||||
{:ok, updated} = CommonAPI.update(activity, user, %{status: "updated 2 :#{emoji2}:"})
|
||||
|
||||
assert updated.data["object"]["content"] == "updated 2 :#{emoji2}:"
|
||||
assert %{^emoji2 => _} = updated.data["object"]["emoji"]
|
||||
|
|
@ -1846,7 +1847,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
assert reply.object.data["emoji"]["remoteemoji"] == remote_emoji_uri
|
||||
|
||||
{:ok, edit} =
|
||||
CommonAPI.update(user, reply, %{status: "reply mew mew", spoiler_text: ":remoteemoji:"})
|
||||
CommonAPI.update(reply, user, %{status: "reply mew mew", spoiler_text: ":remoteemoji:"})
|
||||
|
||||
edited_note = Pleroma.Object.normalize(edit)
|
||||
|
||||
|
|
@ -1862,7 +1863,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
{:ok, activity} = CommonAPI.post(user, %{status: "foo1", spoiler_text: "updated 1"})
|
||||
assert Object.normalize(activity).data["summary"] == "mewmew 1"
|
||||
|
||||
{:ok, updated} = CommonAPI.update(user, activity, %{status: "updated 2"})
|
||||
{:ok, updated} = CommonAPI.update(activity, user, %{status: "updated 2"})
|
||||
|
||||
updated_object = Object.normalize(updated)
|
||||
assert updated_object.data["content"] == "mewmew 2"
|
||||
|
|
@ -1913,11 +1914,224 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
end
|
||||
|
||||
test "it does not boost if group is blocking poster", %{poster: poster, group: group} do
|
||||
{:ok, _} = CommonAPI.block(group, poster)
|
||||
{:ok, _} = CommonAPI.block(poster, group)
|
||||
{:ok, post} = CommonAPI.post(poster, %{status: "hey @#{group.nickname}"})
|
||||
|
||||
announces = get_announces_of_object(post.object)
|
||||
assert [] = announces
|
||||
end
|
||||
end
|
||||
|
||||
describe "Oban jobs are cancelled" do
|
||||
setup do
|
||||
clear_config([:instance, :federating], true)
|
||||
|
||||
local_user = insert(:user)
|
||||
|
||||
remote_one =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
nickname: "nick1@domain.com",
|
||||
ap_id: "https://domain.com/users/nick1",
|
||||
inbox: "https://domain.com/users/nick1/inbox",
|
||||
shared_inbox: "https://domain.com/inbox"
|
||||
})
|
||||
|
||||
remote_two =
|
||||
insert(:user, %{
|
||||
local: false,
|
||||
nickname: "nick2@example.com",
|
||||
ap_id: "https://example.com/users/nick2",
|
||||
inbox: "https://example.com/users/nick2/inbox",
|
||||
shared_inbox: "https://example.com/inbox"
|
||||
})
|
||||
|
||||
%{local_user: local_user, remote_one: remote_one, remote_two: remote_two}
|
||||
end
|
||||
|
||||
test "when deleting posts", %{
|
||||
local_user: local_user,
|
||||
remote_one: remote_one,
|
||||
remote_two: remote_two
|
||||
} do
|
||||
{:ok, _, _} = Pleroma.User.follow(remote_one, local_user)
|
||||
{:ok, _, _} = Pleroma.User.follow(remote_two, local_user)
|
||||
|
||||
{:ok, %{id: activity_id} = _activity} =
|
||||
CommonAPI.post(local_user, %{status: "Happy Friday everyone!"})
|
||||
|
||||
# Generate the publish_one jobs
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
publish_one_jobs =
|
||||
all_enqueued()
|
||||
|> Enum.filter(fn job ->
|
||||
match?(
|
||||
%{
|
||||
state: "available",
|
||||
queue: "federator_outgoing",
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{"op" => "publish_one", "params" => %{"activity_id" => ^activity_id}}
|
||||
},
|
||||
job
|
||||
)
|
||||
end)
|
||||
|
||||
assert length(publish_one_jobs) == 2
|
||||
|
||||
# The delete should have triggered cancelling the publish_one jobs
|
||||
assert {:ok, _delete} = CommonAPI.delete(activity_id, local_user)
|
||||
|
||||
# all_enqueued/1 will not return cancelled jobs
|
||||
cancelled_jobs =
|
||||
Oban.Job
|
||||
|> where([j], j.worker == "Pleroma.Workers.PublisherWorker")
|
||||
|> where([j], j.state == "cancelled")
|
||||
|> where([j], j.args["op"] == "publish_one")
|
||||
|> where([j], j.args["params"]["activity_id"] == ^activity_id)
|
||||
|> Pleroma.Repo.all()
|
||||
|
||||
assert length(cancelled_jobs) == 2
|
||||
end
|
||||
|
||||
test "when unfavoriting posts", %{
|
||||
local_user: local_user,
|
||||
remote_one: remote_user
|
||||
} do
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(remote_user, %{status: "I like turtles!"})
|
||||
|
||||
{:ok, %{id: favorite_id} = _favorite} =
|
||||
CommonAPI.favorite(activity.id, local_user)
|
||||
|
||||
# Generate the publish_one jobs
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
publish_one_jobs =
|
||||
all_enqueued()
|
||||
|> Enum.filter(fn job ->
|
||||
match?(
|
||||
%{
|
||||
state: "available",
|
||||
queue: "federator_outgoing",
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{"op" => "publish_one", "params" => %{"activity_id" => ^favorite_id}}
|
||||
},
|
||||
job
|
||||
)
|
||||
end)
|
||||
|
||||
assert length(publish_one_jobs) == 1
|
||||
|
||||
# The unfavorite should have triggered cancelling the publish_one jobs
|
||||
assert {:ok, _unfavorite} = CommonAPI.unfavorite(activity.id, local_user)
|
||||
|
||||
# all_enqueued/1 will not return cancelled jobs
|
||||
cancelled_jobs =
|
||||
Oban.Job
|
||||
|> where([j], j.worker == "Pleroma.Workers.PublisherWorker")
|
||||
|> where([j], j.state == "cancelled")
|
||||
|> where([j], j.args["op"] == "publish_one")
|
||||
|> where([j], j.args["params"]["activity_id"] == ^favorite_id)
|
||||
|> Pleroma.Repo.all()
|
||||
|
||||
assert length(cancelled_jobs) == 1
|
||||
end
|
||||
|
||||
test "when unboosting posts", %{
|
||||
local_user: local_user,
|
||||
remote_one: remote_one,
|
||||
remote_two: remote_two
|
||||
} do
|
||||
{:ok, _, _} = Pleroma.User.follow(remote_one, local_user)
|
||||
{:ok, _, _} = Pleroma.User.follow(remote_two, local_user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(remote_one, %{status: "This is an unpleasant post"})
|
||||
|
||||
{:ok, %{id: repeat_id} = _repeat} =
|
||||
CommonAPI.repeat(activity.id, local_user)
|
||||
|
||||
# Generate the publish_one jobs
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
publish_one_jobs =
|
||||
all_enqueued()
|
||||
|> Enum.filter(fn job ->
|
||||
match?(
|
||||
%{
|
||||
state: "available",
|
||||
queue: "federator_outgoing",
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{"op" => "publish_one", "params" => %{"activity_id" => ^repeat_id}}
|
||||
},
|
||||
job
|
||||
)
|
||||
end)
|
||||
|
||||
assert length(publish_one_jobs) == 2
|
||||
|
||||
# The unrepeat should have triggered cancelling the publish_one jobs
|
||||
assert {:ok, _unfavorite} = CommonAPI.unrepeat(activity.id, local_user)
|
||||
|
||||
# all_enqueued/1 will not return cancelled jobs
|
||||
cancelled_jobs =
|
||||
Oban.Job
|
||||
|> where([j], j.worker == "Pleroma.Workers.PublisherWorker")
|
||||
|> where([j], j.state == "cancelled")
|
||||
|> where([j], j.args["op"] == "publish_one")
|
||||
|> where([j], j.args["params"]["activity_id"] == ^repeat_id)
|
||||
|> Pleroma.Repo.all()
|
||||
|
||||
assert length(cancelled_jobs) == 2
|
||||
end
|
||||
|
||||
test "when unreacting to posts", %{
|
||||
local_user: local_user,
|
||||
remote_one: remote_one,
|
||||
remote_two: remote_two
|
||||
} do
|
||||
{:ok, _, _} = Pleroma.User.follow(remote_one, local_user)
|
||||
{:ok, _, _} = Pleroma.User.follow(remote_two, local_user)
|
||||
|
||||
{:ok, %{id: activity_id}} =
|
||||
CommonAPI.post(remote_one, %{status: "Gang gang!!!!"})
|
||||
|
||||
{:ok, %{id: react_id} = _react} =
|
||||
CommonAPI.react_with_emoji(activity_id, local_user, "👍")
|
||||
|
||||
# Generate the publish_one jobs
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
publish_one_jobs =
|
||||
all_enqueued()
|
||||
|> Enum.filter(fn job ->
|
||||
match?(
|
||||
%{
|
||||
state: "available",
|
||||
queue: "federator_outgoing",
|
||||
worker: "Pleroma.Workers.PublisherWorker",
|
||||
args: %{"op" => "publish_one", "params" => %{"activity_id" => ^react_id}}
|
||||
},
|
||||
job
|
||||
)
|
||||
end)
|
||||
|
||||
assert length(publish_one_jobs) == 2
|
||||
|
||||
# The unreact should have triggered cancelling the publish_one jobs
|
||||
assert {:ok, _unreact} = CommonAPI.unreact_with_emoji(activity_id, local_user, "👍")
|
||||
|
||||
# all_enqueued/1 will not return cancelled jobs
|
||||
cancelled_jobs =
|
||||
Oban.Job
|
||||
|> where([j], j.worker == "Pleroma.Workers.PublisherWorker")
|
||||
|> where([j], j.state == "cancelled")
|
||||
|> where([j], j.args["op"] == "publish_one")
|
||||
|> where([j], j.args["params"]["activity_id"] == ^react_id)
|
||||
|> Pleroma.Repo.all()
|
||||
|
||||
assert length(cancelled_jobs) == 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ defmodule Pleroma.Web.FallbackTest do
|
|||
resp = get(conn, "/foo")
|
||||
|
||||
assert html_response(resp, 200) =~ "<title>a cool title</title>"
|
||||
refute html_response(resp, 200) =~ "initial-results"
|
||||
assert html_response(resp, 200) =~ "<meta content=\"noindex, noarchive\" name=\"robots\">"
|
||||
end
|
||||
|
||||
test "GET /*path", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -55,11 +55,11 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
|
|||
|
||||
xml = parse(response)
|
||||
|
||||
assert xpath(xml, ~x"//feed/title/text()") == '#pleromaart'
|
||||
assert xpath(xml, ~x"//feed/title/text()") == ~c"#pleromaart"
|
||||
|
||||
assert xpath(xml, ~x"//feed/entry/title/text()"l) == [
|
||||
'42 This is :moominmamm...',
|
||||
'yeah #PleromaArt'
|
||||
~c"42 This is :moominmamm...",
|
||||
~c"yeah #PleromaArt"
|
||||
]
|
||||
|
||||
assert xpath(xml, ~x"//feed/entry/author/name/text()"ls) == [user.nickname, user.nickname]
|
||||
|
|
@ -73,10 +73,10 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
|
|||
resp = response(conn, 200)
|
||||
xml = parse(resp)
|
||||
|
||||
assert xpath(xml, ~x"//feed/title/text()") == '#pleromaart'
|
||||
assert xpath(xml, ~x"//feed/title/text()") == ~c"#pleromaart"
|
||||
|
||||
assert xpath(xml, ~x"//feed/entry/title/text()"l) == [
|
||||
'yeah #PleromaArt'
|
||||
~c"yeah #PleromaArt"
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -120,20 +120,20 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
|
|||
|> response(200)
|
||||
|
||||
xml = parse(response)
|
||||
assert xpath(xml, ~x"//channel/title/text()") == '#pleromaart'
|
||||
assert xpath(xml, ~x"//channel/title/text()") == ~c"#pleromaart"
|
||||
|
||||
assert xpath(xml, ~x"//channel/description/text()"s) ==
|
||||
"These are public toots tagged with #pleromaart. You can interact with them if you have an account anywhere in the fediverse."
|
||||
|
||||
assert xpath(xml, ~x"//channel/link/text()") ==
|
||||
'#{Pleroma.Web.Endpoint.url()}/tags/pleromaart.rss'
|
||||
~c"#{Pleroma.Web.Endpoint.url()}/tags/pleromaart.rss"
|
||||
|
||||
assert xpath(xml, ~x"//channel/webfeeds:logo/text()") ==
|
||||
'#{Pleroma.Web.Endpoint.url()}/static/logo.svg'
|
||||
~c"#{Pleroma.Web.Endpoint.url()}/static/logo.svg"
|
||||
|
||||
assert xpath(xml, ~x"//channel/item/title/text()"l) == [
|
||||
'42 This is :moominmamm...',
|
||||
'yeah #PleromaArt'
|
||||
~c"42 This is :moominmamm...",
|
||||
~c"yeah #PleromaArt"
|
||||
]
|
||||
|
||||
assert xpath(xml, ~x"//channel/item/pubDate/text()"sl) == [
|
||||
|
|
@ -160,7 +160,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
|
|||
|> response(200)
|
||||
|
||||
xml = parse(response)
|
||||
assert xpath(xml, ~x"//channel/title/text()") == '#pleromaart'
|
||||
assert xpath(xml, ~x"//channel/title/text()") == ~c"#pleromaart"
|
||||
|
||||
assert xpath(xml, ~x"//channel/description/text()"s) ==
|
||||
"These are public toots tagged with #pleromaart. You can interact with them if you have an account anywhere in the fediverse."
|
||||
|
|
@ -174,10 +174,10 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
|
|||
resp = response(conn, 200)
|
||||
xml = parse(resp)
|
||||
|
||||
assert xpath(xml, ~x"//channel/title/text()") == '#pleromaart'
|
||||
assert xpath(xml, ~x"//channel/title/text()") == ~c"#pleromaart"
|
||||
|
||||
assert xpath(xml, ~x"//channel/item/title/text()"l) == [
|
||||
'yeah #PleromaArt'
|
||||
~c"yeah #PleromaArt"
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -191,4 +191,60 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
|
|||
|> response(404)
|
||||
end
|
||||
end
|
||||
|
||||
describe "restricted for unauthenticated" do
|
||||
test "returns 404 when local timeline is disabled", %{conn: conn} do
|
||||
clear_config([:restrict_unauthenticated, :timelines], %{local: true, federated: false})
|
||||
|
||||
conn
|
||||
|> put_req_header("accept", "application/rss+xml")
|
||||
|> get(tag_feed_path(conn, :feed, "pleromaart.rss"))
|
||||
|> response(404)
|
||||
end
|
||||
|
||||
test "returns local posts only when federated timeline is disabled", %{conn: conn} do
|
||||
clear_config([:restrict_unauthenticated, :timelines], %{local: false, federated: true})
|
||||
|
||||
local_user = insert(:user)
|
||||
remote_user = insert(:user, local: false)
|
||||
|
||||
local_note =
|
||||
insert(:note,
|
||||
user: local_user,
|
||||
data: %{
|
||||
"content" => "local post #PleromaArt",
|
||||
"summary" => "",
|
||||
"tag" => ["pleromaart"]
|
||||
}
|
||||
)
|
||||
|
||||
remote_note =
|
||||
insert(:note,
|
||||
user: remote_user,
|
||||
data: %{
|
||||
"content" => "remote post #PleromaArt",
|
||||
"summary" => "",
|
||||
"tag" => ["pleromaart"]
|
||||
},
|
||||
local: false
|
||||
)
|
||||
|
||||
insert(:note_activity, user: local_user, note: local_note)
|
||||
insert(:note_activity, user: remote_user, note: remote_note, local: false)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("accept", "application/rss+xml")
|
||||
|> get(tag_feed_path(conn, :feed, "pleromaart.rss"))
|
||||
|> response(200)
|
||||
|
||||
xml = parse(response)
|
||||
|
||||
assert xpath(xml, ~x"//channel/title/text()") == ~c"#pleromaart"
|
||||
|
||||
assert xpath(xml, ~x"//channel/item/title/text()"l) == [
|
||||
~c"local post #PleromaArt"
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
|||
|> SweetXml.parse()
|
||||
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||
|
||||
assert activity_titles == ['Won\'t, didn\'...', '2hu', '2hu & as']
|
||||
assert activity_titles == [~c"Won't, didn'...", ~c"2hu", ~c"2hu & as"]
|
||||
assert resp =~ FeedView.escape(object.data["content"])
|
||||
assert resp =~ FeedView.escape(object.data["summary"])
|
||||
assert resp =~ FeedView.escape(object.data["context"])
|
||||
|
|
@ -104,7 +104,7 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
|||
|> SweetXml.parse()
|
||||
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||
|
||||
assert activity_titles == ['2hu & as']
|
||||
assert activity_titles == [~c"2hu & as"]
|
||||
end
|
||||
|
||||
test "gets a rss feed", %{conn: conn, user: user, object: object, max_id: max_id} do
|
||||
|
|
@ -119,7 +119,7 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
|||
|> SweetXml.parse()
|
||||
|> SweetXml.xpath(~x"//item/title/text()"l)
|
||||
|
||||
assert activity_titles == ['Won\'t, didn\'...', '2hu', '2hu & as']
|
||||
assert activity_titles == [~c"Won't, didn'...", ~c"2hu", ~c"2hu & as"]
|
||||
assert resp =~ FeedView.escape(object.data["content"])
|
||||
assert resp =~ FeedView.escape(object.data["summary"])
|
||||
assert resp =~ FeedView.escape(object.data["context"])
|
||||
|
|
@ -135,7 +135,7 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
|||
|> SweetXml.parse()
|
||||
|> SweetXml.xpath(~x"//item/title/text()"l)
|
||||
|
||||
assert activity_titles == ['2hu & as']
|
||||
assert activity_titles == [~c"2hu & as"]
|
||||
end
|
||||
|
||||
test "returns 404 for a missing feed", %{conn: conn} do
|
||||
|
|
@ -147,6 +147,15 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
|||
assert response(conn, 404)
|
||||
end
|
||||
|
||||
test "returns noindex meta for missing user", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("accept", "text/html")
|
||||
|> get("/users/nonexisting")
|
||||
|
||||
assert html_response(conn, 200) =~ "<meta content=\"noindex, noarchive\" name=\"robots\">"
|
||||
end
|
||||
|
||||
test "returns feed with public and unlisted activities", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
@ -167,7 +176,7 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
|||
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||
|> Enum.sort()
|
||||
|
||||
assert activity_titles == ['public', 'unlisted']
|
||||
assert activity_titles == [~c"public", ~c"unlisted"]
|
||||
end
|
||||
|
||||
test "returns 404 when the user is remote", %{conn: conn} do
|
||||
|
|
@ -208,7 +217,7 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
|||
|> SweetXml.parse()
|
||||
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||
|
||||
assert activity_titles == ['Won\'t, didn\'...', '2hu', '2hu & as']
|
||||
assert activity_titles == [~c"Won't, didn'...", ~c"2hu", ~c"2hu & as"]
|
||||
assert resp =~ FeedView.escape(object.data["content"])
|
||||
assert resp =~ FeedView.escape(object.data["summary"])
|
||||
assert resp =~ FeedView.escape(object.data["context"])
|
||||
|
|
|
|||
|
|
@ -1120,7 +1120,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
|> json_response_and_validate_schema(200)
|
||||
|
||||
# Follow the user, then the pinned status can be seen
|
||||
CommonAPI.follow(reader, user)
|
||||
CommonAPI.follow(user, reader)
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
assert [%{"id" => ^activity_id, "pinned" => true}] =
|
||||
|
|
@ -2118,7 +2118,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
test "pin account", %{user: user, conn: conn} do
|
||||
%{id: id1} = other_user1 = insert(:user)
|
||||
|
||||
CommonAPI.follow(user, other_user1)
|
||||
CommonAPI.follow(other_user1, user)
|
||||
|
||||
assert %{"id" => ^id1, "endorsed" => true} =
|
||||
conn
|
||||
|
|
@ -2136,7 +2136,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
test "unpin account", %{user: user, conn: conn} do
|
||||
%{id: id1} = other_user1 = insert(:user)
|
||||
|
||||
CommonAPI.follow(user, other_user1)
|
||||
CommonAPI.follow(other_user1, user)
|
||||
User.endorse(user, other_user1)
|
||||
|
||||
assert %{"id" => ^id1, "endorsed" => false} =
|
||||
|
|
@ -2156,8 +2156,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
%{id: id1} = other_user1 = insert(:user)
|
||||
%{id: id2} = other_user2 = insert(:user)
|
||||
|
||||
CommonAPI.follow(user, other_user1)
|
||||
CommonAPI.follow(user, other_user2)
|
||||
CommonAPI.follow(other_user1, user)
|
||||
CommonAPI.follow(other_user2, user)
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|
|
@ -2172,13 +2172,62 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "familiar followers" do
|
||||
setup do: oauth_access(["read:follows"])
|
||||
|
||||
test "fetch user familiar followers", %{user: user, conn: conn} do
|
||||
%{id: id1} = other_user1 = insert(:user)
|
||||
%{id: id2} = other_user2 = insert(:user)
|
||||
_ = insert(:user)
|
||||
|
||||
User.follow(user, other_user1)
|
||||
User.follow(other_user1, other_user2)
|
||||
|
||||
assert [%{"accounts" => [%{"id" => ^id1}], "id" => ^id2}] =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> get("/api/v1/accounts/familiar_followers?id[]=#{id2}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
|
||||
test "returns empty array if followers are hidden", %{user: user, conn: conn} do
|
||||
other_user1 = insert(:user, hide_follows: true)
|
||||
%{id: id2} = other_user2 = insert(:user)
|
||||
_ = insert(:user)
|
||||
|
||||
User.follow(user, other_user1)
|
||||
User.follow(other_user1, other_user2)
|
||||
|
||||
assert [%{"accounts" => [], "id" => ^id2}] =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> get("/api/v1/accounts/familiar_followers?id[]=#{id2}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
|
||||
test "it respects hide_followers", %{user: user, conn: conn} do
|
||||
other_user1 = insert(:user)
|
||||
%{id: id2} = other_user2 = insert(:user, hide_followers: true)
|
||||
_ = insert(:user)
|
||||
|
||||
User.follow(user, other_user1)
|
||||
User.follow(other_user1, other_user2)
|
||||
|
||||
assert [%{"accounts" => [], "id" => ^id2}] =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> get("/api/v1/accounts/familiar_followers?id[]=#{id2}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe "remove from followers" do
|
||||
setup do: oauth_access(["follow"])
|
||||
|
||||
test "removing user from followers", %{conn: conn, user: user} do
|
||||
%{id: other_user_id} = other_user = insert(:user)
|
||||
|
||||
CommonAPI.follow(other_user, user)
|
||||
CommonAPI.follow(user, other_user)
|
||||
|
||||
assert %{"id" => ^other_user_id, "followed_by" => false} =
|
||||
conn
|
||||
|
|
@ -2191,7 +2240,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
test "removing remote user from followers", %{conn: conn, user: user} do
|
||||
%{id: other_user_id} = other_user = insert(:user, local: false)
|
||||
|
||||
CommonAPI.follow(other_user, user)
|
||||
CommonAPI.follow(user, other_user)
|
||||
|
||||
assert User.following?(other_user, user)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
|
|||
test "/api/v1/follow_requests works", %{user: user, conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(user, other_user)
|
||||
{:ok, other_user, user} = User.follow(other_user, user, :follow_pending)
|
||||
|
||||
assert User.following?(other_user, user) == false
|
||||
|
|
@ -34,7 +34,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
|
|||
test "/api/v1/follow_requests/:id/authorize works", %{user: user, conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(user, other_user)
|
||||
{:ok, other_user, user} = User.follow(other_user, user, :follow_pending)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
|
@ -56,7 +56,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do
|
|||
test "/api/v1/follow_requests/:id/reject works", %{user: user, conn: conn} do
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, _, _, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@
|
|||
defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "GET /api/v1/markers" do
|
||||
|
|
@ -127,5 +131,36 @@ defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do
|
|||
|
||||
assert response == %{"error" => "Insufficient permissions: write:statuses."}
|
||||
end
|
||||
|
||||
test "marks notifications as read", %{conn: conn} do
|
||||
user1 = insert(:user)
|
||||
token = insert(:oauth_token, user: user1, scopes: ["write:statuses"])
|
||||
|
||||
user2 = insert(:user)
|
||||
{:ok, _activity1} = CommonAPI.post(user2, %{status: "hi @#{user1.nickname}"})
|
||||
{:ok, _activity2} = CommonAPI.post(user2, %{status: "hi @#{user1.nickname}"})
|
||||
{:ok, _activity3} = CommonAPI.post(user2, %{status: "HIE @#{user1.nickname}"})
|
||||
|
||||
[notification3, notification2, notification1] = Notification.for_user(user1, %{limit: 3})
|
||||
|
||||
refute Repo.get(Notification, notification1.id).seen
|
||||
refute Repo.get(Notification, notification2.id).seen
|
||||
refute Repo.get(Notification, notification3.id).seen
|
||||
|
||||
conn
|
||||
|> assign(:user, user1)
|
||||
|> assign(:token, token)
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/markers", %{
|
||||
notifications: %{last_read_id: to_string(notification2.id)}
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
[notification3, notification2, notification1] = Notification.for_user(user1, %{limit: 3})
|
||||
|
||||
assert Repo.get(Notification, notification1.id).seen
|
||||
assert Repo.get(Notification, notification2.id).seen
|
||||
refute Repo.get(Notification, notification3.id).seen
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
|
|||
conn
|
||||
|> put_req_header("content-type", "multipart/form-data")
|
||||
|> post("/api/v2/media", %{"file" => image, "description" => desc})
|
||||
|> json_response_and_validate_schema(202)
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert media_id = response["id"]
|
||||
|
||||
|
|
@ -76,6 +76,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
|
|||
end
|
||||
|
||||
test "/api/v2/media, upload_limit", %{conn: conn, user: user} do
|
||||
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||
desc = "Description of the binary"
|
||||
|
||||
upload_limit = Config.get([:instance, :upload_limit]) * 8 + 8
|
||||
|
|
@ -110,7 +111,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
|
|||
"file" => large_binary,
|
||||
"description" => desc
|
||||
})
|
||||
|> json_response_and_validate_schema(202)
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert media_id = response["id"]
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
blocker = insert(:user)
|
||||
|
||||
{:ok, _} = CommonAPI.block(blocker, user)
|
||||
{:ok, _} = CommonAPI.block(user, blocker)
|
||||
{:ok, activity} = CommonAPI.post(blocker, %{status: "hi @#{user.nickname}"})
|
||||
|
||||
{:ok, [_notification]} = Notification.create_notifications(activity)
|
||||
|
|
@ -326,10 +326,10 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
|
||||
{:ok, private_activity} = CommonAPI.post(other_user, %{status: ".", visibility: "private"})
|
||||
|
||||
{:ok, _} = CommonAPI.favorite(user, public_activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(user, direct_activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(user, unlisted_activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(user, private_activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(public_activity.id, user)
|
||||
{:ok, _} = CommonAPI.favorite(direct_activity.id, user)
|
||||
{:ok, _} = CommonAPI.favorite(unlisted_activity.id, user)
|
||||
{:ok, _} = CommonAPI.favorite(private_activity.id, user)
|
||||
|
||||
activity_ids =
|
||||
conn
|
||||
|
|
@ -414,7 +414,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
{:ok, _favorite} = CommonAPI.favorite(user, reply.id)
|
||||
{:ok, _favorite} = CommonAPI.favorite(reply.id, user)
|
||||
|
||||
activity_ids =
|
||||
conn
|
||||
|
|
@ -432,9 +432,9 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
|
||||
{:ok, mention_activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"})
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(create_activity.id, other_user)
|
||||
{:ok, reblog_activity} = CommonAPI.repeat(create_activity.id, other_user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
mention_notification_id = get_notification_id_by_activity(mention_activity)
|
||||
favorite_notification_id = get_notification_id_by_activity(favorite_activity)
|
||||
|
|
@ -470,9 +470,9 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
|
||||
{:ok, mention_activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"})
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(other_user, create_activity.id)
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(create_activity.id, other_user)
|
||||
{:ok, reblog_activity} = CommonAPI.repeat(create_activity.id, other_user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
mention_notification_id = get_notification_id_by_activity(mention_activity)
|
||||
favorite_notification_id = get_notification_id_by_activity(favorite_activity)
|
||||
|
|
@ -517,9 +517,9 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
|
||||
{:ok, _activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"})
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, _activity} = CommonAPI.favorite(other_user, create_activity.id)
|
||||
{:ok, _activity} = CommonAPI.favorite(create_activity.id, other_user)
|
||||
{:ok, _activity} = CommonAPI.repeat(create_activity.id, other_user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
||||
|
||||
|
|
@ -578,7 +578,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
user2 = insert(:user)
|
||||
|
||||
{:ok, _, _, _} = CommonAPI.follow(user, user2)
|
||||
{:ok, _, _, _} = CommonAPI.follow(user2, user)
|
||||
{:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
ret_conn = get(conn, "/api/v1/notifications")
|
||||
|
|
@ -596,7 +596,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
user2 = insert(:user)
|
||||
|
||||
{:ok, _, _, _} = CommonAPI.follow(user, user2)
|
||||
{:ok, _, _, _} = CommonAPI.follow(user2, user)
|
||||
{:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
ret_conn = get(conn, "/api/v1/notifications")
|
||||
|
|
@ -614,7 +614,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
user2 = insert(:user)
|
||||
|
||||
{:ok, _, _, _} = CommonAPI.follow(user, user2)
|
||||
{:ok, _, _, _} = CommonAPI.follow(user2, user)
|
||||
{:ok, _} = CommonAPI.post(user2, %{status: "hey @#{user.nickname}"})
|
||||
|
||||
ret_conn = get(conn, "/api/v1/notifications")
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Object
|
||||
|
|
@ -27,6 +28,33 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
|
|||
response = json_response_and_validate_schema(conn, 200)
|
||||
id = to_string(object.id)
|
||||
assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
|
||||
|
||||
# Local activities should not generate an Oban job to refresh
|
||||
assert activity.local
|
||||
|
||||
refute_enqueued(
|
||||
worker: Pleroma.Workers.PollWorker,
|
||||
args: %{"op" => "refresh", "activity_id" => activity.id}
|
||||
)
|
||||
end
|
||||
|
||||
test "creates an oban job to refresh poll if activity is remote", %{conn: conn} do
|
||||
user = insert(:user, local: false)
|
||||
question = insert(:question, user: user)
|
||||
activity = insert(:question_activity, question: question, local: false)
|
||||
|
||||
# Ensure this is not represented as a local activity
|
||||
refute activity.local
|
||||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
get(conn, "/api/v1/polls/#{object.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.PollWorker,
|
||||
args: %{"op" => "refresh", "activity_id" => activity.id}
|
||||
)
|
||||
end
|
||||
|
||||
test "does not expose polls for private statuses", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
alias Pleroma.Repo
|
||||
|
|
@ -78,7 +79,7 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
|
|||
}
|
||||
)
|
||||
|
||||
job = Repo.one(from(j in Oban.Job, where: j.queue == "scheduled_activities"))
|
||||
job = Repo.one(from(j in Oban.Job, where: j.queue == "federator_outgoing"))
|
||||
|
||||
assert job.args == %{"activity_id" => scheduled_activity.id}
|
||||
assert DateTime.truncate(job.scheduled_at, :second) == to_datetime(scheduled_at)
|
||||
|
|
@ -124,9 +125,11 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
|
|||
}
|
||||
)
|
||||
|
||||
job = Repo.one(from(j in Oban.Job, where: j.queue == "scheduled_activities"))
|
||||
|
||||
assert job.args == %{"activity_id" => scheduled_activity.id}
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.ScheduledActivityWorker,
|
||||
args: %{"activity_id" => scheduled_activity.id},
|
||||
queue: :federator_outgoing
|
||||
)
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|
|
@ -135,7 +138,11 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do
|
|||
|
||||
assert %{} = json_response_and_validate_schema(res_conn, 200)
|
||||
refute Repo.get(ScheduledActivity, scheduled_activity.id)
|
||||
refute Repo.get(Oban.Job, job.id)
|
||||
|
||||
refute_enqueued(
|
||||
worker: Pleroma.Workers.ScheduledActivityWorker,
|
||||
args: %{"activity_id" => scheduled_activity.id}
|
||||
)
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
|
|||
assert [] = results["statuses"]
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "constructs hashtags from search query", %{conn: conn} do
|
||||
results =
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -235,6 +235,16 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
assert Activity.get_in_reply_to_activity(activity).id == replied_to.id
|
||||
end
|
||||
|
||||
test "replying to a deleted status", %{user: user, conn: conn} do
|
||||
{:ok, status} = CommonAPI.post(user, %{status: "cofe"})
|
||||
{:ok, _deleted_status} = CommonAPI.delete(status.id, user)
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => status.id})
|
||||
|> json_response_and_validate_schema(422)
|
||||
end
|
||||
|
||||
test "replying to a direct message with visibility other than direct", %{
|
||||
user: user,
|
||||
conn: conn
|
||||
|
|
@ -912,13 +922,23 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
%{id: id1} = insert(:note_activity)
|
||||
%{id: id2} = insert(:note_activity)
|
||||
|
||||
query_string = "ids[]=#{id1}&ids[]=#{id2}"
|
||||
query_string = "id[]=#{id1}&id[]=#{id2}"
|
||||
conn = get(conn, "/api/v1/statuses/?#{query_string}")
|
||||
|
||||
assert [%{"id" => ^id1}, %{"id" => ^id2}] =
|
||||
Enum.sort_by(json_response_and_validate_schema(conn, :ok), & &1["id"])
|
||||
end
|
||||
|
||||
test "get statuses by IDs falls back to ids[]" do
|
||||
%{conn: conn} = oauth_access(["read:statuses"])
|
||||
%{id: id} = insert(:note_activity)
|
||||
|
||||
query_string = "ids[]=#{id}"
|
||||
conn = get(conn, "/api/v1/statuses/?#{query_string}")
|
||||
|
||||
assert [%{"id" => ^id}] = json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
|
||||
describe "getting statuses by ids with restricted unauthenticated for local and remote" do
|
||||
setup do: local_and_remote_activities()
|
||||
|
||||
|
|
@ -927,7 +947,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
|
||||
|
||||
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
|
||||
res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
|
||||
res_conn = get(conn, "/api/v1/statuses?id[]=#{local.id}&id[]=#{remote.id}")
|
||||
|
||||
assert json_response_and_validate_schema(res_conn, 200) == []
|
||||
end
|
||||
|
|
@ -935,7 +955,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
test "if user is authenticated", %{local: local, remote: remote} do
|
||||
%{conn: conn} = oauth_access(["read"])
|
||||
|
||||
res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
|
||||
res_conn = get(conn, "/api/v1/statuses?id[]=#{local.id}&id[]=#{remote.id}")
|
||||
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 2
|
||||
end
|
||||
|
|
@ -947,7 +967,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
setup do: clear_config([:restrict_unauthenticated, :activities, :local], true)
|
||||
|
||||
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
|
||||
res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
|
||||
res_conn = get(conn, "/api/v1/statuses?id[]=#{local.id}&id[]=#{remote.id}")
|
||||
|
||||
remote_id = remote.id
|
||||
assert [%{"id" => ^remote_id}] = json_response_and_validate_schema(res_conn, 200)
|
||||
|
|
@ -956,7 +976,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
test "if user is authenticated", %{local: local, remote: remote} do
|
||||
%{conn: conn} = oauth_access(["read"])
|
||||
|
||||
res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
|
||||
res_conn = get(conn, "/api/v1/statuses?id[]=#{local.id}&id[]=#{remote.id}")
|
||||
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 2
|
||||
end
|
||||
|
|
@ -968,7 +988,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
|
||||
|
||||
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
|
||||
res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
|
||||
res_conn = get(conn, "/api/v1/statuses?id[]=#{local.id}&id[]=#{remote.id}")
|
||||
|
||||
local_id = local.id
|
||||
assert [%{"id" => ^local_id}] = json_response_and_validate_schema(res_conn, 200)
|
||||
|
|
@ -977,7 +997,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
test "if user is authenticated", %{local: local, remote: remote} do
|
||||
%{conn: conn} = oauth_access(["read"])
|
||||
|
||||
res_conn = get(conn, "/api/v1/statuses?ids[]=#{local.id}&ids[]=#{remote.id}")
|
||||
res_conn = get(conn, "/api/v1/statuses?id[]=#{local.id}&id[]=#{remote.id}")
|
||||
|
||||
assert length(json_response_and_validate_schema(res_conn, 200)) == 2
|
||||
end
|
||||
|
|
@ -1346,7 +1366,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
user1 = insert(:user)
|
||||
user2 = insert(:user)
|
||||
user3 = insert(:user)
|
||||
{:ok, _} = CommonAPI.favorite(user2, activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(activity.id, user2)
|
||||
{:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id)
|
||||
{:ok, reblog_activity1} = CommonAPI.repeat(activity.id, user1)
|
||||
{:ok, _} = CommonAPI.repeat(activity.id, user2)
|
||||
|
|
@ -1473,7 +1493,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
test "unfavorites a status and returns it", %{user: user, conn: conn} do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
{:ok, _} = CommonAPI.favorite(user, activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(activity.id, user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|
|
@ -1761,7 +1781,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
end
|
||||
|
||||
test "cannot mute already muted conversation", %{conn: conn, user: user, activity: activity} do
|
||||
{:ok, _} = CommonAPI.add_mute(user, activity)
|
||||
{:ok, _} = CommonAPI.add_mute(activity, user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|
|
@ -1774,7 +1794,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
end
|
||||
|
||||
test "unmute conversation", %{conn: conn, user: user, activity: activity} do
|
||||
{:ok, _} = CommonAPI.add_mute(user, activity)
|
||||
{:ok, _} = CommonAPI.add_mute(activity, user)
|
||||
|
||||
id_str = to_string(activity.id)
|
||||
|
||||
|
|
@ -1849,7 +1869,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|
||||
test "returns users who have favorited the status", %{conn: conn, activity: activity} do
|
||||
other_user = insert(:user)
|
||||
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(activity.id, other_user)
|
||||
|
||||
response =
|
||||
conn
|
||||
|
|
@ -1880,7 +1900,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
other_user = insert(:user)
|
||||
{:ok, _user_relationship} = User.block(user, other_user)
|
||||
|
||||
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(activity.id, other_user)
|
||||
|
||||
response =
|
||||
conn
|
||||
|
|
@ -1892,7 +1912,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|
||||
test "does not fail on an unauthenticated request", %{activity: activity} do
|
||||
other_user = insert(:user)
|
||||
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(activity.id, other_user)
|
||||
|
||||
response =
|
||||
build_conn()
|
||||
|
|
@ -1912,7 +1932,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
visibility: "direct"
|
||||
})
|
||||
|
||||
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(activity.id, other_user)
|
||||
|
||||
favourited_by_url = "/api/v1/statuses/#{activity.id}/favourited_by"
|
||||
|
||||
|
|
@ -1943,7 +1963,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
clear_config([:instance, :show_reactions], false)
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, _} = CommonAPI.favorite(other_user, activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(activity.id, other_user)
|
||||
|
||||
response =
|
||||
conn
|
||||
|
|
@ -2086,9 +2106,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
{:ok, second_post} = CommonAPI.post(other_user, %{status: "bla"})
|
||||
{:ok, third_post} = CommonAPI.post(other_user, %{status: "bla"})
|
||||
|
||||
{:ok, _first_favorite} = CommonAPI.favorite(user, third_post.id)
|
||||
{:ok, _second_favorite} = CommonAPI.favorite(user, first_post.id)
|
||||
{:ok, third_favorite} = CommonAPI.favorite(user, second_post.id)
|
||||
{:ok, _first_favorite} = CommonAPI.favorite(third_post.id, user)
|
||||
{:ok, _second_favorite} = CommonAPI.favorite(first_post.id, user)
|
||||
{:ok, third_favorite} = CommonAPI.favorite(second_post.id, user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|
|
@ -2124,7 +2144,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
{:ok, _} = CommonAPI.post(other_user, %{status: "bla"})
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{status: "trees are happy"})
|
||||
|
||||
{:ok, last_like} = CommonAPI.favorite(user, activity.id)
|
||||
{:ok, last_like} = CommonAPI.favorite(activity.id, user)
|
||||
|
||||
first_conn = get(conn, "/api/v1/favourites")
|
||||
|
||||
|
|
@ -2140,7 +2160,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
status: "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
|
||||
})
|
||||
|
||||
{:ok, _} = CommonAPI.favorite(user, second_activity.id)
|
||||
{:ok, _} = CommonAPI.favorite(second_activity.id, user)
|
||||
|
||||
second_conn = get(conn, "/api/v1/favourites?since_id=#{last_like.id}")
|
||||
|
||||
|
|
@ -2231,7 +2251,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/statuses/?ids[]=#{activity.id}")
|
||||
|> get("/api/v1/statuses/?id[]=#{activity.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
|
|
@ -2244,7 +2264,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/statuses/?ids[]=#{activity.id}&with_muted=true")
|
||||
|> get("/api/v1/statuses/?id[]=#{activity.id}&with_muted=true")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
|
|||
|
||||
test "returns v2 suggestions excluding blocked accounts", %{conn: conn, user: blocker} do
|
||||
blocked = insert(:user, is_suggested: true)
|
||||
{:ok, _} = CommonAPI.block(blocker, blocked)
|
||||
{:ok, _} = CommonAPI.block(blocked, blocker)
|
||||
|
||||
res =
|
||||
conn
|
||||
|
|
@ -59,7 +59,7 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
|
|||
|
||||
test "returns v2 suggestions excluding followed accounts", %{conn: conn, user: follower} do
|
||||
followed = insert(:user, is_suggested: true)
|
||||
{:ok, _, _, _} = CommonAPI.follow(follower, followed)
|
||||
{:ok, _, _, _} = CommonAPI.follow(followed, follower)
|
||||
|
||||
res =
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -0,0 +1,159 @@
|
|||
defmodule Pleroma.Web.MastodonAPI.TagControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
|
||||
alias Pleroma.User
|
||||
|
||||
setup do
|
||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "GET /api/v1/tags/:id" do
|
||||
test "returns 200 with tag" do
|
||||
%{user: user, conn: conn} = oauth_access(["read"])
|
||||
|
||||
tag = insert(:hashtag, name: "jubjub")
|
||||
{:ok, _user} = User.follow_hashtag(user, tag)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/tags/jubjub")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert %{
|
||||
"name" => "jubjub",
|
||||
"url" => "http://localhost:4001/tags/jubjub",
|
||||
"history" => [],
|
||||
"following" => true
|
||||
} = response
|
||||
end
|
||||
|
||||
test "returns 404 with unknown tag" do
|
||||
%{conn: conn} = oauth_access(["read"])
|
||||
|
||||
conn
|
||||
|> get("/api/v1/tags/jubjub")
|
||||
|> json_response_and_validate_schema(404)
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v1/tags/:id/follow" do
|
||||
test "should follow a hashtag" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:follows"])
|
||||
hashtag = insert(:hashtag, name: "jubjub")
|
||||
|
||||
response =
|
||||
conn
|
||||
|> post("/api/v1/tags/jubjub/follow")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response["following"] == true
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
assert User.following_hashtag?(user, hashtag)
|
||||
end
|
||||
|
||||
test "should 404 if hashtag doesn't exist" do
|
||||
%{conn: conn} = oauth_access(["write:follows"])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> post("/api/v1/tags/rubrub/follow")
|
||||
|> json_response_and_validate_schema(404)
|
||||
|
||||
assert response["error"] == "Hashtag not found"
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v1/tags/:id/unfollow" do
|
||||
test "should unfollow a hashtag" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:follows"])
|
||||
hashtag = insert(:hashtag, name: "jubjub")
|
||||
{:ok, user} = User.follow_hashtag(user, hashtag)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> post("/api/v1/tags/jubjub/unfollow")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert response["following"] == false
|
||||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
refute User.following_hashtag?(user, hashtag)
|
||||
end
|
||||
|
||||
test "should 404 if hashtag doesn't exist" do
|
||||
%{conn: conn} = oauth_access(["write:follows"])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> post("/api/v1/tags/rubrub/unfollow")
|
||||
|> json_response_and_validate_schema(404)
|
||||
|
||||
assert response["error"] == "Hashtag not found"
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/v1/followed_tags" do
|
||||
test "should list followed tags" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:follows"])
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/followed_tags")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert Enum.empty?(response)
|
||||
|
||||
hashtag = insert(:hashtag, name: "jubjub")
|
||||
{:ok, _user} = User.follow_hashtag(user, hashtag)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/followed_tags")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"name" => "jubjub"}] = response
|
||||
end
|
||||
|
||||
test "should include a link header to paginate" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:follows"])
|
||||
|
||||
for i <- 1..21 do
|
||||
hashtag = insert(:hashtag, name: "jubjub#{i}}")
|
||||
{:ok, _user} = User.follow_hashtag(user, hashtag)
|
||||
end
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/followed_tags")
|
||||
|
||||
json = json_response_and_validate_schema(response, 200)
|
||||
assert Enum.count(json) == 20
|
||||
assert [link_header] = get_resp_header(response, "link")
|
||||
assert link_header =~ "rel=\"next\""
|
||||
next_link = extract_next_link_header(link_header)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get(next_link)
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert Enum.count(response) == 1
|
||||
end
|
||||
|
||||
test "should refuse access without read:follows scope" do
|
||||
%{conn: conn} = oauth_access(["write"])
|
||||
|
||||
conn
|
||||
|> get("/api/v1/followed_tags")
|
||||
|> json_response_and_validate_schema(403)
|
||||
end
|
||||
end
|
||||
|
||||
defp extract_next_link_header(header) do
|
||||
[_, next_link] = Regex.run(~r{<(?<next_link>.*)>; rel="next"}, header)
|
||||
next_link
|
||||
end
|
||||
end
|
||||
|
|
@ -152,7 +152,6 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
|
|||
end
|
||||
|
||||
describe "public" do
|
||||
@tag capture_log: true
|
||||
test "the public timeline", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
@ -791,7 +790,6 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
|
|||
describe "hashtag" do
|
||||
setup do: oauth_access(["n/a"])
|
||||
|
||||
@tag capture_log: true
|
||||
test "hashtag timeline", %{conn: conn} do
|
||||
following = insert(:user)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,15 +6,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|
|||
use Pleroma.Web.ConnCase, async: true
|
||||
|
||||
describe "empty_array/2 (stubs)" do
|
||||
test "GET /api/v1/accounts/:id/identity_proofs" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:accounts"])
|
||||
|
||||
assert [] ==
|
||||
conn
|
||||
|> get("/api/v1/accounts/#{user.id}/identity_proofs")
|
||||
|> json_response(200)
|
||||
end
|
||||
|
||||
test "GET /api/v1/endorsements" do
|
||||
%{conn: conn} = oauth_access(["read:accounts"])
|
||||
|
||||
|
|
|
|||
|
|
@ -430,6 +430,75 @@ defmodule Pleroma.Web.MastodonAPI.UpdateCredentialsTest do
|
|||
assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
|
||||
end
|
||||
|
||||
test "adds avatar description with a new avatar", %{user: user, conn: conn} do
|
||||
new_avatar = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
res =
|
||||
patch(conn, "/api/v1/accounts/update_credentials", %{
|
||||
"avatar" => new_avatar,
|
||||
"avatar_description" => "me and pleroma tan"
|
||||
})
|
||||
|
||||
assert json_response_and_validate_schema(res, 200)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.avatar["name"] == "me and pleroma tan"
|
||||
end
|
||||
|
||||
test "adds avatar description to existing avatar", %{user: user, conn: conn} do
|
||||
new_avatar = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
assert user.avatar == %{}
|
||||
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
|
||||
|
||||
assert conn
|
||||
|> assign(:user, User.get_by_id(user.id))
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"avatar_description" => "me and pleroma tan"
|
||||
})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
user = User.get_by_id(user.id)
|
||||
assert user.avatar["name"] == "me and pleroma tan"
|
||||
end
|
||||
|
||||
test "limit", %{user: user, conn: conn} do
|
||||
new_header = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image.jpg"),
|
||||
filename: "an_image.jpg"
|
||||
}
|
||||
|
||||
assert user.banner == %{}
|
||||
|
||||
conn
|
||||
|> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
|
||||
|
||||
description_limit = Config.get([:instance, :description_limit], 100)
|
||||
|
||||
description = String.duplicate(".", description_limit + 1)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, User.get_by_id(user.id))
|
||||
|> patch("/api/v1/accounts/update_credentials", %{
|
||||
"header_description" => description
|
||||
})
|
||||
|
||||
assert %{"error" => "Banner description is too long"} =
|
||||
json_response_and_validate_schema(conn, 413)
|
||||
end
|
||||
|
||||
test "Strip / from upload files", %{user: user, conn: conn} do
|
||||
new_image = %Plug.Upload{
|
||||
content_type: "image/jpeg",
|
||||
|
|
|
|||
|
|
@ -96,7 +96,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
hide_follows_count: false,
|
||||
relationship: %{},
|
||||
skip_thread_containment: false,
|
||||
accepts_chat_messages: nil
|
||||
accepts_chat_messages: nil,
|
||||
avatar_description: "",
|
||||
header_description: ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -340,7 +342,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
hide_follows_count: false,
|
||||
relationship: %{},
|
||||
skip_thread_containment: false,
|
||||
accepts_chat_messages: nil
|
||||
accepts_chat_messages: nil,
|
||||
avatar_description: "",
|
||||
header_description: ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -436,7 +440,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
{:ok, other_user, user} = User.follow(other_user, user)
|
||||
{:ok, _subscription} = User.subscribe(user, other_user)
|
||||
{:ok, _user_relationships} = User.mute(user, other_user, %{notifications: true})
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(user, other_user)
|
||||
{:ok, _reblog_mute} = CommonAPI.hide_reblogs(other_user, user)
|
||||
|
||||
expected =
|
||||
Map.merge(
|
||||
|
|
@ -456,6 +460,45 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
test_relationship_rendering(user, other_user, expected)
|
||||
end
|
||||
|
||||
test "relationship does not indicate following if a FollowingRelationship is missing" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
|
||||
# Create a follow relationship with the real Follow Activity and Accept it
|
||||
assert {:ok, _, _, _} = CommonAPI.follow(other_user, user)
|
||||
assert {:ok, _} = CommonAPI.accept_follow_request(user, other_user)
|
||||
|
||||
assert %{data: %{"state" => "accept"}} =
|
||||
Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(user, other_user)
|
||||
|
||||
# Fetch the relationship and forcibly delete it to simulate
|
||||
# a Follow Accept that did not complete processing
|
||||
%{following_relationships: [relationship]} =
|
||||
Pleroma.UserRelationship.view_relationships_option(user, [other_user])
|
||||
|
||||
assert {:ok, _} = Pleroma.Repo.delete(relationship)
|
||||
|
||||
assert %{following_relationships: [], user_relationships: []} ==
|
||||
Pleroma.UserRelationship.view_relationships_option(user, [other_user])
|
||||
|
||||
expected =
|
||||
Map.merge(
|
||||
@blank_response,
|
||||
%{
|
||||
following: false,
|
||||
followed_by: false,
|
||||
muting: false,
|
||||
muting_notifications: false,
|
||||
subscribing: false,
|
||||
notifying: false,
|
||||
showing_reblogs: true,
|
||||
id: to_string(other_user.id)
|
||||
}
|
||||
)
|
||||
|
||||
test_relationship_rendering(user, other_user, expected)
|
||||
end
|
||||
|
||||
test "represent a relationship for the blocking and blocked user" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
|
@ -493,7 +536,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user, is_locked: true)
|
||||
|
||||
{:ok, user, other_user, _} = CommonAPI.follow(user, other_user)
|
||||
{:ok, other_user, user, _} = CommonAPI.follow(other_user, user)
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
||||
|
|
@ -547,8 +590,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, user, other_user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
assert %{
|
||||
followers_count: 0,
|
||||
|
|
@ -560,8 +603,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
test "shows when follows/followers are hidden" do
|
||||
user = insert(:user, hide_followers: true, hide_follows: true)
|
||||
other_user = insert(:user)
|
||||
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
assert %{
|
||||
followers_count: 1,
|
||||
|
|
@ -573,11 +616,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
test "shows actual follower/following count to the account owner" do
|
||||
user = insert(:user, hide_followers: true, hide_follows: true)
|
||||
other_user = insert(:user)
|
||||
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
assert User.following?(user, other_user)
|
||||
assert Pleroma.FollowingRelationship.follower_count(other_user) == 1
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
assert %{
|
||||
followers_count: 1,
|
||||
|
|
@ -684,7 +727,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
assert %{follow_requests_count: 0} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
|
|
@ -696,7 +739,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 1} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
|
|
@ -708,7 +751,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 1} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
|
|
@ -725,7 +768,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 1} =
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
|
|
@ -742,7 +785,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||
|
||||
other_user = insert(:user)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
{:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user)
|
||||
|
||||
{:ok, user} = User.update_and_set_cache(user, %{is_locked: false})
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "pleroma:chat_mention",
|
||||
account: AccountView.render("show.json", %{user: user, for: recipient}),
|
||||
|
|
@ -75,6 +76,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "mention",
|
||||
account:
|
||||
|
|
@ -93,12 +95,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
user = insert(:user)
|
||||
another_user = insert(:user)
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(another_user, create_activity.id)
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(create_activity.id, another_user)
|
||||
{:ok, [notification]} = Notification.create_notifications(favorite_activity)
|
||||
create_activity = Activity.get_by_id(create_activity.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "favourite",
|
||||
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||
|
|
@ -119,6 +122,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "reblog",
|
||||
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||
|
|
@ -132,11 +136,12 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
test "Follow notification" do
|
||||
follower = insert(:user)
|
||||
followed = insert(:user)
|
||||
{:ok, follower, followed, _activity} = CommonAPI.follow(follower, followed)
|
||||
{:ok, followed, follower, _activity} = CommonAPI.follow(followed, follower)
|
||||
notification = Notification |> Repo.one() |> Repo.preload(:activity)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "follow",
|
||||
account: AccountView.render("show.json", %{user: follower, for: followed}),
|
||||
|
|
@ -165,6 +170,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "move",
|
||||
account: AccountView.render("show.json", %{user: old_user, for: follower}),
|
||||
|
|
@ -190,6 +196,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "pleroma:emoji_reaction",
|
||||
emoji: "☕",
|
||||
|
|
@ -229,6 +236,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "pleroma:emoji_reaction",
|
||||
emoji: ":dinosaur:",
|
||||
|
|
@ -248,6 +256,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "poll",
|
||||
account:
|
||||
|
|
@ -274,6 +283,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "pleroma:report",
|
||||
account: AccountView.render("show.json", %{user: reporting_user, for: moderator_user}),
|
||||
|
|
@ -290,7 +300,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "mew"})
|
||||
{:ok, _} = CommonAPI.repeat(activity.id, repeat_user)
|
||||
{:ok, update} = CommonAPI.update(user, activity, %{status: "mew mew"})
|
||||
{:ok, update} = CommonAPI.update(activity, user, %{status: "mew mew"})
|
||||
|
||||
user = Pleroma.User.get_by_ap_id(user.ap_id)
|
||||
activity = Pleroma.Activity.normalize(activity)
|
||||
|
|
@ -300,6 +310,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "update",
|
||||
account: AccountView.render("show.json", %{user: user, for: repeat_user}),
|
||||
|
|
@ -316,12 +327,13 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
{:ok, _} = Pleroma.UserRelationship.create_mute(user, another_user)
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(another_user, create_activity.id)
|
||||
{:ok, favorite_activity} = CommonAPI.favorite(create_activity.id, another_user)
|
||||
{:ok, [notification]} = Notification.create_notifications(favorite_activity)
|
||||
create_activity = Activity.get_by_id(create_activity.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: true, is_muted: true},
|
||||
type: "favourite",
|
||||
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||
|
|
@ -331,4 +343,32 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do
|
|||
|
||||
test_notifications_rendering([notification], user, [expected])
|
||||
end
|
||||
|
||||
test "Subscribed status notification" do
|
||||
user = insert(:user)
|
||||
subscriber = insert(:user)
|
||||
|
||||
User.subscribe(subscriber, user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hi"})
|
||||
{:ok, [notification]} = Notification.create_notifications(activity)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
||||
expected = %{
|
||||
id: to_string(notification.id),
|
||||
group_key: "ungrouped-#{to_string(notification.id)}",
|
||||
pleroma: %{is_seen: false, is_muted: false},
|
||||
type: "status",
|
||||
account:
|
||||
AccountView.render("show.json", %{
|
||||
user: user,
|
||||
for: subscriber
|
||||
}),
|
||||
status: StatusView.render("show.json", %{activity: activity, for: subscriber}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
||||
test_notifications_rendering([notification], subscriber, [expected])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do
|
|||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
{:ok, _votes, object} = CommonAPI.vote(voter, object, [0, 1])
|
||||
{:ok, _votes, object} = CommonAPI.vote(object, voter, [0, 1])
|
||||
|
||||
assert match?(
|
||||
%{
|
||||
|
|
@ -119,7 +119,7 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do
|
|||
|
||||
object = Object.normalize(activity, fetch: false)
|
||||
|
||||
{:ok, _, object} = CommonAPI.vote(other_user, object, [1, 2])
|
||||
{:ok, _, object} = CommonAPI.vote(object, other_user, [1, 2])
|
||||
|
||||
result = PollView.render("show.json", %{object: object, for: other_user})
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns a temporary ap_id based user for activities missing db users" do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
@ -343,7 +342,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
parent_visible: false,
|
||||
pinned_at: nil,
|
||||
quotes_count: 0,
|
||||
bookmark_folder: nil
|
||||
bookmark_folder: nil,
|
||||
list_id: nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -389,7 +389,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
|
||||
assert status.pleroma.thread_muted == false
|
||||
|
||||
{:ok, activity} = CommonAPI.add_mute(user, activity)
|
||||
{:ok, activity} = CommonAPI.add_mute(activity, user)
|
||||
|
||||
status = StatusView.render("show.json", %{activity: activity, for: user})
|
||||
|
||||
|
|
@ -467,7 +467,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
|
||||
# Create a public post quoting the private post
|
||||
quote_private =
|
||||
insert(:note_activity, note: insert(:note, data: %{"quoteUrl" => private_object.data["id"]}))
|
||||
insert(:note_activity,
|
||||
note: insert(:note, data: %{"quoteUrl" => private_object.data["id"]})
|
||||
)
|
||||
|
||||
status = StatusView.render("show.json", %{activity: quote_private})
|
||||
|
||||
|
|
@ -478,7 +480,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
|
||||
# After following the user, the quote is rendered
|
||||
follower = insert(:user)
|
||||
CommonAPI.follow(follower, user)
|
||||
CommonAPI.follow(user, follower)
|
||||
|
||||
status = StatusView.render("show.json", %{activity: quote_private, for: follower})
|
||||
assert status.pleroma.quote.id == to_string(private.id)
|
||||
|
|
@ -591,45 +593,78 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
assert mention.url == recipient.ap_id
|
||||
end
|
||||
|
||||
test "attachments" do
|
||||
object = %{
|
||||
"type" => "Image",
|
||||
"url" => [
|
||||
%{
|
||||
"mediaType" => "image/png",
|
||||
"href" => "someurl",
|
||||
"width" => 200,
|
||||
"height" => 100
|
||||
}
|
||||
],
|
||||
"blurhash" => "UJJ8X[xYW,%Jtq%NNFbXB5j]IVM|9GV=WHRn",
|
||||
"uuid" => 6
|
||||
}
|
||||
describe "attachments" do
|
||||
test "Complete Mastodon style" do
|
||||
object = %{
|
||||
"type" => "Image",
|
||||
"url" => [
|
||||
%{
|
||||
"mediaType" => "image/png",
|
||||
"href" => "someurl",
|
||||
"width" => 200,
|
||||
"height" => 100
|
||||
}
|
||||
],
|
||||
"blurhash" => "UJJ8X[xYW,%Jtq%NNFbXB5j]IVM|9GV=WHRn",
|
||||
"uuid" => 6
|
||||
}
|
||||
|
||||
expected = %{
|
||||
id: "1638338801",
|
||||
type: "image",
|
||||
url: "someurl",
|
||||
remote_url: "someurl",
|
||||
preview_url: "someurl",
|
||||
text_url: "someurl",
|
||||
description: nil,
|
||||
pleroma: %{mime_type: "image/png"},
|
||||
meta: %{original: %{width: 200, height: 100, aspect: 2}},
|
||||
blurhash: "UJJ8X[xYW,%Jtq%NNFbXB5j]IVM|9GV=WHRn"
|
||||
}
|
||||
expected = %{
|
||||
id: "1638338801",
|
||||
type: "image",
|
||||
url: "someurl",
|
||||
remote_url: "someurl",
|
||||
preview_url: "someurl",
|
||||
text_url: "someurl",
|
||||
description: nil,
|
||||
pleroma: %{mime_type: "image/png"},
|
||||
meta: %{original: %{width: 200, height: 100, aspect: 2}},
|
||||
blurhash: "UJJ8X[xYW,%Jtq%NNFbXB5j]IVM|9GV=WHRn"
|
||||
}
|
||||
|
||||
api_spec = Pleroma.Web.ApiSpec.spec()
|
||||
api_spec = Pleroma.Web.ApiSpec.spec()
|
||||
|
||||
assert expected == StatusView.render("attachment.json", %{attachment: object})
|
||||
assert_schema(expected, "Attachment", api_spec)
|
||||
assert expected == StatusView.render("attachment.json", %{attachment: object})
|
||||
assert_schema(expected, "Attachment", api_spec)
|
||||
|
||||
# If theres a "id", use that instead of the generated one
|
||||
object = Map.put(object, "id", 2)
|
||||
result = StatusView.render("attachment.json", %{attachment: object})
|
||||
# If theres a "id", use that instead of the generated one
|
||||
object = Map.put(object, "id", 2)
|
||||
result = StatusView.render("attachment.json", %{attachment: object})
|
||||
|
||||
assert %{id: "2"} = result
|
||||
assert_schema(result, "Attachment", api_spec)
|
||||
assert %{id: "2"} = result
|
||||
assert_schema(result, "Attachment", api_spec)
|
||||
end
|
||||
|
||||
test "Honkerific" do
|
||||
object = %{
|
||||
"type" => "Image",
|
||||
"url" => [
|
||||
%{
|
||||
"mediaType" => "image/png",
|
||||
"href" => "someurl"
|
||||
}
|
||||
],
|
||||
"name" => "fool.jpeg",
|
||||
"summary" => "they have played us for absolute fools."
|
||||
}
|
||||
|
||||
expected = %{
|
||||
blurhash: nil,
|
||||
description: "they have played us for absolute fools.",
|
||||
id: "1638338801",
|
||||
pleroma: %{mime_type: "image/png", name: "fool.jpeg"},
|
||||
preview_url: "someurl",
|
||||
remote_url: "someurl",
|
||||
text_url: "someurl",
|
||||
type: "image",
|
||||
url: "someurl"
|
||||
}
|
||||
|
||||
api_spec = Pleroma.Web.ApiSpec.spec()
|
||||
|
||||
assert expected == StatusView.render("attachment.json", %{attachment: object})
|
||||
assert_schema(expected, "Attachment", api_spec)
|
||||
end
|
||||
end
|
||||
|
||||
test "put the url advertised in the Activity in to the url attribute" do
|
||||
|
|
@ -878,6 +913,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
status = StatusView.render("show.json", activity: activity)
|
||||
|
||||
assert status.visibility == "list"
|
||||
assert status.pleroma.list_id == nil
|
||||
|
||||
status = StatusView.render("show.json", activity: activity, for: user)
|
||||
|
||||
assert status.pleroma.list_id == list.id
|
||||
end
|
||||
|
||||
test "has a field for parent visibility" do
|
||||
|
|
@ -904,7 +944,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
status = StatusView.render("show.json", activity: post)
|
||||
refute status.edited_at
|
||||
|
||||
{:ok, _} = CommonAPI.update(poster, post, %{status: "mew mew"})
|
||||
{:ok, _} = CommonAPI.update(post, poster, %{status: "mew mew"})
|
||||
edited = Pleroma.Activity.normalize(post)
|
||||
|
||||
status = StatusView.render("show.json", activity: edited)
|
||||
|
|
|
|||
|
|
@ -248,8 +248,8 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
|
|||
|
||||
response = get(conn, url)
|
||||
|
||||
assert response.status == 302
|
||||
assert redirected_to(response) == media_proxy_url
|
||||
assert response.status == 301
|
||||
assert redirected_to(response, 301) == media_proxy_url
|
||||
end
|
||||
|
||||
test "with `static` param and non-GIF image preview requested, " <>
|
||||
|
|
@ -290,8 +290,8 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
|
|||
|
||||
response = get(conn, url)
|
||||
|
||||
assert response.status == 302
|
||||
assert redirected_to(response) == media_proxy_url
|
||||
assert response.status == 301
|
||||
assert redirected_to(response, 301) == media_proxy_url
|
||||
end
|
||||
|
||||
test "thumbnails PNG images into PNG", %{
|
||||
|
|
@ -356,5 +356,32 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
|
|||
assert response.status == 302
|
||||
assert redirected_to(response) == media_proxy_url
|
||||
end
|
||||
|
||||
test "redirects to media proxy URI with 301 when image is too small for preview", %{
|
||||
conn: conn,
|
||||
url: url,
|
||||
media_proxy_url: media_proxy_url
|
||||
} do
|
||||
clear_config([:media_preview_proxy],
|
||||
enabled: true,
|
||||
min_content_length: 1000,
|
||||
image_quality: 85,
|
||||
thumbnail_max_width: 100,
|
||||
thumbnail_max_height: 100
|
||||
)
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :head, url: ^media_proxy_url} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: "",
|
||||
headers: [{"content-type", "image/png"}, {"content-length", "500"}]
|
||||
}
|
||||
end)
|
||||
|
||||
response = get(conn, url)
|
||||
assert response.status == 301
|
||||
assert redirected_to(response, 301) == media_proxy_url
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
40
test/pleroma/web/metadata/providers/activity_pub_test.exs
Normal file
40
test/pleroma/web/metadata/providers/activity_pub_test.exs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Metadata.Providers.ActivityPubTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.Metadata.Providers.ActivityPub
|
||||
|
||||
setup do: clear_config([Pleroma.Web.Metadata, :unfurl_nsfw])
|
||||
|
||||
test "it renders a link for user info" do
|
||||
user = insert(:user)
|
||||
res = ActivityPub.build_tags(%{user: user})
|
||||
|
||||
assert res == [
|
||||
{:link, [rel: "alternate", type: "application/activity+json", href: user.ap_id], []}
|
||||
]
|
||||
end
|
||||
|
||||
test "it renders a link for a post" do
|
||||
user = insert(:user)
|
||||
{:ok, %{id: activity_id, object: object}} = CommonAPI.post(user, %{status: "hi"})
|
||||
|
||||
result = ActivityPub.build_tags(%{object: object, user: user, activity_id: activity_id})
|
||||
|
||||
assert [
|
||||
{:link,
|
||||
[rel: "alternate", type: "application/activity+json", href: object.data["id"]], []}
|
||||
] == result
|
||||
end
|
||||
|
||||
test "it returns an empty array for anything else" do
|
||||
result = ActivityPub.build_tags(%{})
|
||||
|
||||
assert result == []
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue