diff --git a/.gitignore b/.gitignore index 186713e1f..6883b4eca 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,8 @@ query_testing/**/reports/*.json api_tests/node_modules api_tests/.yalc api_tests/yalc.lock +api_tests/test.png +api_tests/pict-rs # pictrs data pictrs/ diff --git a/Cargo.lock b/Cargo.lock index bfbedd64c..66b91dbac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1997,9 +1997,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "js-sys", @@ -3306,9 +3306,9 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "openssl" -version = "0.10.57" +version = "0.10.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -3338,9 +3338,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" dependencies = [ "cc", "libc", @@ -5356,9 +5356,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", diff --git a/api_tests/package.json b/api_tests/package.json index 17ac9f7be..653d57e32 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -9,22 +9,24 @@ "scripts": { "lint": "tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx src && prettier --check 'src/**/*.ts'", "fix": "prettier --write src && eslint --fix src", - "api-test": "jest -i follow.spec.ts && jest -i post.spec.ts && jest -i comment.spec.ts && jest -i private_message.spec.ts && jest -i user.spec.ts && jest -i community.spec.ts", + "api-test": "jest -i follow.spec.ts && jest -i post.spec.ts && jest -i comment.spec.ts && jest -i private_message.spec.ts && jest -i user.spec.ts && jest -i community.spec.ts && jest -i image.spec.ts", "api-test-comment": "jest -i comment.spec.ts", "api-test-post": "jest -i post.spec.ts", "api-test-user": "jest -i user.spec.ts", "api-test-community": "jest -i community.spec.ts", - "api-test-private-message": "jest -i private_message.spec.ts" + "api-test-private-message": "jest -i private_message.spec.ts", + "api-test-image": "jest -i image.spec.ts" }, "devDependencies": { "@types/jest": "^29.5.8", "@types/node": "^20.9.0", "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", + "download-file-sync": "^1.0.4", "eslint": "^8.53.0", "eslint-plugin-prettier": "^5.0.1", "jest": "^29.5.0", - "lemmy-js-client": "0.19.0-rc.12", + "lemmy-js-client": "0.19.0-alpha.18", "prettier": "^3.0.0", "ts-jest": "^29.1.0", "typescript": "^5.0.4" diff --git a/api_tests/prepare-drone-federation-test.sh b/api_tests/prepare-drone-federation-test.sh index 4044ba0dd..0b623f6d2 100755 --- a/api_tests/prepare-drone-federation-test.sh +++ b/api_tests/prepare-drone-federation-test.sh @@ -8,6 +8,17 @@ export RUST_LOG="warn,lemmy_server=debug,lemmy_federate=debug,lemmy_api=debug,le export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queue has delays in the scale of 30s-5min +# pictrs setup +if ! [ -f "pict-rs" ]; then + curl "https://git.asonix.dog/asonix/pict-rs/releases/download/v0.5.0-beta.2/pict-rs-linux-amd64" -o api_tests/pict-rs + chmod +x api_tests/pict-rs +fi +./api_tests/pict-rs \ + run -a 0.0.0.0:8080 \ + --danger-dummy-mode \ + filesystem -p /tmp/pictrs/files \ + sled -p /tmp/pictrs/sled-repo 2>&1 & + for INSTANCE in lemmy_alpha lemmy_beta lemmy_gamma lemmy_delta lemmy_epsilon; do echo "DB URL: ${LEMMY_DATABASE_URL} INSTANCE: $INSTANCE" psql "${LEMMY_DATABASE_URL}/lemmy" -c "DROP DATABASE IF EXISTS $INSTANCE" diff --git a/api_tests/run-federation-test.sh b/api_tests/run-federation-test.sh index 3042fd344..609cd473e 100755 --- a/api_tests/run-federation-test.sh +++ b/api_tests/run-federation-test.sh @@ -14,6 +14,8 @@ yarn yarn api-test || true killall -s1 lemmy_server || true +killall -s1 pict-rs || true for INSTANCE in lemmy_alpha lemmy_beta lemmy_gamma lemmy_delta lemmy_epsilon; do psql "$LEMMY_DATABASE_URL" -c "DROP DATABASE $INSTANCE" done +rm -r /tmp/pictrs diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 951641d78..7ab8db335 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -54,8 +54,8 @@ beforeAll(async () => { } }); -afterAll(async () => { - await unfollows(); +afterAll(() => { + unfollows(); }); function assertCommentFederation( @@ -94,7 +94,9 @@ test("Create a comment", async () => { }); test("Create a comment in a non-existent post", async () => { - await expect(createComment(alpha, -1)).rejects.toBe("couldnt_find_post"); + await expect(createComment(alpha, -1)).rejects.toStrictEqual( + Error("couldnt_find_post"), + ); }); test("Update a comment", async () => { @@ -143,7 +145,7 @@ test("Delete a comment", async () => { await waitUntil( () => resolveComment(gamma, commentRes.comment_view.comment).catch(e => e), - r => r !== "couldnt_find_object", + r => r.message !== "couldnt_find_object", ) ).comment; if (!gammaComment) { @@ -160,13 +162,13 @@ test("Delete a comment", async () => { // Make sure that comment is undefined on beta await waitUntil( () => resolveComment(beta, commentRes.comment_view.comment).catch(e => e), - e => e === "couldnt_find_object", + e => e.message == "couldnt_find_object", ); // Make sure that comment is undefined on gamma after delete await waitUntil( () => resolveComment(gamma, commentRes.comment_view.comment).catch(e => e), - e => e === "couldnt_find_object", + e => e.message === "couldnt_find_object", ); // Test undeleting the comment @@ -181,7 +183,7 @@ test("Delete a comment", async () => { let betaComment2 = ( await waitUntil( () => resolveComment(beta, commentRes.comment_view.comment).catch(e => e), - e => e !== "couldnt_find_object", + e => e.message !== "couldnt_find_object", ) ).comment; expect(betaComment2?.comment.deleted).toBe(false); diff --git a/api_tests/src/community.spec.ts b/api_tests/src/community.spec.ts index 2f3a410f6..a16802e08 100644 --- a/api_tests/src/community.spec.ts +++ b/api_tests/src/community.spec.ts @@ -34,9 +34,7 @@ import { } from "./shared"; import { EditSite, LemmyHttp } from "lemmy-js-client"; -beforeAll(async () => { - await setupLogins(); -}); +beforeAll(setupLogins); function assertCommunityFederation( communityOne?: CommunityView, @@ -66,8 +64,8 @@ test("Create community", async () => { // A dupe check let prevName = communityRes.community_view.community.name; - await expect(createCommunity(alpha, prevName)).rejects.toBe( - "community_already_exists", + await expect(createCommunity(alpha, prevName)).rejects.toStrictEqual( + Error("community_already_exists"), ); // Cache the community on beta, make sure it has the other fields @@ -333,8 +331,8 @@ test("Get community for different casing on domain", async () => { // A dupe check let prevName = communityRes.community_view.community.name; - await expect(createCommunity(alpha, prevName)).rejects.toBe( - "community_already_exists", + await expect(createCommunity(alpha, prevName)).rejects.toStrictEqual( + Error("community_already_exists"), ); // Cache the community on beta, make sure it has the other fields diff --git a/api_tests/src/follow.spec.ts b/api_tests/src/follow.spec.ts index a0b43989b..89d078848 100644 --- a/api_tests/src/follow.spec.ts +++ b/api_tests/src/follow.spec.ts @@ -10,12 +10,10 @@ import { waitUntil, } from "./shared"; -beforeAll(async () => { - await setupLogins(); -}); +beforeAll(setupLogins); -afterAll(async () => { - await unfollowRemotes(alpha); +afterAll(() => { + unfollowRemotes(alpha); }); test("Follow federated community", async () => { diff --git a/api_tests/src/image.spec.ts b/api_tests/src/image.spec.ts new file mode 100644 index 000000000..73d020872 --- /dev/null +++ b/api_tests/src/image.spec.ts @@ -0,0 +1,44 @@ +jest.setTimeout(120000); + +import { UploadImage, DeleteImage } from "lemmy-js-client"; +import { alpha, setupLogins, unfollowRemotes } from "./shared"; +import fs = require("fs"); +const downloadFileSync = require("download-file-sync"); + +beforeAll(setupLogins); + +afterAll(() => { + unfollowRemotes(alpha); +}); + +test("Upload image and delete it", async () => { + // upload test image + const upload_image = fs.readFileSync("test.png"); + const upload_form: UploadImage = { + image: upload_image, + }; + const upload = await alpha.uploadImage(upload_form); + console.log(upload); + expect(upload.files![0].file).toBeDefined(); + expect(upload.files![0].delete_token).toBeDefined(); + expect(upload.url).toBeDefined(); + expect(upload.delete_url).toBeDefined(); + + // ensure that image download is working. theres probably a better way to do this + const content = downloadFileSync(upload.url); + expect(content.length).toBeGreaterThan(0); + + // delete image + const delete_form: DeleteImage = { + token: upload.files![0].delete_token, + filename: upload.files![0].file, + }; + const delete_ = await alpha.deleteImage(delete_form); + expect(delete_).toBe(true); + + // ensure that image is deleted + const content2 = downloadFileSync(upload.url); + expect(content2).toBe(""); +}); + +// TODO: add tests for image purging diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 1d6e90c72..d79a536cb 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -50,8 +50,8 @@ beforeAll(async () => { await unfollows(); }); -afterAll(async () => { - await unfollows(); +afterAll(() => { + unfollows(); }); function assertPostFederation(postOne?: PostView, postTwo?: PostView) { @@ -96,18 +96,20 @@ test("Create a post", async () => { assertPostFederation(betaPost, postRes.post_view); // Delta only follows beta, so it should not see an alpha ap_id - await expect(resolvePost(delta, postRes.post_view.post)).rejects.toBe( - "couldnt_find_object", - ); + await expect( + resolvePost(delta, postRes.post_view.post), + ).rejects.toStrictEqual(Error("couldnt_find_object")); // Epsilon has alpha blocked, it should not see the alpha post - await expect(resolvePost(epsilon, postRes.post_view.post)).rejects.toBe( - "couldnt_find_object", - ); + await expect( + resolvePost(epsilon, postRes.post_view.post), + ).rejects.toStrictEqual(Error("couldnt_find_object")); }); test("Create a post in a non-existent community", async () => { - await expect(createPost(alpha, -2)).rejects.toBe("couldnt_find_community"); + await expect(createPost(alpha, -2)).rejects.toStrictEqual( + Error("couldnt_find_community"), + ); }); test("Unlike a post", async () => { @@ -157,8 +159,8 @@ test("Update a post", async () => { assertPostFederation(betaPost, updatedPost.post_view); // Make sure lemmy beta cannot update the post - await expect(editPost(beta, betaPost.post)).rejects.toBe( - "no_post_edit_allowed", + await expect(editPost(beta, betaPost.post)).rejects.toStrictEqual( + Error("no_post_edit_allowed"), ); }); @@ -226,7 +228,9 @@ test("Lock a post", async () => { ); // Try to make a new comment there, on alpha - await expect(createComment(alpha, alphaPost1.post.id)).rejects.toBe("locked"); + await expect(createComment(alpha, alphaPost1.post.id)).rejects.toStrictEqual( + Error("locked"), + ); // Unlock a post let unlockedPost = await lockPost(beta, false, betaPost1.post); @@ -281,8 +285,8 @@ test("Delete a post", async () => { assertPostFederation(betaPost2, undeletedPost.post_view); // Make sure lemmy beta cannot delete the post - await expect(deletePost(beta, true, betaPost2.post)).rejects.toBe( - "no_post_edit_allowed", + await expect(deletePost(beta, true, betaPost2.post)).rejects.toStrictEqual( + Error("no_post_edit_allowed"), ); }); @@ -483,12 +487,12 @@ test.skip("Enforce community ban for federated user", async () => { // ensure that the post by alpha got removed await expect(getPost(alpha, searchBeta1.posts[0].post.id)).rejects.toBe( - "unknown", + Error("unknown"), ); // Alpha tries to make post on beta, but it fails because of ban await expect(createPost(alpha, betaCommunity.community.id)).rejects.toBe( - "banned_from_community", + Error("banned_from_community"), ); // Unban alpha diff --git a/api_tests/src/private_message.spec.ts b/api_tests/src/private_message.spec.ts index 081bb8d8d..08c519df7 100644 --- a/api_tests/src/private_message.spec.ts +++ b/api_tests/src/private_message.spec.ts @@ -20,8 +20,8 @@ beforeAll(async () => { recipient_id = 3; }); -afterAll(async () => { - await unfollowRemotes(alpha); +afterAll(() => { + unfollowRemotes(alpha); }); test("Create a private message", async () => { diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index 8d1a4744c..5a6a82ed2 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -10,6 +10,7 @@ import { InstanceId, LemmyHttp, PostView, + SuccessResponse, } from "lemmy-js-client"; import { CreatePost } from "lemmy-js-client/dist/types/CreatePost"; import { DeletePost } from "lemmy-js-client/dist/types/DeletePost"; @@ -58,7 +59,6 @@ import { Register } from "lemmy-js-client/dist/types/Register"; import { SaveUserSettings } from "lemmy-js-client/dist/types/SaveUserSettings"; import { DeleteAccount } from "lemmy-js-client/dist/types/DeleteAccount"; import { GetSiteResponse } from "lemmy-js-client/dist/types/GetSiteResponse"; -import { DeleteAccountResponse } from "lemmy-js-client/dist/types/DeleteAccountResponse"; import { PrivateMessagesResponse } from "lemmy-js-client/dist/types/PrivateMessagesResponse"; import { GetPrivateMessages } from "lemmy-js-client/dist/types/GetPrivateMessages"; import { PostReportResponse } from "lemmy-js-client/dist/types/PostReportResponse"; @@ -637,7 +637,7 @@ export async function loginUser( export async function saveUserSettingsBio( api: LemmyHttp, -): Promise { +): Promise { let form: SaveUserSettings = { show_nsfw: true, blur_nsfw: false, @@ -655,7 +655,7 @@ export async function saveUserSettingsBio( export async function saveUserSettingsFederated( api: LemmyHttp, -): Promise { +): Promise { let avatar = "https://image.flaticon.com/icons/png/512/35/35896.png"; let banner = "https://image.flaticon.com/icons/png/512/36/35896.png"; let bio = "a changed bio"; @@ -679,7 +679,7 @@ export async function saveUserSettingsFederated( export async function saveUserSettings( api: LemmyHttp, form: SaveUserSettings, -): Promise { +): Promise { return api.saveUserSettings(form); } export async function getPersonDetails( @@ -692,9 +692,7 @@ export async function getPersonDetails( return api.getPersonDetails(form); } -export async function deleteUser( - api: LemmyHttp, -): Promise { +export async function deleteUser(api: LemmyHttp): Promise { let form: DeleteAccount = { delete_content: true, password, diff --git a/api_tests/src/user.spec.ts b/api_tests/src/user.spec.ts index 70fad1a66..d71827f89 100644 --- a/api_tests/src/user.spec.ts +++ b/api_tests/src/user.spec.ts @@ -22,9 +22,7 @@ import { import { LemmyHttp, SaveUserSettings } from "lemmy-js-client"; import { GetPosts } from "lemmy-js-client/dist/types/GetPosts"; -beforeAll(async () => { - await setupLogins(); -}); +beforeAll(setupLogins); let apShortname: string; diff --git a/api_tests/test.png b/api_tests/test.png new file mode 100644 index 000000000..b01d868e9 Binary files /dev/null and b/api_tests/test.png differ diff --git a/api_tests/yarn.lock b/api_tests/yarn.lock index d00a78380..9a272efee 100644 --- a/api_tests/yarn.lock +++ b/api_tests/yarn.lock @@ -1270,6 +1270,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +download-file-sync@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/download-file-sync/-/download-file-sync-1.0.4.tgz#d3e3c543f836f41039455b9034c72e355b036019" + integrity sha512-vH92qNH508jZZA12HQNq/aiMDfagr4JvjFiI17Bi8oYjsxwv5ZVIi7iHkYmUXxOQUr90tcVX+8EPePjAqG1Y0w== + electron-to-chromium@^1.4.535: version "1.4.537" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.537.tgz#aac4101db53066be1e49baedd000a26bc754adc9" @@ -2281,10 +2286,10 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -lemmy-js-client@0.19.0-rc.12: - version "0.19.0-rc.12" - resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.19.0-rc.12.tgz#e3bd4e21b1966d583ab790ef70ece8394b012b48" - integrity sha512-1iu2fW9vlb3TrI+QR/ODP3+5pWZB0rUqL1wH09IzomDXohCqoQvfmXpwArmgF4Eq8GZgjkcfeMDC2gMrfw/i7Q== +lemmy-js-client@0.19.0-alpha.18: + version "0.19.0-alpha.18" + resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.19.0-alpha.18.tgz#f94841681cabdf9d5c4ce7048eacb57557f68724" + integrity sha512-cKJfKKnjK+ijk0Yd6ydtne3Y4FILp2RbQg05pCru9n6PCyPAa85eQL4QxPB1PPed20ckSZRcHLcnr/bYFDgpaw== dependencies: cross-fetch "^3.1.5" form-data "^4.0.0"