mirror of
https://github.com/versia-pub/server.git
synced 2026-03-13 05:49:16 +01:00
Media upload for avatars and banners, more work, fix tests
This commit is contained in:
parent
16cfd5d900
commit
460b68c381
17 changed files with 360 additions and 139 deletions
|
|
@ -23,27 +23,34 @@ beforeAll(async () => {
|
|||
|
||||
describe("POST /@test/actor", () => {
|
||||
test("should return a valid ActivityPub Actor when querying an existing user", async () => {
|
||||
const response = await fetch(`${config.http.base_url}/users/test/actor`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Accept: "application/activity+json",
|
||||
},
|
||||
});
|
||||
const response = await fetch(
|
||||
`${config.http.base_url}/users/test/actor`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
Accept: "application/activity+json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("content-type")).toBe(
|
||||
"application/activity+json"
|
||||
);
|
||||
|
||||
const actor: APActor = await response.json();
|
||||
const actor = (await response.json()) as APActor;
|
||||
|
||||
expect(actor.type).toBe("Person");
|
||||
expect(actor.id).toBe(`${config.http.base_url}/users/test`);
|
||||
expect(actor.preferredUsername).toBe("test");
|
||||
expect(actor.inbox).toBe(`${config.http.base_url}/users/test/inbox`);
|
||||
expect(actor.outbox).toBe(`${config.http.base_url}/users/test/outbox`);
|
||||
expect(actor.followers).toBe(`${config.http.base_url}/users/test/followers`);
|
||||
expect(actor.following).toBe(`${config.http.base_url}/users/test/following`);
|
||||
expect(actor.followers).toBe(
|
||||
`${config.http.base_url}/users/test/followers`
|
||||
);
|
||||
expect(actor.following).toBe(
|
||||
`${config.http.base_url}/users/test/following`
|
||||
);
|
||||
expect((actor as any).publicKey).toBeDefined();
|
||||
expect((actor as any).publicKey.id).toBeDefined();
|
||||
expect((actor as any).publicKey.owner).toBe(
|
||||
|
|
@ -82,4 +89,6 @@ afterAll(async () => {
|
|||
if (user) {
|
||||
await user.remove();
|
||||
}
|
||||
|
||||
await AppDataSource.destroy();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -66,6 +66,28 @@ describe("API Tests", () => {
|
|||
token = await token.save();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
const activities = await RawActivity.createQueryBuilder("activity")
|
||||
.where("activity.data->>'actor' = :actor", {
|
||||
actor: `${config.http.base_url}/users/test`,
|
||||
})
|
||||
.leftJoinAndSelect("activity.objects", "objects")
|
||||
.getMany();
|
||||
|
||||
// Delete all created objects and activities as part of testing
|
||||
for (const activity of activities) {
|
||||
for (const object of activity.objects) {
|
||||
await object.remove();
|
||||
}
|
||||
await activity.remove();
|
||||
}
|
||||
|
||||
await user.remove();
|
||||
await user2.remove();
|
||||
|
||||
await AppDataSource.destroy();
|
||||
});
|
||||
|
||||
describe("POST /api/v1/accounts/:id", () => {
|
||||
test("should return a 404 error when trying to fetch a non-existent user", async () => {
|
||||
const response = await fetch(
|
||||
|
|
@ -150,7 +172,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const statuses: APIStatus[] = await response.json();
|
||||
const statuses = (await response.json()) as APIStatus[];
|
||||
|
||||
expect(statuses.some(s => s.id === status?.id)).toBe(true);
|
||||
});
|
||||
|
|
@ -177,7 +199,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const user: APIAccount = await response.json();
|
||||
const user = (await response.json()) as APIAccount;
|
||||
|
||||
expect(user.display_name).toBe("New Display Name");
|
||||
});
|
||||
|
|
@ -201,7 +223,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIAccount = await response.json();
|
||||
const account = (await response.json()) as APIAccount;
|
||||
|
||||
expect(account.username).toBe(user.username);
|
||||
expect(account.bot).toBe(false);
|
||||
|
|
@ -246,7 +268,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const statuses: APIStatus[] = await response.json();
|
||||
const statuses = (await response.json()) as APIStatus[];
|
||||
|
||||
expect(statuses.length).toBe(1);
|
||||
|
||||
|
|
@ -278,7 +300,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIRelationship = await response.json();
|
||||
const account = (await response.json()) as APIRelationship;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.following).toBe(true);
|
||||
|
|
@ -304,7 +326,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIRelationship = await response.json();
|
||||
const account = (await response.json()) as APIRelationship;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.following).toBe(false);
|
||||
|
|
@ -330,7 +352,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIRelationship = await response.json();
|
||||
const account = (await response.json()) as APIRelationship;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.followed_by).toBe(false);
|
||||
|
|
@ -356,7 +378,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIRelationship = await response.json();
|
||||
const account = (await response.json()) as APIRelationship;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.blocking).toBe(true);
|
||||
|
|
@ -382,7 +404,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIRelationship = await response.json();
|
||||
const account = (await response.json()) as APIRelationship;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.blocking).toBe(false);
|
||||
|
|
@ -408,7 +430,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIRelationship = await response.json();
|
||||
const account = (await response.json()) as APIRelationship;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.muting).toBe(true);
|
||||
|
|
@ -433,7 +455,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIRelationship = await response.json();
|
||||
const account = (await response.json()) as APIRelationship;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.muting).toBe(true);
|
||||
|
|
@ -460,7 +482,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIRelationship = await response.json();
|
||||
const account = (await response.json()) as APIRelationship;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.muting).toBe(false);
|
||||
|
|
@ -486,7 +508,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIRelationship = await response.json();
|
||||
const account = (await response.json()) as APIRelationship;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.endorsed).toBe(true);
|
||||
|
|
@ -512,7 +534,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIRelationship = await response.json();
|
||||
const account = (await response.json()) as APIRelationship;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.endorsed).toBe(false);
|
||||
|
|
@ -538,7 +560,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const account: APIAccount = await response.json();
|
||||
const account = (await response.json()) as APIAccount;
|
||||
|
||||
expect(account.id).toBe(user2.id);
|
||||
expect(account.note).toBe("This is a new note");
|
||||
|
|
@ -562,7 +584,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const relationships: APIRelationship[] = await response.json();
|
||||
const relationships = (await response.json()) as APIRelationship[];
|
||||
|
||||
expect(Array.isArray(relationships)).toBe(true);
|
||||
expect(relationships.length).toBeGreaterThan(0);
|
||||
|
|
@ -595,8 +617,10 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const familiarFollowers: { id: string; accounts: APIAccount[] }[] =
|
||||
await response.json();
|
||||
const familiarFollowers = (await response.json()) as {
|
||||
id: string;
|
||||
accounts: APIAccount[];
|
||||
}[];
|
||||
|
||||
expect(Array.isArray(familiarFollowers)).toBe(true);
|
||||
expect(familiarFollowers.length).toBeGreaterThan(0);
|
||||
|
|
@ -657,7 +681,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const statusJson = await response.json();
|
||||
const statusJson = (await response.json()) as APIStatus;
|
||||
|
||||
expect(statusJson.id).toBe(status?.id);
|
||||
expect(statusJson.content).toBeDefined();
|
||||
|
|
@ -718,7 +742,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const instance: APIInstance = await response.json();
|
||||
const instance = (await response.json()) as APIInstance;
|
||||
|
||||
expect(instance.uri).toBe(new URL(config.http.base_url).hostname);
|
||||
expect(instance.title).toBeDefined();
|
||||
|
|
@ -764,7 +788,7 @@ describe("API Tests", () => {
|
|||
"application/json"
|
||||
);
|
||||
|
||||
const emojis: APIEmoji[] = await response.json();
|
||||
const emojis = (await response.json()) as APIEmoji[];
|
||||
|
||||
expect(emojis.length).toBeGreaterThan(0);
|
||||
expect(emojis[0].shortcode).toBe("test");
|
||||
|
|
@ -774,26 +798,4 @@ describe("API Tests", () => {
|
|||
await Emoji.delete({ shortcode: "test" });
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
const activities = await RawActivity.createQueryBuilder("activity")
|
||||
.where("activity.data->>'actor' = :actor", {
|
||||
actor: `${config.http.base_url}/users/test`,
|
||||
})
|
||||
.leftJoinAndSelect("activity.objects", "objects")
|
||||
.getMany();
|
||||
|
||||
// Delete all created objects and activities as part of testing
|
||||
await Promise.all(
|
||||
activities.map(async activity => {
|
||||
await Promise.all(
|
||||
activity.objects.map(async object => await object.remove())
|
||||
);
|
||||
await activity.remove();
|
||||
})
|
||||
);
|
||||
|
||||
await user.remove();
|
||||
await user2.remove();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -37,4 +37,6 @@ describe("Instance", () => {
|
|||
|
||||
afterAll(async () => {
|
||||
await instance.remove();
|
||||
|
||||
await AppDataSource.destroy();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,17 +1,27 @@
|
|||
import { getConfig } from "@config";
|
||||
import { ConfigType, getConfig } from "@config";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "bun:test";
|
||||
import { LocalBackend, S3Backend } from "~classes/media";
|
||||
import { unlink } from "fs/promises";
|
||||
import { DeleteObjectCommand } from "@aws-sdk/client-s3";
|
||||
|
||||
const config = getConfig();
|
||||
const originalConfig = getConfig();
|
||||
const modifiedConfig: ConfigType = {
|
||||
...originalConfig,
|
||||
media: {
|
||||
...originalConfig.media,
|
||||
conversion: {
|
||||
...originalConfig.media.conversion,
|
||||
convert_images: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
describe("LocalBackend", () => {
|
||||
let localBackend: LocalBackend;
|
||||
let fileName: string;
|
||||
|
||||
beforeAll(() => {
|
||||
localBackend = new LocalBackend();
|
||||
localBackend = new LocalBackend(modifiedConfig);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
|
|
@ -25,7 +35,7 @@ describe("LocalBackend", () => {
|
|||
});
|
||||
|
||||
const hash = await localBackend.addMedia(media);
|
||||
fileName = `${hash}`;
|
||||
fileName = hash;
|
||||
|
||||
expect(hash).toBeDefined();
|
||||
});
|
||||
|
|
@ -33,16 +43,14 @@ describe("LocalBackend", () => {
|
|||
|
||||
describe("getMediaByHash", () => {
|
||||
it("should retrieve the file from the local filesystem and return it as a File object", async () => {
|
||||
const media = await localBackend.getMediaByHash(fileName, "txt");
|
||||
const media = await localBackend.getMediaByHash(fileName);
|
||||
|
||||
expect(media).toBeInstanceOf(File);
|
||||
});
|
||||
|
||||
it("should return null if the file does not exist", async () => {
|
||||
const media = await localBackend.getMediaByHash(
|
||||
"does-not-exist",
|
||||
"txt"
|
||||
);
|
||||
const media =
|
||||
await localBackend.getMediaByHash("does-not-exist.txt");
|
||||
|
||||
expect(media).toBeNull();
|
||||
});
|
||||
|
|
@ -50,12 +58,12 @@ describe("LocalBackend", () => {
|
|||
});
|
||||
|
||||
describe("S3Backend", () => {
|
||||
const s3Backend = new S3Backend(config);
|
||||
const s3Backend = new S3Backend(modifiedConfig);
|
||||
let fileName: string;
|
||||
|
||||
afterAll(async () => {
|
||||
const command = new DeleteObjectCommand({
|
||||
Bucket: config.s3.bucket_name,
|
||||
Bucket: modifiedConfig.s3.bucket_name,
|
||||
Key: fileName,
|
||||
});
|
||||
|
||||
|
|
@ -69,7 +77,7 @@ describe("S3Backend", () => {
|
|||
});
|
||||
|
||||
const hash = await s3Backend.addMedia(media);
|
||||
fileName = `${hash}`;
|
||||
fileName = hash;
|
||||
|
||||
expect(hash).toBeDefined();
|
||||
});
|
||||
|
|
@ -77,16 +85,13 @@ describe("S3Backend", () => {
|
|||
|
||||
describe("getMediaByHash", () => {
|
||||
it("should retrieve the file from the S3 bucket and return it as a File object", async () => {
|
||||
const media = await s3Backend.getMediaByHash(fileName, "txt");
|
||||
const media = await s3Backend.getMediaByHash(fileName);
|
||||
|
||||
expect(media).toBeInstanceOf(File);
|
||||
});
|
||||
|
||||
it("should return null if the file does not exist", async () => {
|
||||
const media = await s3Backend.getMediaByHash(
|
||||
"does-not-exist",
|
||||
"txt"
|
||||
);
|
||||
const media = await s3Backend.getMediaByHash("does-not-exist.txt");
|
||||
|
||||
expect(media).toBeNull();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ describe("POST /@test/inbox", () => {
|
|||
manuallyApprovesFollowers: false,
|
||||
followers: `${config.http.base_url}/users/test/followers`,
|
||||
following: `${config.http.base_url}/users/test/following`,
|
||||
published: expect.any(String),
|
||||
name: "",
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
|
|
@ -217,11 +218,11 @@ describe("POST /@test/inbox", () => {
|
|||
],
|
||||
icon: {
|
||||
type: "Image",
|
||||
url: "",
|
||||
url: expect.any(String),
|
||||
},
|
||||
image: {
|
||||
type: "Image",
|
||||
url: "",
|
||||
url: expect.any(String),
|
||||
},
|
||||
inbox: `${config.http.base_url}/users/test/inbox`,
|
||||
type: "Person",
|
||||
|
|
@ -311,4 +312,6 @@ afterAll(async () => {
|
|||
await Promise.all(tokens.map(async token => await token.remove()));
|
||||
|
||||
if (user) await user.remove();
|
||||
|
||||
await AppDataSource.destroy();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ describe("POST /api/v1/apps/", () => {
|
|||
formData.append("redirect_uris", "https://example.com");
|
||||
formData.append("scopes", "read write");
|
||||
|
||||
// @ts-expect-error FormData works
|
||||
const response = await fetch(`${config.http.base_url}/api/v1/apps/`, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
|
|
@ -42,7 +43,7 @@ describe("POST /api/v1/apps/", () => {
|
|||
expect(response.headers.get("content-type")).toBe("application/json");
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const json = await response.json();
|
||||
const json = (await response.json()) as any;
|
||||
|
||||
expect(json).toEqual({
|
||||
id: expect.any(String),
|
||||
|
|
@ -67,6 +68,8 @@ describe("POST /auth/login/", () => {
|
|||
|
||||
formData.append("email", "test@test.com");
|
||||
formData.append("password", "test");
|
||||
|
||||
// @ts-expect-error FormData works
|
||||
const response = await fetch(
|
||||
`${config.http.base_url}/auth/login/?client_id=${client_id}&redirect_uri=https://example.com&response_type=code&scope=read+write`,
|
||||
{
|
||||
|
|
@ -96,13 +99,17 @@ describe("POST /oauth/token/", () => {
|
|||
formData.append("client_secret", client_secret);
|
||||
formData.append("scope", "read+write");
|
||||
|
||||
// @ts-expect-error FormData works
|
||||
const response = await fetch(`${config.http.base_url}/oauth/token/`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
body: formData,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const json = await response.json();
|
||||
const json = (await response.json()) as any;
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("content-type")).toBe("application/json");
|
||||
|
|
@ -134,7 +141,7 @@ describe("GET /api/v1/apps/verify_credentials", () => {
|
|||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("content-type")).toBe("application/json");
|
||||
|
||||
const credentials: Partial<Application> = await response.json();
|
||||
const credentials = (await response.json()) as Partial<Application>;
|
||||
|
||||
expect(credentials.name).toBe("Test Application");
|
||||
expect(credentials.website).toBe("https://example.com");
|
||||
|
|
@ -167,4 +174,6 @@ afterAll(async () => {
|
|||
);
|
||||
|
||||
if (user) await user.remove();
|
||||
|
||||
await AppDataSource.destroy();
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue