server/tests/inbox.test.ts

299 lines
8.4 KiB
TypeScript
Raw Normal View History

2023-09-14 05:39:11 +02:00
import { getConfig } from "@config";
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
import { AppDataSource } from "~database/datasource";
import { RawActivity } from "~database/entities/RawActivity";
import { Token } from "~database/entities/Token";
import { User } from "~database/entities/User";
const config = getConfig();
beforeAll(async () => {
if (!AppDataSource.isInitialized) await AppDataSource.initialize();
// Initialize test user
2023-09-22 00:42:59 +02:00
await User.createNew({
email: "test@test.com",
username: "test",
password: "test",
display_name: "",
});
2023-09-14 05:39:11 +02:00
});
describe("POST /@test/inbox", () => {
test("should store a new Note object", async () => {
2023-09-22 00:42:59 +02:00
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
const response = await fetch(`${config.http.base_url}/@test/inbox/`, {
method: "POST",
headers: {
"Content-Type": "application/activity+json",
},
body: JSON.stringify({
"@context": "https://www.w3.org/ns/activitystreams",
type: "Create",
id: activityId,
actor: {
id: `${config.http.base_url}/@test`,
type: "Person",
preferredUsername: "test",
2023-09-14 05:39:11 +02:00
},
to: ["https://www.w3.org/ns/activitystreams#Public"],
cc: [],
published: "2021-01-01T00:00:00.000Z",
object: {
2023-09-14 05:39:11 +02:00
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://example.com/notes/1",
type: "Note",
content: "Hello, world!",
summary: null,
inReplyTo: null,
2023-09-14 05:39:11 +02:00
published: "2021-01-01T00:00:00.000Z",
},
}),
});
2023-09-14 05:39:11 +02:00
expect(response.status).toBe(200);
expect(response.headers.get("content-type")).toBe("application/json");
2023-09-22 00:42:59 +02:00
const activity = await RawActivity.getLatestById(activityId);
2023-09-14 05:39:11 +02:00
expect(activity).not.toBeUndefined();
expect(activity?.data).toEqual({
"@context": "https://www.w3.org/ns/activitystreams",
type: "Create",
2023-09-22 00:42:59 +02:00
id: activityId,
2023-09-14 05:39:11 +02:00
to: ["https://www.w3.org/ns/activitystreams#Public"],
cc: [],
published: "2021-01-01T00:00:00.000Z",
});
expect(activity?.objects).toHaveLength(1);
expect(activity?.objects[0].data).toEqual({
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://example.com/notes/1",
type: "Note",
content: "Hello, world!",
summary: null,
inReplyTo: null,
published: "2021-01-01T00:00:00.000Z",
});
});
2023-09-14 08:12:54 +02:00
test("should try to update that Note object", async () => {
2023-09-22 00:42:59 +02:00
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
const response = await fetch(`${config.http.base_url}/@test/inbox/`, {
method: "POST",
headers: {
"Content-Type": "application/activity+json",
},
body: JSON.stringify({
"@context": "https://www.w3.org/ns/activitystreams",
type: "Update",
id: activityId,
actor: {
id: `${config.http.base_url}/@test`,
type: "Person",
preferredUsername: "test",
2023-09-14 08:12:54 +02:00
},
to: ["https://www.w3.org/ns/activitystreams#Public"],
cc: [],
published: "2021-01-02T00:00:00.000Z",
object: {
2023-09-14 08:12:54 +02:00
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://example.com/notes/1",
type: "Note",
content: "This note has been edited!",
summary: null,
inReplyTo: null,
published: "2021-01-01T00:00:00.000Z",
},
}),
});
2023-09-14 08:12:54 +02:00
expect(response.status).toBe(200);
expect(response.headers.get("content-type")).toBe("application/json");
2023-09-22 00:42:59 +02:00
const activity = await RawActivity.getLatestById(activityId);
2023-09-14 08:12:54 +02:00
expect(activity).not.toBeUndefined();
expect(activity?.data).toEqual({
"@context": "https://www.w3.org/ns/activitystreams",
type: "Update",
2023-09-22 00:42:59 +02:00
id: activityId,
2023-09-14 08:12:54 +02:00
to: ["https://www.w3.org/ns/activitystreams#Public"],
cc: [],
published: "2021-01-02T00:00:00.000Z",
});
expect(activity?.objects).toHaveLength(1);
expect(activity?.objects[0].data).toEqual({
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://example.com/notes/1",
type: "Note",
content: "This note has been edited!",
summary: null,
inReplyTo: null,
published: "2021-01-01T00:00:00.000Z",
});
});
2023-09-15 03:22:27 +02:00
test("should delete the Note object", async () => {
2023-09-22 00:42:59 +02:00
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
const response = await fetch(`${config.http.base_url}/@test/inbox/`, {
method: "POST",
headers: {
"Content-Type": "application/activity+json",
},
body: JSON.stringify({
"@context": "https://www.w3.org/ns/activitystreams",
type: "Delete",
id: activityId,
actor: {
id: `${config.http.base_url}/@test`,
type: "Person",
preferredUsername: "test",
2023-09-15 03:22:27 +02:00
},
to: ["https://www.w3.org/ns/activitystreams#Public"],
cc: [],
published: "2021-01-03T00:00:00.000Z",
object: {
2023-09-15 03:22:27 +02:00
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://example.com/notes/1",
type: "Note",
content: "This note has been edited!",
summary: null,
inReplyTo: null,
published: "2021-01-01T00:00:00.000Z",
},
}),
});
2023-09-15 03:22:27 +02:00
expect(response.status).toBe(200);
expect(response.headers.get("content-type")).toBe("application/json");
2023-09-22 00:42:59 +02:00
const activity = await RawActivity.getLatestById(activityId);
2023-09-15 03:22:27 +02:00
expect(activity).not.toBeUndefined();
expect(activity?.data).toEqual({
"@context": "https://www.w3.org/ns/activitystreams",
type: "Delete",
2023-09-22 00:42:59 +02:00
id: activityId,
2023-09-15 03:22:27 +02:00
to: ["https://www.w3.org/ns/activitystreams#Public"],
cc: [],
published: "2021-01-03T00:00:00.000Z",
});
2023-09-22 00:42:59 +02:00
expect(activity?.actors).toHaveLength(1);
expect(activity?.actors[0].data).toEqual({
preferredUsername: "test",
id: `${config.http.base_url}/@test`,
2023-09-27 01:08:05 +02:00
summary: "",
publicKey: {
id: `${config.http.base_url}/@test/actor#main-key`,
owner: `${config.http.base_url}/@test/actor`,
publicKeyPem: expect.any(String),
},
outbox: `${config.http.base_url}/@test/outbox`,
manuallyApprovesFollowers: false,
followers: `${config.http.base_url}/@test/followers`,
following: `${config.http.base_url}/@test/following`,
name: "",
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
],
icon: {
type: "Image",
url: "",
},
image: {
type: "Image",
url: "",
},
inbox: `${config.http.base_url}/@test/inbox`,
2023-09-22 00:42:59 +02:00
type: "Person",
});
2023-09-15 05:42:52 +02:00
// Can be 0 or 1 length depending on whether config.activitypub.use_tombstone is true or false
if (config.activitypub.use_tombstones) {
expect(activity?.objects).toHaveLength(1);
} else {
expect(activity?.objects).toHaveLength(0);
}
2023-09-15 03:22:27 +02:00
});
2023-09-22 00:42:59 +02:00
test("should return a 404 error when trying to delete a non-existent Note object", async () => {
const activityId = `https://example.com/objects/${crypto.randomUUID()}`;
const response = await fetch(`${config.http.base_url}/@test/inbox/`, {
method: "POST",
headers: {
"Content-Type": "application/activity+json",
},
body: JSON.stringify({
"@context": "https://www.w3.org/ns/activitystreams",
type: "Delete",
id: activityId,
actor: {
id: `${config.http.base_url}/@test`,
type: "Person",
preferredUsername: "test",
2023-09-22 00:42:59 +02:00
},
to: ["https://www.w3.org/ns/activitystreams#Public"],
cc: [],
published: "2021-01-03T00:00:00.000Z",
object: {
2023-09-22 00:42:59 +02:00
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://example.com/notes/2345678909876543",
type: "Note",
},
}),
});
2023-09-22 00:42:59 +02:00
expect(response.status).toBe(404);
expect(response.headers.get("content-type")).toBe("application/json");
});
2023-09-14 05:39:11 +02:00
});
afterAll(async () => {
// Clean up user
const user = await User.findOneBy({
username: "test",
});
// Clean up tokens
const tokens = await Token.findBy({
user: {
username: "test",
},
});
const activities = await RawActivity.createQueryBuilder("activity")
2023-09-22 00:42:59 +02:00
// Join objects
2023-09-14 05:39:11 +02:00
.leftJoinAndSelect("activity.objects", "objects")
2023-09-22 00:42:59 +02:00
.leftJoinAndSelect("activity.actors", "actors")
// activity.actors is a many-to-many relationship with Actor objects (it is an array of Actor objects)
// Get the actors of the activity that have data.id as `${config.http.base_url}/@test`
2023-09-22 00:42:59 +02:00
.where("actors.data @> :data", {
data: JSON.stringify({
id: `${config.http.base_url}/@test`,
2023-09-22 00:42:59 +02:00
}),
})
2023-09-14 05:39:11 +02:00
.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 Promise.all(tokens.map(async token => await token.remove()));
if (user) await user.remove();
});