mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 16:38:19 +01:00
refactor(api): ♻️ Refactor test code to use new client
This commit is contained in:
parent
232ce83e4d
commit
84b9fc3719
|
|
@ -1,8 +1,7 @@
|
||||||
import { afterAll, describe, expect, test } from "bun:test";
|
import { afterAll, describe, expect, test } from "bun:test";
|
||||||
import type { Relationship as ApiRelationship } from "@versia/client/types";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(2);
|
const { users, deleteUsers } = await getTestUsers(2);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
|
|
@ -11,57 +10,40 @@ afterAll(async () => {
|
||||||
// /api/v1/accounts/:id/block
|
// /api/v1/accounts/:id/block
|
||||||
describe("/api/v1/accounts/:id/block", () => {
|
describe("/api/v1/accounts/:id/block", () => {
|
||||||
test("should return 401 if not authenticated", async () => {
|
test("should return 401 if not authenticated", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient();
|
||||||
`/api/v1/accounts/${users[1].id}/block`,
|
|
||||||
{
|
const { ok, raw } = await client.blockAccount(users[1].id);
|
||||||
method: "POST",
|
|
||||||
},
|
expect(ok).toBe(false);
|
||||||
);
|
expect(raw.status).toBe(401);
|
||||||
expect(response.status).toBe(401);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return 404 if user not found", async () => {
|
test("should return 404 if user not found", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
"/api/v1/accounts/00000000-0000-0000-0000-000000000000/block",
|
|
||||||
{
|
const { ok, raw } = await client.blockAccount(
|
||||||
method: "POST",
|
"00000000-0000-0000-0000-000000000000",
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
expect(response.status).toBe(404);
|
|
||||||
|
expect(ok).toBe(false);
|
||||||
|
expect(raw.status).toBe(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should block user", async () => {
|
test("should block user", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/block`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(response.status).toBe(200);
|
|
||||||
|
|
||||||
const relationship = (await response.json()) as ApiRelationship;
|
const { ok, data } = await client.blockAccount(users[1].id);
|
||||||
expect(relationship.blocking).toBe(true);
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
|
expect(data.blocking).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return 200 if user already blocked", async () => {
|
test("should return 200 if user already blocked", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/block`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(response.status).toBe(200);
|
|
||||||
|
|
||||||
const relationship = (await response.json()) as ApiRelationship;
|
const { ok, data } = await client.blockAccount(users[1].id);
|
||||||
expect(relationship.blocking).toBe(true);
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
|
expect(data.blocking).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { afterAll, describe, expect, test } from "bun:test";
|
import { afterAll, describe, expect, test } from "bun:test";
|
||||||
import type { Relationship as ApiRelationship } from "@versia/client/types";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(2);
|
const { users, deleteUsers } = await getTestUsers(2);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
|
|
@ -11,67 +10,38 @@ afterAll(async () => {
|
||||||
// /api/v1/accounts/:id/follow
|
// /api/v1/accounts/:id/follow
|
||||||
describe("/api/v1/accounts/:id/follow", () => {
|
describe("/api/v1/accounts/:id/follow", () => {
|
||||||
test("should return 401 if not authenticated", async () => {
|
test("should return 401 if not authenticated", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient();
|
||||||
`/api/v1/accounts/${users[1].id}/follow`,
|
|
||||||
{
|
const { ok, raw } = await client.followAccount(users[1].id);
|
||||||
method: "POST",
|
|
||||||
headers: {
|
expect(ok).toBe(false);
|
||||||
"Content-Type": "application/json",
|
expect(raw.status).toBe(401);
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(response.status).toBe(401);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return 404 if user not found", async () => {
|
test("should return 404 if user not found", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
"/api/v1/accounts/00000000-0000-0000-0000-000000000000/follow",
|
|
||||||
{
|
const { ok, raw } = await client.followAccount(
|
||||||
method: "POST",
|
"00000000-0000-0000-0000-000000000000",
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
expect(response.status).toBe(404);
|
|
||||||
|
expect(ok).toBe(false);
|
||||||
|
expect(raw.status).toBe(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should follow user", async () => {
|
test("should follow user", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/follow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(response.status).toBe(200);
|
|
||||||
|
|
||||||
const relationship = (await response.json()) as ApiRelationship;
|
const { ok } = await client.followAccount(users[1].id);
|
||||||
expect(relationship.following).toBe(true);
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return 200 if user already followed", async () => {
|
test("should return 200 if user already followed", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/follow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(response.status).toBe(200);
|
|
||||||
|
|
||||||
const relationship = (await response.json()) as ApiRelationship;
|
const { ok } = await client.followAccount(users[1].id);
|
||||||
expect(relationship.following).toBe(true);
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,30 @@
|
||||||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||||
import type { Account as ApiAccount } from "@versia/client/types";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(5);
|
const { users, deleteUsers } = await getTestUsers(5);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
// Follow user
|
await using client = await generateClient(users[0]);
|
||||||
const response = await fakeRequest(
|
|
||||||
`/api/v1/accounts/${users[1].id}/follow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
// Follow user
|
||||||
|
const { ok, raw } = await client.followAccount(users[1].id);
|
||||||
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
|
expect(raw.status).toBe(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
// /api/v1/accounts/:id/followers
|
// /api/v1/accounts/:id/followers
|
||||||
describe("/api/v1/accounts/:id/followers", () => {
|
describe("/api/v1/accounts/:id/followers", () => {
|
||||||
test("should return 200 with followers", async () => {
|
test("should return 200 with followers", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/followers`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { ok, data } = await client.getAccountFollowers(users[1].id);
|
||||||
|
|
||||||
const data = (await response.json()) as ApiAccount[];
|
expect(ok).toBe(true);
|
||||||
|
|
||||||
expect(data).toBeInstanceOf(Array);
|
expect(data).toBeInstanceOf(Array);
|
||||||
expect(data.length).toBe(1);
|
expect(data.length).toBe(1);
|
||||||
|
|
@ -47,32 +32,15 @@ describe("/api/v1/accounts/:id/followers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return no followers after unfollowing", async () => {
|
test("should return no followers after unfollowing", async () => {
|
||||||
// Unfollow user
|
await using client = await generateClient(users[0]);
|
||||||
const response = await fakeRequest(
|
|
||||||
`/api/v1/accounts/${users[1].id}/unfollow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { ok } = await client.unfollowAccount(users[1].id);
|
||||||
|
|
||||||
const response2 = await fakeRequest(
|
expect(ok).toBe(true);
|
||||||
`/api/v1/accounts/${users[1].id}/followers`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response2.status).toBe(200);
|
const { ok: ok2, data } = await client.getAccountFollowers(users[1].id);
|
||||||
|
|
||||||
const data = (await response2.json()) as ApiAccount[];
|
|
||||||
|
|
||||||
|
expect(ok2).toBe(true);
|
||||||
expect(data).toBeInstanceOf(Array);
|
expect(data).toBeInstanceOf(Array);
|
||||||
expect(data.length).toBe(0);
|
expect(data.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,29 @@
|
||||||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||||
import type { Account as ApiAccount } from "@versia/client/types";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(5);
|
const { users, deleteUsers } = await getTestUsers(5);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
// Follow user
|
await using client = await generateClient(users[0]);
|
||||||
const response = await fakeRequest(
|
|
||||||
`/api/v1/accounts/${users[1].id}/follow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
// Follow user
|
||||||
|
const { ok } = await client.followAccount(users[1].id);
|
||||||
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// /api/v1/accounts/:id/following
|
// /api/v1/accounts/:id/following
|
||||||
describe("/api/v1/accounts/:id/following", () => {
|
describe("/api/v1/accounts/:id/following", () => {
|
||||||
test("should return 200 with following", async () => {
|
test("should return 200 with following", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[1]);
|
||||||
`/api/v1/accounts/${users[0].id}/following`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { ok, data } = await client.getAccountFollowing(users[0].id);
|
||||||
|
|
||||||
const data = (await response.json()) as ApiAccount[];
|
expect(ok).toBe(true);
|
||||||
|
|
||||||
expect(data).toBeInstanceOf(Array);
|
expect(data).toBeInstanceOf(Array);
|
||||||
expect(data.length).toBe(1);
|
expect(data.length).toBe(1);
|
||||||
|
|
@ -47,32 +31,15 @@ describe("/api/v1/accounts/:id/following", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return no following after unfollowing", async () => {
|
test("should return no following after unfollowing", async () => {
|
||||||
// Unfollow user
|
await using client = await generateClient(users[0]);
|
||||||
const response = await fakeRequest(
|
|
||||||
`/api/v1/accounts/${users[1].id}/unfollow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { ok } = await client.unfollowAccount(users[1].id);
|
||||||
|
|
||||||
const response2 = await fakeRequest(
|
expect(ok).toBe(true);
|
||||||
`/api/v1/accounts/${users[0].id}/following`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response2.status).toBe(200);
|
const { ok: ok2, data } = await client.getAccountFollowing(users[1].id);
|
||||||
|
|
||||||
const data = (await response2.json()) as ApiAccount[];
|
|
||||||
|
|
||||||
|
expect(ok2).toBe(true);
|
||||||
expect(data).toBeInstanceOf(Array);
|
expect(data).toBeInstanceOf(Array);
|
||||||
expect(data.length).toBe(0);
|
expect(data.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,39 @@
|
||||||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||||
import type { Account as ApiAccount } from "@versia/client/types";
|
import type { Account as ApiAccount } from "@versia/client/types";
|
||||||
import { fakeRequest, getTestStatuses, getTestUsers } from "~/tests/utils";
|
import { generateClient, getTestStatuses, getTestUsers } from "~/tests/utils";
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(5);
|
const { users, deleteUsers } = await getTestUsers(5);
|
||||||
const timeline = (await getTestStatuses(40, users[0])).toReversed();
|
const timeline = (await getTestStatuses(5, users[0])).toReversed();
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
await using client = await generateClient(users[0]);
|
||||||
|
|
||||||
for (const status of timeline) {
|
for (const status of timeline) {
|
||||||
await fakeRequest(`/api/v1/statuses/${status.id}/favourite`, {
|
await client.favouriteStatus(status.id);
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// /api/v1/accounts/:id
|
// /api/v1/accounts/:id
|
||||||
describe("/api/v1/accounts/:id", () => {
|
describe("/api/v1/accounts/:id", () => {
|
||||||
test("should return 404 if ID is invalid", async () => {
|
test("should return 404 if ID is invalid", async () => {
|
||||||
const response = await fakeRequest("/api/v1/accounts/invalid-id");
|
await using client = await generateClient(users[0]);
|
||||||
expect(response.status).toBe(422);
|
|
||||||
|
const { ok, raw } = await client.getAccount("invalid-id");
|
||||||
|
|
||||||
|
expect(ok).toBe(false);
|
||||||
|
expect(raw.status).toBe(422);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return user", async () => {
|
test("should return user", async () => {
|
||||||
const response = await fakeRequest(`/api/v1/accounts/${users[0].id}`);
|
await using client = await generateClient(users[0]);
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { ok, data } = await client.getAccount(users[0].id);
|
||||||
|
|
||||||
const data = (await response.json()) as ApiAccount;
|
expect(ok).toBe(true);
|
||||||
expect(data).toMatchObject({
|
expect(data).toMatchObject({
|
||||||
id: users[0].id,
|
id: users[0].id,
|
||||||
username: users[0].data.username,
|
username: users[0].data.username,
|
||||||
|
|
@ -45,7 +44,7 @@ describe("/api/v1/accounts/:id", () => {
|
||||||
created_at: new Date(users[0].data.createdAt).toISOString(),
|
created_at: new Date(users[0].data.createdAt).toISOString(),
|
||||||
followers_count: 0,
|
followers_count: 0,
|
||||||
following_count: 0,
|
following_count: 0,
|
||||||
statuses_count: 40,
|
statuses_count: 5,
|
||||||
note: users[0].data.note,
|
note: users[0].data.note,
|
||||||
acct: users[0].data.username,
|
acct: users[0].data.username,
|
||||||
uri: expect.any(String),
|
uri: expect.any(String),
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { afterAll, describe, expect, test } from "bun:test";
|
import { afterAll, describe, expect, test } from "bun:test";
|
||||||
import type { Relationship as ApiRelationship } from "@versia/client/types";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(2);
|
const { users, deleteUsers } = await getTestUsers(2);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
|
|
@ -11,67 +10,44 @@ afterAll(async () => {
|
||||||
// /api/v1/accounts/:id/mute
|
// /api/v1/accounts/:id/mute
|
||||||
describe("/api/v1/accounts/:id/mute", () => {
|
describe("/api/v1/accounts/:id/mute", () => {
|
||||||
test("should return 401 if not authenticated", async () => {
|
test("should return 401 if not authenticated", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient();
|
||||||
`/api/v1/accounts/${users[1].id}/mute`,
|
|
||||||
{
|
const { ok, raw } = await client.muteAccount(users[1].id);
|
||||||
method: "POST",
|
|
||||||
headers: {
|
expect(ok).toBe(false);
|
||||||
"Content-Type": "application/json",
|
expect(raw.status).toBe(401);
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(response.status).toBe(401);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return 404 if user not found", async () => {
|
test("should return 404 if user not found", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
"/api/v1/accounts/00000000-0000-0000-0000-000000000000/mute",
|
|
||||||
{
|
const { ok, raw } = await client.muteAccount(
|
||||||
method: "POST",
|
"00000000-0000-0000-0000-000000000000",
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
expect(response.status).toBe(404);
|
|
||||||
|
expect(ok).toBe(false);
|
||||||
|
expect(raw.status).toBe(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should mute user", async () => {
|
test("should mute user", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/mute`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(response.status).toBe(200);
|
|
||||||
|
|
||||||
const relationship = (await response.json()) as ApiRelationship;
|
const { data, ok, raw } = await client.muteAccount(users[1].id);
|
||||||
expect(relationship.muting).toBe(true);
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
|
expect(raw.status).toBe(200);
|
||||||
|
|
||||||
|
expect(data.muting).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return 200 if user already muted", async () => {
|
test("should return 200 if user already muted", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/mute`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(response.status).toBe(200);
|
|
||||||
|
|
||||||
const relationship = (await response.json()) as ApiRelationship;
|
const { data, ok, raw } = await client.muteAccount(users[1].id);
|
||||||
expect(relationship.muting).toBe(true);
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
|
expect(raw.status).toBe(200);
|
||||||
|
|
||||||
|
expect(data.muting).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,146 +1,109 @@
|
||||||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||||
import type { Status as ApiStatus } from "@versia/client/types";
|
import {
|
||||||
import { fakeRequest, getTestStatuses, getTestUsers } from "~/tests/utils.ts";
|
generateClient,
|
||||||
|
getTestStatuses,
|
||||||
|
getTestUsers,
|
||||||
|
} from "~/tests/utils.ts";
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(5);
|
const { users, deleteUsers } = await getTestUsers(5);
|
||||||
const timeline = (await getTestStatuses(40, users[1])).toReversed();
|
const timeline = (await getTestStatuses(5, users[1])).toReversed();
|
||||||
const timeline2 = (await getTestStatuses(40, users[2])).toReversed();
|
const timeline2 = (await getTestStatuses(5, users[2])).toReversed();
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[1]);
|
||||||
`/api/v1/statuses/${timeline2[0].id}/reblog`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { ok } = await client.reblogStatus(timeline2[0].id);
|
||||||
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// /api/v1/accounts/:id/statuses
|
// /api/v1/accounts/:id/statuses
|
||||||
describe("/api/v1/accounts/:id/statuses", () => {
|
describe("/api/v1/accounts/:id/statuses", () => {
|
||||||
test("should return 200 with statuses", async () => {
|
test("should return 200 with statuses", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[1]);
|
||||||
`/api/v1/accounts/${users[1].id}/statuses`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getAccountStatuses(users[1].id, {
|
||||||
|
limit: 5,
|
||||||
|
});
|
||||||
|
|
||||||
const data = (await response.json()) as ApiStatus[];
|
expect(ok).toBe(true);
|
||||||
|
|
||||||
expect(data.length).toBe(20);
|
expect(data).toBeArrayOfSize(5);
|
||||||
// Should have reblogs
|
// Should have reblogs
|
||||||
expect(data[0].reblog).toBeDefined();
|
expect(data[0].reblog).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should exclude reblogs", async () => {
|
test("should exclude reblogs", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[1]);
|
||||||
`/api/v1/accounts/${users[1].id}/statuses?exclude_reblogs=true`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getAccountStatuses(users[1].id, {
|
||||||
|
exclude_reblogs: true,
|
||||||
|
limit: 5,
|
||||||
|
});
|
||||||
|
|
||||||
const data = (await response.json()) as ApiStatus[];
|
expect(ok).toBe(true);
|
||||||
|
|
||||||
expect(data.length).toBe(20);
|
expect(data).toBeArrayOfSize(5);
|
||||||
// Should not have reblogs
|
// Should not have reblogs
|
||||||
expect(data[0].reblog).toBeNull();
|
expect(data[0].reblog).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should exclude replies", async () => {
|
test("should exclude replies", async () => {
|
||||||
// Create reply
|
// Create reply
|
||||||
const replyResponse = await fakeRequest("/api/v1/statuses", {
|
await using client0 = await generateClient(users[0]);
|
||||||
method: "POST",
|
await using client1 = await generateClient(users[1]);
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
const { ok } = await client1.postStatus("Reply", {
|
||||||
},
|
in_reply_to_id: timeline[0].id,
|
||||||
body: new URLSearchParams({
|
local_only: true,
|
||||||
status: "Reply",
|
|
||||||
in_reply_to_id: timeline[0].id,
|
|
||||||
local_only: "true",
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(replyResponse.status).toBe(200);
|
expect(ok).toBe(true);
|
||||||
|
|
||||||
const response = await fakeRequest(
|
const { data, ok: ok2 } = await client0.getAccountStatuses(
|
||||||
`/api/v1/accounts/${users[1].id}/statuses?exclude_replies=true`,
|
users[1].id,
|
||||||
{
|
{
|
||||||
headers: {
|
exclude_replies: true,
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
limit: 5,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
expect(ok2).toBe(true);
|
||||||
|
|
||||||
const data = (await response.json()) as ApiStatus[];
|
expect(data).toBeArrayOfSize(5);
|
||||||
|
|
||||||
expect(data.length).toBe(20);
|
|
||||||
// Should not have replies
|
// Should not have replies
|
||||||
expect(data[0].in_reply_to_id).toBeNull();
|
expect(data[0].in_reply_to_id).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should only include pins", async () => {
|
test("should only include pins", async () => {
|
||||||
const response = await fakeRequest(
|
await using client0 = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/statuses?pinned=true`,
|
await using client1 = await generateClient(users[1]);
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { ok, data } = await client0.getAccountStatuses(users[1].id, {
|
||||||
|
pinned: true,
|
||||||
|
});
|
||||||
|
|
||||||
const data = (await response.json()) as ApiStatus[];
|
expect(ok).toBe(true);
|
||||||
|
expect(data).toBeArrayOfSize(0);
|
||||||
expect(data.length).toBe(0);
|
|
||||||
|
|
||||||
// Create pin
|
// Create pin
|
||||||
const pinResponse = await fakeRequest(
|
const { ok: ok2 } = await client1.pinStatus(timeline[3].id);
|
||||||
`/api/v1/statuses/${timeline[3].id}/pin`,
|
|
||||||
|
|
||||||
|
expect(ok2).toBe(true);
|
||||||
|
|
||||||
|
const { data: data2, ok: ok3 } = await client0.getAccountStatuses(
|
||||||
|
users[1].id,
|
||||||
{
|
{
|
||||||
method: "POST",
|
pinned: true,
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(pinResponse.status).toBe(200);
|
expect(ok3).toBe(true);
|
||||||
|
expect(data2).toBeArrayOfSize(1);
|
||||||
const response2 = await fakeRequest(
|
expect(data2[0].id).toBe(timeline[3].id);
|
||||||
`/api/v1/accounts/${users[1].id}/statuses?pinned=true`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response2.status).toBe(200);
|
|
||||||
|
|
||||||
const data2 = (await response2.json()) as ApiStatus[];
|
|
||||||
|
|
||||||
expect(data2.length).toBe(1);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,76 +1,57 @@
|
||||||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||||
import type { Relationship as ApiRelationship } from "@versia/client/types";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(2);
|
const { users, deleteUsers } = await getTestUsers(2);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await fakeRequest(`/api/v1/accounts/${users[0].id}/mute`, {
|
await using client = await generateClient(users[0]);
|
||||||
method: "POST",
|
|
||||||
headers: {
|
const { ok } = await client.muteAccount(users[1].id);
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
|
||||||
},
|
expect(ok).toBe(true);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// /api/v1/accounts/:id/unmute
|
// /api/v1/accounts/:id/unmute
|
||||||
describe("/api/v1/accounts/:id/unmute", () => {
|
describe("/api/v1/accounts/:id/unmute", () => {
|
||||||
test("should return 401 if not authenticated", async () => {
|
test("should return 401 if not authenticated", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient();
|
||||||
`/api/v1/accounts/${users[1].id}/unmute`,
|
|
||||||
{
|
const { ok, raw } = await client.unmuteAccount(users[0].id);
|
||||||
method: "POST",
|
|
||||||
},
|
expect(ok).toBe(false);
|
||||||
);
|
expect(raw.status).toBe(401);
|
||||||
expect(response.status).toBe(401);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return 404 if user not found", async () => {
|
test("should return 404 if user not found", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
"/api/v1/accounts/00000000-0000-0000-0000-000000000000/unmute",
|
|
||||||
{
|
const { ok, raw } = await client.unmuteAccount(
|
||||||
method: "POST",
|
"00000000-0000-0000-0000-000000000000",
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
expect(response.status).toBe(404);
|
|
||||||
|
expect(ok).toBe(false);
|
||||||
|
expect(raw.status).toBe(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should unmute user", async () => {
|
test("should unmute user", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/unmute`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(response.status).toBe(200);
|
|
||||||
|
|
||||||
const relationship = (await response.json()) as ApiRelationship;
|
const { data, ok } = await client.unmuteAccount(users[1].id);
|
||||||
expect(relationship.muting).toBe(false);
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
|
expect(data.muting).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return 200 if user already unmuted", async () => {
|
test("should return 200 if user already unmuted", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/unmute`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(response.status).toBe(200);
|
|
||||||
|
|
||||||
const relationship = (await response.json()) as ApiRelationship;
|
const { data, ok } = await client.unmuteAccount(users[1].id);
|
||||||
expect(relationship.muting).toBe(false);
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
|
expect(data.muting).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,81 +1,39 @@
|
||||||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils.ts";
|
import { generateClient, getTestUsers } from "~/tests/utils.ts";
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(5);
|
const { users, deleteUsers } = await getTestUsers(5);
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
// Create followers relationships
|
// Create followers relationships
|
||||||
const result1 = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/${users[1].id}/follow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result1.status).toBe(200);
|
const { ok } = await client.followAccount(users[1].id);
|
||||||
|
|
||||||
const result2 = await fakeRequest(
|
expect(ok).toBe(true);
|
||||||
`/api/v1/accounts/${users[2].id}/follow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result2.status).toBe(200);
|
const { ok: ok2 } = await client.followAccount(users[2].id);
|
||||||
|
|
||||||
const result3 = await fakeRequest(
|
expect(ok2).toBe(true);
|
||||||
`/api/v1/accounts/${users[3].id}/follow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result3.status).toBe(200);
|
const { ok: ok3 } = await client.followAccount(users[3].id);
|
||||||
|
|
||||||
const result4 = await fakeRequest(
|
expect(ok3).toBe(true);
|
||||||
`/api/v1/accounts/${users[2].id}/follow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result4.status).toBe(200);
|
await using client1 = await generateClient(users[1]);
|
||||||
|
|
||||||
const result5 = await fakeRequest(
|
const { ok: ok4 } = await client1.followAccount(users[2].id);
|
||||||
`/api/v1/accounts/${users[3].id}/follow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result5.status).toBe(200);
|
expect(ok4).toBe(true);
|
||||||
|
|
||||||
const result6 = await fakeRequest(
|
const { ok: ok5 } = await client1.followAccount(users[3].id);
|
||||||
`/api/v1/accounts/${users[3].id}/follow`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[2].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result6.status).toBe(200);
|
expect(ok5).toBe(true);
|
||||||
|
|
||||||
|
await using client2 = await generateClient(users[2]);
|
||||||
|
|
||||||
|
const { ok: ok6 } = await client2.followAccount(users[3].id);
|
||||||
|
|
||||||
|
expect(ok6).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|
@ -84,55 +42,33 @@ afterAll(async () => {
|
||||||
|
|
||||||
describe("/api/v1/accounts/familiar_followers", () => {
|
describe("/api/v1/accounts/familiar_followers", () => {
|
||||||
test("should return 0 familiar followers", async () => {
|
test("should return 0 familiar followers", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/familiar_followers?id=${users[4].id}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getFamiliarFollowers([users[4].id]);
|
||||||
|
|
||||||
const data = await response.json();
|
expect(ok).toBe(true);
|
||||||
expect(data.length).toBe(1);
|
|
||||||
expect(data[0].id).toBe(users[4].id);
|
|
||||||
expect(data[0].accounts).toBeArrayOfSize(0);
|
expect(data[0].accounts).toBeArrayOfSize(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return 1 familiar follower", async () => {
|
test("should return 1 familiar follower", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/familiar_followers?id=${users[2].id}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getFamiliarFollowers([users[2].id]);
|
||||||
|
|
||||||
const data = await response.json();
|
expect(ok).toBe(true);
|
||||||
expect(data.length).toBe(1);
|
expect(data).toBeArrayOfSize(1);
|
||||||
expect(data[0].id).toBe(users[2].id);
|
expect(data[0].id).toBe(users[2].id);
|
||||||
|
expect(data[0].accounts).toBeArrayOfSize(1);
|
||||||
expect(data[0].accounts[0].id).toBe(users[1].id);
|
expect(data[0].accounts[0].id).toBe(users[1].id);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return 2 familiar followers", async () => {
|
test("should return 2 familiar followers", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/familiar_followers?id=${users[3].id}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getFamiliarFollowers([users[3].id]);
|
||||||
|
|
||||||
const data = await response.json();
|
expect(ok).toBe(true);
|
||||||
expect(data.length).toBe(1);
|
expect(data).toBeArrayOfSize(1);
|
||||||
expect(data[0].id).toBe(users[3].id);
|
expect(data[0].id).toBe(users[3].id);
|
||||||
expect(data[0].accounts).toBeArrayOfSize(2);
|
expect(data[0].accounts).toBeArrayOfSize(2);
|
||||||
expect(data[0].accounts[0].id).toBe(users[2].id);
|
expect(data[0].accounts[0].id).toBe(users[2].id);
|
||||||
|
|
@ -140,22 +76,21 @@ describe("/api/v1/accounts/familiar_followers", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should work with multiple ids", async () => {
|
test("should work with multiple ids", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/familiar_followers?id[]=${users[2].id}&id[]=${users[3].id}&id[]=${users[4].id}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getFamiliarFollowers([
|
||||||
|
users[2].id,
|
||||||
|
users[3].id,
|
||||||
|
users[4].id,
|
||||||
|
]);
|
||||||
|
|
||||||
const data = await response.json();
|
expect(ok).toBe(true);
|
||||||
expect(data.length).toBe(3);
|
expect(data).toBeArrayOfSize(3);
|
||||||
expect(data[0].id).toBe(users[2].id);
|
expect(data[0].id).toBe(users[2].id);
|
||||||
|
expect(data[0].accounts).toBeArrayOfSize(1);
|
||||||
expect(data[0].accounts[0].id).toBe(users[1].id);
|
expect(data[0].accounts[0].id).toBe(users[1].id);
|
||||||
expect(data[1].id).toBe(users[3].id);
|
expect(data[1].id).toBe(users[3].id);
|
||||||
|
expect(data[1].accounts).toBeArrayOfSize(2);
|
||||||
expect(data[1].accounts[0].id).toBe(users[2].id);
|
expect(data[1].accounts[0].id).toBe(users[2].id);
|
||||||
expect(data[1].accounts[1].id).toBe(users[1].id);
|
expect(data[1].accounts[1].id).toBe(users[1].id);
|
||||||
expect(data[2].id).toBe(users[4].id);
|
expect(data[2].id).toBe(users[4].id);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { randomString } from "@/math";
|
||||||
import { db } from "@versia/kit/db";
|
import { db } from "@versia/kit/db";
|
||||||
import { Users } from "@versia/kit/tables";
|
import { Users } from "@versia/kit/tables";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { fakeRequest, getSolvedChallenge } from "~/tests/utils";
|
import { generateClient, getSolvedChallenge } from "~/tests/utils";
|
||||||
|
|
||||||
const username = randomString(10, "hex");
|
const username = randomString(10, "hex");
|
||||||
const username2 = randomString(10, "hex");
|
const username2 = randomString(10, "hex");
|
||||||
|
|
@ -16,208 +16,211 @@ afterEach(async () => {
|
||||||
// /api/v1/statuses
|
// /api/v1/statuses
|
||||||
describe("/api/v1/accounts", () => {
|
describe("/api/v1/accounts", () => {
|
||||||
test("should create a new account", async () => {
|
test("should create a new account", async () => {
|
||||||
const response = await fakeRequest("/api/v1/accounts", {
|
await using client = await generateClient();
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
username,
|
|
||||||
email: "bob@gamer.com",
|
|
||||||
password: "password",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.ok).toBe(true);
|
const { ok, raw } = await client.registerAccount(
|
||||||
expect(response.headers.get("Content-Type")).not.toContain("json");
|
username,
|
||||||
|
"bob@gamer.com",
|
||||||
|
"password",
|
||||||
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
|
expect(raw.headers.get("Content-Type")).not.toContain("json");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should refuse invalid emails", async () => {
|
test("should refuse invalid emails", async () => {
|
||||||
const response = await fakeRequest("/api/v1/accounts", {
|
await using client = await generateClient();
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
username,
|
|
||||||
email: "bob",
|
|
||||||
password: "password",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.status).toBe(422);
|
const { ok, raw } = await client.registerAccount(
|
||||||
|
username,
|
||||||
|
"bob",
|
||||||
|
"password",
|
||||||
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ok).toBe(false);
|
||||||
|
expect(raw.status).toBe(422);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should require a password", async () => {
|
test("should require a password", async () => {
|
||||||
const response = await fakeRequest("/api/v1/accounts", {
|
await using client = await generateClient();
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
username,
|
|
||||||
email: "contatc@bob.com",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.status).toBe(422);
|
const { ok, raw } = await client.registerAccount(
|
||||||
|
username,
|
||||||
|
"bob@gamer.com",
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ok).toBe(false);
|
||||||
|
expect(raw.status).toBe(422);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should not allow a previously registered email", async () => {
|
test("should not allow a previously registered email", async () => {
|
||||||
await fakeRequest("/api/v1/accounts", {
|
await using client = await generateClient();
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
username,
|
|
||||||
email: "contact@george.com",
|
|
||||||
password: "password",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await fakeRequest("/api/v1/accounts", {
|
const { ok } = await client.registerAccount(
|
||||||
method: "POST",
|
username,
|
||||||
headers: {
|
"contact@george.com",
|
||||||
"Content-Type": "application/json",
|
"password",
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
);
|
||||||
username: username2,
|
|
||||||
email: "contact@george.com",
|
|
||||||
password: "password",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.status).toBe(422);
|
expect(ok).toBe(true);
|
||||||
|
|
||||||
|
const { ok: ok2, raw } = await client.registerAccount(
|
||||||
|
username2,
|
||||||
|
"contact@george.com",
|
||||||
|
"password",
|
||||||
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ok2).toBe(false);
|
||||||
|
expect(raw.status).toBe(422);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should not allow a previously registered email (case insensitive)", async () => {
|
test("should not allow a previously registered email (case insensitive)", async () => {
|
||||||
await fakeRequest("/api/v1/accounts", {
|
await using client = await generateClient();
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
username,
|
|
||||||
email: "contact@george.com",
|
|
||||||
password: "password",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await fakeRequest("/api/v1/accounts", {
|
const { ok } = await client.registerAccount(
|
||||||
method: "POST",
|
username,
|
||||||
headers: {
|
"contact@george.com",
|
||||||
"Content-Type": "application/json",
|
"password",
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
);
|
||||||
username: username2,
|
|
||||||
email: "CONTACT@george.CoM",
|
|
||||||
password: "password",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.status).toBe(422);
|
expect(ok).toBe(true);
|
||||||
|
|
||||||
|
const { ok: ok2, raw } = await client.registerAccount(
|
||||||
|
username2,
|
||||||
|
"CONTACT@george.CoM",
|
||||||
|
"password",
|
||||||
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ok2).toBe(false);
|
||||||
|
expect(raw.status).toBe(422);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should not allow invalid usernames (not a-z_0-9)", async () => {
|
test("should not allow invalid usernames (not a-z_0-9)", async () => {
|
||||||
const response1 = await fakeRequest("/api/v1/accounts", {
|
await using client = await generateClient();
|
||||||
method: "POST",
|
|
||||||
headers: {
|
const { ok: ok1, raw: raw1 } = await client.registerAccount(
|
||||||
"Content-Type": "application/json",
|
"bob$",
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
"contact@george.com",
|
||||||
|
"password",
|
||||||
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
);
|
||||||
username: "bob$",
|
|
||||||
email: "contact@bob.com",
|
|
||||||
password: "password",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response1.status).toBe(422);
|
expect(ok1).toBe(false);
|
||||||
|
expect(raw1.status).toBe(422);
|
||||||
|
|
||||||
const response2 = await fakeRequest("/api/v1/accounts", {
|
const { ok: ok2, raw: raw2 } = await client.registerAccount(
|
||||||
method: "POST",
|
"bob-markey",
|
||||||
headers: {
|
"contact@bob.com",
|
||||||
"Content-Type": "application/json",
|
"password",
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
);
|
||||||
username: "bob-markey",
|
|
||||||
email: "contact@bob.com",
|
|
||||||
password: "password",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response2.status).toBe(422);
|
expect(ok2).toBe(false);
|
||||||
|
expect(raw2.status).toBe(422);
|
||||||
|
|
||||||
const response3 = await fakeRequest("/api/v1/accounts", {
|
const { ok: ok3, raw: raw3 } = await client.registerAccount(
|
||||||
method: "POST",
|
"bob markey",
|
||||||
headers: {
|
"contact@bob.com",
|
||||||
"Content-Type": "application/json",
|
"password",
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
);
|
||||||
username: "bob markey",
|
|
||||||
email: "contact@bob.com",
|
|
||||||
password: "password",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response3.status).toBe(422);
|
expect(ok3).toBe(false);
|
||||||
|
expect(raw3.status).toBe(422);
|
||||||
|
|
||||||
const response4 = await fakeRequest("/api/v1/accounts", {
|
const { ok: ok4, raw: raw4 } = await client.registerAccount(
|
||||||
method: "POST",
|
"BOB",
|
||||||
headers: {
|
"contact@bob.com",
|
||||||
"Content-Type": "application/json",
|
"password",
|
||||||
"X-Challenge-Solution": await getSolvedChallenge(),
|
true,
|
||||||
|
"en",
|
||||||
|
"testing",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"X-Challenge-Solution": await getSolvedChallenge(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
);
|
||||||
username: "BOB",
|
|
||||||
email: "contact@bob.com",
|
|
||||||
password: "password",
|
|
||||||
agreement: "true",
|
|
||||||
locale: "en",
|
|
||||||
reason: "testing",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response4.status).toBe(422);
|
expect(ok4).toBe(false);
|
||||||
|
expect(raw4.status).toBe(422);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { afterAll, describe, expect, test } from "bun:test";
|
import { afterAll, describe, expect, test } from "bun:test";
|
||||||
import type { Account as ApiAccount } from "@versia/client/types";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(5);
|
const { users, deleteUsers } = await getTestUsers(5);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
|
|
@ -11,18 +10,11 @@ afterAll(async () => {
|
||||||
// /api/v1/accounts/lookup
|
// /api/v1/accounts/lookup
|
||||||
describe("/api/v1/accounts/lookup", () => {
|
describe("/api/v1/accounts/lookup", () => {
|
||||||
test("should return 200 with users", async () => {
|
test("should return 200 with users", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/lookup?acct=${users[0].data.username}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.lookupAccount(users[0].data.username);
|
||||||
|
|
||||||
const data = (await response.json()) as ApiAccount[];
|
expect(ok).toBe(true);
|
||||||
expect(data).toEqual(
|
expect(data).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: users[0].id,
|
id: users[0].id,
|
||||||
|
|
@ -35,15 +27,13 @@ describe("/api/v1/accounts/lookup", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should require exact case", async () => {
|
test("should require exact case", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/lookup?acct=${users[0].data.username.toUpperCase()}`,
|
|
||||||
{
|
const { ok, raw } = await client.lookupAccount(
|
||||||
headers: {
|
users[0].data.username.toUpperCase(),
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(response.status).toBe(404);
|
expect(ok).toBe(false);
|
||||||
|
expect(raw.status).toBe(404);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||||
import { db } from "@versia/kit/db";
|
import { db } from "@versia/kit/db";
|
||||||
import { Users } from "@versia/kit/tables";
|
import { Users } from "@versia/kit/tables";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(5);
|
const { users, deleteUsers } = await getTestUsers(5);
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
// user0 should be `locked`
|
// user0 should be `locked`
|
||||||
|
|
@ -15,27 +15,17 @@ beforeAll(async () => {
|
||||||
.set({ isLocked: true })
|
.set({ isLocked: true })
|
||||||
.where(eq(Users.id, users[0].id));
|
.where(eq(Users.id, users[0].id));
|
||||||
|
|
||||||
const res1 = await fakeRequest(`/api/v1/accounts/${users[0].id}/follow`, {
|
await using client1 = await generateClient(users[1]);
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res1.ok).toBe(true);
|
const { ok } = await client1.followAccount(users[0].id);
|
||||||
|
|
||||||
const res2 = await fakeRequest(`/api/v1/accounts/${users[2].id}/follow`, {
|
expect(ok).toBe(true);
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res2.ok).toBe(true);
|
await using client0 = await generateClient(users[0]);
|
||||||
|
|
||||||
|
const { ok: ok2 } = await client0.followAccount(users[2].id);
|
||||||
|
|
||||||
|
expect(ok2).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|
@ -45,27 +35,21 @@ afterAll(async () => {
|
||||||
// /api/v1/accounts/relationships
|
// /api/v1/accounts/relationships
|
||||||
describe("/api/v1/accounts/relationships", () => {
|
describe("/api/v1/accounts/relationships", () => {
|
||||||
test("should return 401 if not authenticated", async () => {
|
test("should return 401 if not authenticated", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient();
|
||||||
`/api/v1/accounts/relationships?id[]=${users[2].id}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(401);
|
const { ok, raw } = await client.getRelationships([users[2].id]);
|
||||||
|
|
||||||
|
expect(ok).toBe(false);
|
||||||
|
expect(raw.status).toBe(401);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return relationships", async () => {
|
test("should return relationships", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/relationships?id[]=${users[2].id}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getRelationships([users[2].id]);
|
||||||
|
|
||||||
const body = await response.json();
|
expect(ok).toBe(true);
|
||||||
expect(body).toEqual(
|
expect(data).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: users[2].id,
|
id: users[2].id,
|
||||||
|
|
@ -83,19 +67,12 @@ describe("/api/v1/accounts/relationships", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should be requested_by user1", async () => {
|
test("should be requested_by user1", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/relationships?id[]=${users[1].id}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getRelationships([users[1].id]);
|
||||||
|
|
||||||
const body = await response.json();
|
expect(ok).toBe(true);
|
||||||
expect(body).toEqual(
|
expect(data).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
following: false,
|
following: false,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { afterAll, describe, expect, test } from "bun:test";
|
import { afterAll, describe, expect, test } from "bun:test";
|
||||||
import type { Account as ApiAccount } from "@versia/client/types";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(5);
|
const { users, deleteUsers } = await getTestUsers(5);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
|
|
@ -11,18 +10,11 @@ afterAll(async () => {
|
||||||
// /api/v1/accounts/search
|
// /api/v1/accounts/search
|
||||||
describe("/api/v1/accounts/search", () => {
|
describe("/api/v1/accounts/search", () => {
|
||||||
test("should return 200 with users", async () => {
|
test("should return 200 with users", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
`/api/v1/accounts/search?q=${users[0].data.username}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.searchAccount(users[0].data.username);
|
||||||
|
|
||||||
const data = (await response.json()) as ApiAccount[];
|
expect(ok).toBe(true);
|
||||||
expect(data).toEqual(
|
expect(data).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { afterAll, describe, expect, test } from "bun:test";
|
import { afterAll, describe, expect, test } from "bun:test";
|
||||||
import type { Account as APIAccount } from "@versia/client/types";
|
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
|
|
||||||
const { tokens, deleteUsers } = await getTestUsers(1);
|
const { users, deleteUsers } = await getTestUsers(1);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await deleteUsers();
|
await deleteUsers();
|
||||||
|
|
@ -13,53 +12,28 @@ afterAll(async () => {
|
||||||
describe("/api/v1/accounts/update_credentials", () => {
|
describe("/api/v1/accounts/update_credentials", () => {
|
||||||
describe("HTML injection testing", () => {
|
describe("HTML injection testing", () => {
|
||||||
test("should not allow HTML injection", async () => {
|
test("should not allow HTML injection", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
"/api/v1/accounts/update_credentials",
|
|
||||||
{
|
|
||||||
method: "PATCH",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
body: new URLSearchParams({
|
|
||||||
note: "Hi! <script>alert('Hello, world!');</script>",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { ok, data } = await client.updateCredentials({
|
||||||
expect(response.headers.get("content-type")).toContain(
|
note: "Hi! <script>alert('Hello, world!');</script>",
|
||||||
"application/json",
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const object = (await response.json()) as APIAccount;
|
expect(ok).toBe(true);
|
||||||
|
expect(data.note).toBe(
|
||||||
expect(object.note).toBe(
|
|
||||||
"<p>Hi! <script>alert('Hello, world!');</script></p>\n",
|
"<p>Hi! <script>alert('Hello, world!');</script></p>\n",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should rewrite all image and video src to go through proxy", async () => {
|
test("should rewrite all image and video src to go through proxy", async () => {
|
||||||
const response = await fakeRequest(
|
await using client = await generateClient(users[0]);
|
||||||
"/api/v1/accounts/update_credentials",
|
|
||||||
{
|
|
||||||
method: "PATCH",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
body: new URLSearchParams({
|
|
||||||
note: "<img src='https://example.com/image.jpg'> <video src='https://example.com/video.mp4'> Test!",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { ok, data } = await client.updateCredentials({
|
||||||
expect(response.headers.get("content-type")).toContain(
|
note: "<img src='https://example.com/image.jpg'> <video src='https://example.com/video.mp4'> Test!",
|
||||||
"application/json",
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const object = (await response.json()) as APIAccount;
|
expect(ok).toBe(true);
|
||||||
// Proxy url is base_url/media/proxy/<base64url encoded url>
|
expect(data.note).toBe(
|
||||||
expect(object.note).toBe(
|
// Proxy url is base_url/media/proxy/<base64url encoded url>
|
||||||
`<p><img src="${config.http.base_url}media/proxy/${Buffer.from(
|
`<p><img src="${config.http.base_url}media/proxy/${Buffer.from(
|
||||||
"https://example.com/image.jpg",
|
"https://example.com/image.jpg",
|
||||||
).toString("base64url")}"> <video src="${
|
).toString("base64url")}"> <video src="${
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,15 @@
|
||||||
import { describe, expect, test } from "bun:test";
|
import { describe, expect, test } from "bun:test";
|
||||||
import { fakeRequest } from "~/tests/utils";
|
import { generateClient } from "~/tests/utils";
|
||||||
|
|
||||||
// /api/v1/challenges
|
// /api/v1/challenges
|
||||||
describe("/api/v1/challenges", () => {
|
describe("/api/v1/challenges", () => {
|
||||||
test("should get a challenge", async () => {
|
test("should get a challenge", async () => {
|
||||||
const response = await fakeRequest("/api/v1/challenges", {
|
await using client = await generateClient();
|
||||||
method: "POST",
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getChallenge();
|
||||||
|
|
||||||
const body = await response.json();
|
expect(ok).toBe(true);
|
||||||
|
expect(data).toMatchObject({
|
||||||
expect(body).toMatchObject({
|
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
algorithm: expect.any(String),
|
algorithm: expect.any(String),
|
||||||
challenge: expect.any(String),
|
challenge: expect.any(String),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { apiRoute, auth } from "@/api";
|
import { apiRoute, auth } from "@/api";
|
||||||
import { generateChallenge } from "@/challenges";
|
import { generateChallenge } from "@/challenges";
|
||||||
import { createRoute, z } from "@hono/zod-openapi";
|
import { createRoute } from "@hono/zod-openapi";
|
||||||
|
import { Challenge } from "@versia/client-ng/schemas";
|
||||||
import { ApiError } from "~/classes/errors/api-error";
|
import { ApiError } from "~/classes/errors/api-error";
|
||||||
import { config } from "~/config.ts";
|
import { config } from "~/config.ts";
|
||||||
import { ErrorSchema } from "~/types/api";
|
import { ErrorSchema } from "~/types/api";
|
||||||
|
|
@ -21,14 +22,7 @@ const route = createRoute({
|
||||||
description: "Challenge",
|
description: "Challenge",
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
schema: z.object({
|
schema: Challenge,
|
||||||
id: z.string(),
|
|
||||||
algorithm: z.enum(["SHA-1", "SHA-256", "SHA-512"]),
|
|
||||||
challenge: z.string(),
|
|
||||||
maxnumber: z.number().optional(),
|
|
||||||
salt: z.string(),
|
|
||||||
signature: z.string(),
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,53 +2,42 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||||
import { db } from "@versia/kit/db";
|
import { db } from "@versia/kit/db";
|
||||||
import { Emojis } from "@versia/kit/tables";
|
import { Emojis } from "@versia/kit/tables";
|
||||||
import { inArray } from "drizzle-orm";
|
import { inArray } from "drizzle-orm";
|
||||||
import { fakeRequest, getTestUsers } from "~/tests/utils";
|
import { generateClient, getTestUsers } from "~/tests/utils";
|
||||||
|
|
||||||
const { users, tokens, deleteUsers } = await getTestUsers(2);
|
const { users, deleteUsers } = await getTestUsers(2);
|
||||||
|
|
||||||
// Make user 2 an admin
|
// Make user 2 an admin
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await users[1].update({ isAdmin: true });
|
await users[1].update({ isAdmin: true });
|
||||||
|
|
||||||
// Upload one emoji as admin, then one as each user
|
// Upload one emoji as admin, then one as each user
|
||||||
const response = await fakeRequest("/api/v1/emojis", {
|
await using client1 = await generateClient(users[1]);
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
const { ok } = await client1.uploadEmoji(
|
||||||
"Content-Type": "application/json",
|
"test1",
|
||||||
},
|
new URL("https://cdn.versia.social/logo.webp"),
|
||||||
method: "POST",
|
{
|
||||||
body: JSON.stringify({
|
|
||||||
shortcode: "test1",
|
|
||||||
element: "https://cdn.versia.social/logo.webp",
|
|
||||||
global: true,
|
global: true,
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.status).toBe(201);
|
|
||||||
|
|
||||||
await fakeRequest("/api/v1/emojis", {
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
},
|
||||||
method: "POST",
|
);
|
||||||
body: JSON.stringify({
|
|
||||||
shortcode: "test2",
|
|
||||||
element: "https://cdn.versia.social/logo.webp",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
await fakeRequest("/api/v1/emojis", {
|
expect(ok).toBe(true);
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
await using client0 = await generateClient(users[0]);
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
const { ok: ok2 } = await client0.uploadEmoji(
|
||||||
method: "POST",
|
"test2",
|
||||||
body: JSON.stringify({
|
new URL("https://cdn.versia.social/logo.webp"),
|
||||||
shortcode: "test3",
|
);
|
||||||
element: "https://cdn.versia.social/logo.webp",
|
|
||||||
}),
|
expect(ok2).toBe(true);
|
||||||
});
|
|
||||||
|
const { ok: ok3 } = await client1.uploadEmoji(
|
||||||
|
"test3",
|
||||||
|
new URL("https://cdn.versia.social/logo.webp"),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(ok3).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|
@ -61,31 +50,23 @@ afterAll(async () => {
|
||||||
|
|
||||||
describe("/api/v1/custom_emojis", () => {
|
describe("/api/v1/custom_emojis", () => {
|
||||||
test("should return all global emojis", async () => {
|
test("should return all global emojis", async () => {
|
||||||
const response = await fakeRequest("/api/v1/custom_emojis", {
|
await using client = await generateClient(users[1]);
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[1].data.accessToken}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getInstanceCustomEmojis();
|
||||||
expect(response.headers.get("content-type")).toContain(
|
|
||||||
"application/json",
|
|
||||||
);
|
|
||||||
|
|
||||||
const emojis = await response.json();
|
|
||||||
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
// Should contain test1 and test2, but not test2
|
// Should contain test1 and test2, but not test2
|
||||||
expect(emojis).toContainEqual(
|
expect(data).toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
shortcode: "test1",
|
shortcode: "test1",
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
expect(emojis).not.toContainEqual(
|
expect(data).not.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
shortcode: "test2",
|
shortcode: "test2",
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
expect(emojis).toContainEqual(
|
expect(data).toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
shortcode: "test3",
|
shortcode: "test3",
|
||||||
}),
|
}),
|
||||||
|
|
@ -93,31 +74,23 @@ describe("/api/v1/custom_emojis", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return all user emojis", async () => {
|
test("should return all user emojis", async () => {
|
||||||
const response = await fakeRequest("/api/v1/custom_emojis", {
|
await using client = await generateClient(users[0]);
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${tokens[0].data.accessToken}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getInstanceCustomEmojis();
|
||||||
expect(response.headers.get("content-type")).toContain(
|
|
||||||
"application/json",
|
|
||||||
);
|
|
||||||
|
|
||||||
const emojis = await response.json();
|
|
||||||
|
|
||||||
|
expect(ok).toBe(true);
|
||||||
// Should contain test1 and test2, but not test3
|
// Should contain test1 and test2, but not test3
|
||||||
expect(emojis).toContainEqual(
|
expect(data).toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
shortcode: "test1",
|
shortcode: "test1",
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
expect(emojis).toContainEqual(
|
expect(data).toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
shortcode: "test2",
|
shortcode: "test2",
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
expect(emojis).not.toContainEqual(
|
expect(data).not.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
shortcode: "test3",
|
shortcode: "test3",
|
||||||
}),
|
}),
|
||||||
|
|
@ -125,27 +98,24 @@ describe("/api/v1/custom_emojis", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return all global emojis when signed out", async () => {
|
test("should return all global emojis when signed out", async () => {
|
||||||
const response = await fakeRequest("/api/v1/custom_emojis");
|
await using client = await generateClient();
|
||||||
|
|
||||||
expect(response.status).toBe(200);
|
const { data, ok } = await client.getInstanceCustomEmojis();
|
||||||
expect(response.headers.get("content-type")).toContain(
|
|
||||||
"application/json",
|
|
||||||
);
|
|
||||||
|
|
||||||
const emojis = await response.json();
|
expect(ok).toBe(true);
|
||||||
|
|
||||||
// Should contain test1, but not test2 or test3
|
// Should contain test1, but not test2 or test3
|
||||||
expect(emojis).toContainEqual(
|
expect(data).toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
shortcode: "test1",
|
shortcode: "test1",
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
expect(emojis).not.toContainEqual(
|
expect(data).not.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
shortcode: "test2",
|
shortcode: "test2",
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
expect(emojis).not.toContainEqual(
|
expect(data).not.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
shortcode: "test3",
|
shortcode: "test3",
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,6 @@ export { Status, Mention, StatusSource } from "./schemas/status.ts";
|
||||||
export { Tag } from "./schemas/tag.ts";
|
export { Tag } from "./schemas/tag.ts";
|
||||||
export { Token } from "./schemas/token.ts";
|
export { Token } from "./schemas/token.ts";
|
||||||
export { TermsOfService } from "./schemas/tos.ts";
|
export { TermsOfService } from "./schemas/tos.ts";
|
||||||
export { Role, NoteReaction, SSOConfig } from "./schemas/versia.ts";
|
export { Role, NoteReaction, SSOConfig, Challenge } from "./schemas/versia.ts";
|
||||||
|
|
||||||
export { Id, iso631, zBoolean } from "./schemas/common.ts";
|
export { Id, iso631, zBoolean } from "./schemas/common.ts";
|
||||||
|
|
|
||||||
|
|
@ -105,3 +105,35 @@ export const SSOConfig = z.object({
|
||||||
"An array of external OpenID Connect providers that users can link their accounts to.",
|
"An array of external OpenID Connect providers that users can link their accounts to.",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* Versia Server API extension */
|
||||||
|
export const Challenge = z
|
||||||
|
.object({
|
||||||
|
id: Id.openapi({}).openapi({
|
||||||
|
description: "Challenge ID in the database.",
|
||||||
|
example: "b4a7e0f0-8f6a-479b-910b-9265c070d5bd",
|
||||||
|
}),
|
||||||
|
algorithm: z.enum(["SHA-1", "SHA-256", "SHA-512"]).openapi({
|
||||||
|
description: "Algorithm used to generate the challenge.",
|
||||||
|
example: "SHA-1",
|
||||||
|
}),
|
||||||
|
challenge: z.string().openapi({
|
||||||
|
description: "Challenge to solve.",
|
||||||
|
example: "1234567890",
|
||||||
|
}),
|
||||||
|
maxnumber: z.number().int().nonnegative().optional().openapi({
|
||||||
|
description: "Maximum number to solve the challenge.",
|
||||||
|
example: 100,
|
||||||
|
}),
|
||||||
|
salt: z.string().openapi({
|
||||||
|
description: "Salt used to generate the challenge.",
|
||||||
|
example: "1234567890",
|
||||||
|
}),
|
||||||
|
signature: z.string().openapi({
|
||||||
|
description: "Signature of the challenge.",
|
||||||
|
example: "1234567890",
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.openapi({
|
||||||
|
description: "A cryptographic challenge to solve. Used for Captchas.",
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -91,9 +91,10 @@ export class BaseClient {
|
||||||
public constructor(
|
public constructor(
|
||||||
protected baseUrl: URL,
|
protected baseUrl: URL,
|
||||||
private accessToken?: string,
|
private accessToken?: string,
|
||||||
public globalCatch: (error: ResponseError) => void = () => {
|
private options: {
|
||||||
// Do nothing by default
|
globalCatch?: (error: ResponseError) => void;
|
||||||
},
|
throwOnError?: boolean;
|
||||||
|
} = {},
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public get url(): URL {
|
public get url(): URL {
|
||||||
|
|
@ -104,16 +105,21 @@ export class BaseClient {
|
||||||
return this.accessToken;
|
return this.accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Overridable by testing */
|
||||||
|
private fetch = fetch;
|
||||||
|
|
||||||
private async request<ReturnType>(
|
private async request<ReturnType>(
|
||||||
request: Request,
|
request: Request,
|
||||||
): Promise<Output<ReturnType>> {
|
): Promise<Output<ReturnType>> {
|
||||||
const result = await fetch(request);
|
const result = await this.fetch(request);
|
||||||
const isJson = result.headers
|
const isJson = result.headers
|
||||||
.get("Content-Type")
|
.get("Content-Type")
|
||||||
?.includes("application/json");
|
?.includes("application/json");
|
||||||
|
|
||||||
if (!result.ok) {
|
if (!result.ok && this.options.throwOnError) {
|
||||||
const error = isJson ? await result.json() : await result.text();
|
const error = isJson
|
||||||
|
? await result.clone().json()
|
||||||
|
: await result.clone().text();
|
||||||
throw new ResponseError(
|
throw new ResponseError(
|
||||||
{
|
{
|
||||||
data: error,
|
data: error,
|
||||||
|
|
@ -127,8 +133,10 @@ export class BaseClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: isJson ? await result.json() : (await result.text()) || null,
|
data: isJson
|
||||||
ok: true,
|
? await result.clone().json()
|
||||||
|
: (await result.clone().text()) || null,
|
||||||
|
ok: result.ok,
|
||||||
raw: result,
|
raw: result,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -168,19 +176,19 @@ export class BaseClient {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public get<ReturnType>(
|
public get<ReturnType = void>(
|
||||||
path: string,
|
path: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<ReturnType>> {
|
): Promise<Output<ReturnType>> {
|
||||||
return this.request<ReturnType>(
|
return this.request<ReturnType>(
|
||||||
this.constructRequest(path, "GET", undefined, extra),
|
this.constructRequest(path, "GET", undefined, extra),
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
this.globalCatch(e);
|
this.options.globalCatch?.(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public post<ReturnType>(
|
public post<ReturnType = void>(
|
||||||
path: string,
|
path: string,
|
||||||
body?: object,
|
body?: object,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
|
|
@ -188,12 +196,12 @@ export class BaseClient {
|
||||||
return this.request<ReturnType>(
|
return this.request<ReturnType>(
|
||||||
this.constructRequest(path, "POST", body, extra),
|
this.constructRequest(path, "POST", body, extra),
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
this.globalCatch(e);
|
this.options.globalCatch?.(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public postForm<ReturnType>(
|
public postForm<ReturnType = void>(
|
||||||
path: string,
|
path: string,
|
||||||
body: FormData | ConvertibleObject,
|
body: FormData | ConvertibleObject,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
|
|
@ -206,12 +214,12 @@ export class BaseClient {
|
||||||
extra,
|
extra,
|
||||||
),
|
),
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
this.globalCatch(e);
|
this.options.globalCatch?.(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public put<ReturnType>(
|
public put<ReturnType = void>(
|
||||||
path: string,
|
path: string,
|
||||||
body?: object,
|
body?: object,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
|
|
@ -219,12 +227,12 @@ export class BaseClient {
|
||||||
return this.request<ReturnType>(
|
return this.request<ReturnType>(
|
||||||
this.constructRequest(path, "PUT", body, extra),
|
this.constructRequest(path, "PUT", body, extra),
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
this.globalCatch(e);
|
this.options.globalCatch?.(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public putForm<ReturnType>(
|
public putForm<ReturnType = void>(
|
||||||
path: string,
|
path: string,
|
||||||
body: FormData | ConvertibleObject,
|
body: FormData | ConvertibleObject,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
|
|
@ -237,12 +245,12 @@ export class BaseClient {
|
||||||
extra,
|
extra,
|
||||||
),
|
),
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
this.globalCatch(e);
|
this.options.globalCatch?.(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public patch<ReturnType>(
|
public patch<ReturnType = void>(
|
||||||
path: string,
|
path: string,
|
||||||
body?: object,
|
body?: object,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
|
|
@ -250,12 +258,12 @@ export class BaseClient {
|
||||||
return this.request<ReturnType>(
|
return this.request<ReturnType>(
|
||||||
this.constructRequest(path, "PATCH", body, extra),
|
this.constructRequest(path, "PATCH", body, extra),
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
this.globalCatch(e);
|
this.options.globalCatch?.(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public patchForm<ReturnType>(
|
public patchForm<ReturnType = void>(
|
||||||
path: string,
|
path: string,
|
||||||
body: FormData | ConvertibleObject,
|
body: FormData | ConvertibleObject,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
|
|
@ -268,12 +276,12 @@ export class BaseClient {
|
||||||
extra,
|
extra,
|
||||||
),
|
),
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
this.globalCatch(e);
|
this.options.globalCatch?.(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public delete<ReturnType>(
|
public delete<ReturnType = void>(
|
||||||
path: string,
|
path: string,
|
||||||
body?: object,
|
body?: object,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
|
|
@ -281,12 +289,12 @@ export class BaseClient {
|
||||||
return this.request<ReturnType>(
|
return this.request<ReturnType>(
|
||||||
this.constructRequest(path, "DELETE", body, extra),
|
this.constructRequest(path, "DELETE", body, extra),
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
this.globalCatch(e);
|
this.options.globalCatch?.(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public deleteForm<ReturnType>(
|
public deleteForm<ReturnType = void>(
|
||||||
path: string,
|
path: string,
|
||||||
body: FormData | ConvertibleObject,
|
body: FormData | ConvertibleObject,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
|
|
@ -299,7 +307,7 @@ export class BaseClient {
|
||||||
extra,
|
extra,
|
||||||
),
|
),
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
this.globalCatch(e);
|
this.options.globalCatch?.(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import type { Attachment } from "../schemas/attachment.ts";
|
||||||
import type { Context } from "../schemas/context.ts";
|
import type { Context } from "../schemas/context.ts";
|
||||||
import type { CustomEmoji } from "../schemas/emoji.ts";
|
import type { CustomEmoji } from "../schemas/emoji.ts";
|
||||||
import type { ExtendedDescription } from "../schemas/extended-description.ts";
|
import type { ExtendedDescription } from "../schemas/extended-description.ts";
|
||||||
|
import type { FamiliarFollowers } from "../schemas/familiar-followers.ts";
|
||||||
import type { Instance } from "../schemas/instance.ts";
|
import type { Instance } from "../schemas/instance.ts";
|
||||||
import type { Marker } from "../schemas/marker.ts";
|
import type { Marker } from "../schemas/marker.ts";
|
||||||
import type { Notification } from "../schemas/notification.ts";
|
import type { Notification } from "../schemas/notification.ts";
|
||||||
|
|
@ -21,7 +22,7 @@ import type { Status, StatusSource } from "../schemas/status.ts";
|
||||||
import type { Tag } from "../schemas/tag.ts";
|
import type { Tag } from "../schemas/tag.ts";
|
||||||
import type { Token } from "../schemas/token.ts";
|
import type { Token } from "../schemas/token.ts";
|
||||||
import type { TermsOfService } from "../schemas/tos.ts";
|
import type { TermsOfService } from "../schemas/tos.ts";
|
||||||
import type { Role } from "../schemas/versia.ts";
|
import type { Challenge, Role } from "../schemas/versia.ts";
|
||||||
import { BaseClient, type Output } from "./base.ts";
|
import { BaseClient, type Output } from "./base.ts";
|
||||||
import { DEFAULT_SCOPE, NO_REDIRECT } from "./constants.ts";
|
import { DEFAULT_SCOPE, NO_REDIRECT } from "./constants.ts";
|
||||||
|
|
||||||
|
|
@ -71,7 +72,7 @@ export class Client extends BaseClient {
|
||||||
account_ids: string[],
|
account_ids: string[],
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.post<void>(
|
return this.post(
|
||||||
`/api/v1/lists/${id}/accounts`,
|
`/api/v1/lists/${id}/accounts`,
|
||||||
{ account_ids },
|
{ account_ids },
|
||||||
extra,
|
extra,
|
||||||
|
|
@ -89,7 +90,7 @@ export class Client extends BaseClient {
|
||||||
name: string,
|
name: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.put<void>(
|
return this.put(
|
||||||
`/api/v1/announcements/${id}/reactions/${name}`,
|
`/api/v1/announcements/${id}/reactions/${name}`,
|
||||||
undefined,
|
undefined,
|
||||||
extra,
|
extra,
|
||||||
|
|
@ -108,7 +109,7 @@ export class Client extends BaseClient {
|
||||||
role_id: string,
|
role_id: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.post<void>(
|
return this.post(
|
||||||
`/api/v1/accounts/${account_id}/roles/${role_id}`,
|
`/api/v1/accounts/${account_id}/roles/${role_id}`,
|
||||||
undefined,
|
undefined,
|
||||||
extra,
|
extra,
|
||||||
|
|
@ -141,7 +142,7 @@ export class Client extends BaseClient {
|
||||||
domain: string,
|
domain: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.post<void>("/api/v1/domain_blocks", { domain }, extra);
|
return this.post("/api/v1/domain_blocks", { domain }, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bookmarkStatus(
|
public bookmarkStatus(
|
||||||
|
|
@ -164,7 +165,7 @@ export class Client extends BaseClient {
|
||||||
id: string,
|
id: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.delete<void>(
|
return this.delete(
|
||||||
`/api/v1/scheduled_statuses/${id}/cancel`,
|
`/api/v1/scheduled_statuses/${id}/cancel`,
|
||||||
undefined,
|
undefined,
|
||||||
extra,
|
extra,
|
||||||
|
|
@ -287,7 +288,7 @@ export class Client extends BaseClient {
|
||||||
account_ids: string[],
|
account_ids: string[],
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.delete<void>(
|
return this.delete(
|
||||||
`/api/v1/lists/${id}/accounts`,
|
`/api/v1/lists/${id}/accounts`,
|
||||||
{ account_ids },
|
{ account_ids },
|
||||||
extra,
|
extra,
|
||||||
|
|
@ -303,11 +304,7 @@ export class Client extends BaseClient {
|
||||||
id: string,
|
id: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.delete<void>(
|
return this.delete(`/api/v1/conversations/${id}`, undefined, extra);
|
||||||
`/api/v1/conversations/${id}`,
|
|
||||||
undefined,
|
|
||||||
extra,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -318,7 +315,7 @@ export class Client extends BaseClient {
|
||||||
* @return Empty.
|
* @return Empty.
|
||||||
*/
|
*/
|
||||||
public deleteEmoji(id: string, extra?: RequestInit): Promise<Output<void>> {
|
public deleteEmoji(id: string, extra?: RequestInit): Promise<Output<void>> {
|
||||||
return this.delete<void>(`/api/v1/emojis/${id}`, undefined, extra);
|
return this.delete(`/api/v1/emojis/${id}`, undefined, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -350,11 +347,7 @@ export class Client extends BaseClient {
|
||||||
id: string,
|
id: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.delete<void>(
|
return this.delete(`/api/v1/featured_tags/${id}`, undefined, extra);
|
||||||
`/api/v1/featured_tags/${id}`,
|
|
||||||
undefined,
|
|
||||||
extra,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -363,14 +356,14 @@ export class Client extends BaseClient {
|
||||||
* @param id Target list ID.
|
* @param id Target list ID.
|
||||||
*/
|
*/
|
||||||
public deleteList(id: string, extra?: RequestInit): Promise<Output<void>> {
|
public deleteList(id: string, extra?: RequestInit): Promise<Output<void>> {
|
||||||
return this.delete<void>(`/api/v1/lists/${id}`, undefined, extra);
|
return this.delete(`/api/v1/lists/${id}`, undefined, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DELETE /api/v1/push/subscription
|
* DELETE /api/v1/push/subscription
|
||||||
*/
|
*/
|
||||||
public deletePushSubscription(extra?: RequestInit): Promise<Output<void>> {
|
public deletePushSubscription(extra?: RequestInit): Promise<Output<void>> {
|
||||||
return this.delete<void>("/api/v1/push/subscription", undefined, extra);
|
return this.delete("/api/v1/push/subscription", undefined, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -381,7 +374,7 @@ export class Client extends BaseClient {
|
||||||
* @return Empty.
|
* @return Empty.
|
||||||
*/
|
*/
|
||||||
public deleteRole(id: string, extra?: RequestInit): Promise<Output<void>> {
|
public deleteRole(id: string, extra?: RequestInit): Promise<Output<void>> {
|
||||||
return this.delete<void>(`/api/v1/roles/${id}`, undefined, extra);
|
return this.delete(`/api/v1/roles/${id}`, undefined, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -412,7 +405,7 @@ export class Client extends BaseClient {
|
||||||
id: string,
|
id: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.post<void>(
|
return this.post(
|
||||||
`/api/v1/instance/announcements/${id}/dismiss`,
|
`/api/v1/instance/announcements/${id}/dismiss`,
|
||||||
undefined,
|
undefined,
|
||||||
extra,
|
extra,
|
||||||
|
|
@ -428,7 +421,7 @@ export class Client extends BaseClient {
|
||||||
id: string,
|
id: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.post<void>(
|
return this.post(
|
||||||
`/api/v1/notifications/${id}/dismiss`,
|
`/api/v1/notifications/${id}/dismiss`,
|
||||||
undefined,
|
undefined,
|
||||||
extra,
|
extra,
|
||||||
|
|
@ -439,7 +432,7 @@ export class Client extends BaseClient {
|
||||||
* POST /api/v1/notifications/clear
|
* POST /api/v1/notifications/clear
|
||||||
*/
|
*/
|
||||||
public dismissNotifications(extra?: RequestInit): Promise<Output<void>> {
|
public dismissNotifications(extra?: RequestInit): Promise<Output<void>> {
|
||||||
return this.post<void>("/api/v1/notifications/clear", undefined, extra);
|
return this.post("/api/v1/notifications/clear", undefined, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -600,6 +593,22 @@ export class Client extends BaseClient {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/v1/challenges
|
||||||
|
*
|
||||||
|
* Generates a new Captcha to solve.
|
||||||
|
* @returns A challenge.
|
||||||
|
*/
|
||||||
|
public getChallenge(
|
||||||
|
extra?: RequestInit,
|
||||||
|
): Promise<Output<z.infer<typeof Challenge>>> {
|
||||||
|
return this.post<z.infer<typeof Challenge>>(
|
||||||
|
"/api/v1/challenges",
|
||||||
|
undefined,
|
||||||
|
extra,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/v1/accounts/:id
|
* GET /api/v1/accounts/:id
|
||||||
*
|
*
|
||||||
|
|
@ -1047,6 +1056,28 @@ export class Client extends BaseClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/v1/accounts/familiar_followers
|
||||||
|
*
|
||||||
|
* @param ids Array of account IDs.
|
||||||
|
* @return Array of familiar followers.
|
||||||
|
*/
|
||||||
|
public getFamiliarFollowers(
|
||||||
|
ids: string[],
|
||||||
|
): Promise<Output<z.infer<typeof FamiliarFollowers>[]>> {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
|
if (ids) {
|
||||||
|
for (const id of ids) {
|
||||||
|
params.append("id[]", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.get<z.infer<typeof FamiliarFollowers>[]>(
|
||||||
|
`/api/v1/accounts/familiar_followers?${params}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/v1/favourites
|
* GET /api/v1/favourites
|
||||||
*
|
*
|
||||||
|
|
@ -2354,7 +2385,7 @@ export class Client extends BaseClient {
|
||||||
role_id: string,
|
role_id: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.delete<void>(`/api/v1/roles/${role_id}`, undefined, extra);
|
return this.delete(`/api/v1/roles/${role_id}`, undefined, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -2400,7 +2431,7 @@ export class Client extends BaseClient {
|
||||||
token: string,
|
token: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.post<void>(
|
return this.post(
|
||||||
"/oauth/revoke",
|
"/oauth/revoke",
|
||||||
{ client_id, client_secret, token },
|
{ client_id, client_secret, token },
|
||||||
extra,
|
extra,
|
||||||
|
|
@ -2534,7 +2565,7 @@ export class Client extends BaseClient {
|
||||||
*/
|
*/
|
||||||
public searchAccount(
|
public searchAccount(
|
||||||
q: string,
|
q: string,
|
||||||
options: Partial<{
|
options?: Partial<{
|
||||||
following: boolean;
|
following: boolean;
|
||||||
limit: number;
|
limit: number;
|
||||||
max_id: string;
|
max_id: string;
|
||||||
|
|
@ -2547,22 +2578,20 @@ export class Client extends BaseClient {
|
||||||
|
|
||||||
params.set("q", q);
|
params.set("q", q);
|
||||||
|
|
||||||
if (options) {
|
if (options?.following) {
|
||||||
if (options.following) {
|
params.set("following", "true");
|
||||||
params.set("following", "true");
|
}
|
||||||
}
|
if (options?.limit) {
|
||||||
if (options.limit) {
|
params.set("limit", options.limit.toString());
|
||||||
params.set("limit", options.limit.toString());
|
}
|
||||||
}
|
if (options?.max_id) {
|
||||||
if (options.max_id) {
|
params.set("max_id", options.max_id);
|
||||||
params.set("max_id", options.max_id);
|
}
|
||||||
}
|
if (options?.resolve) {
|
||||||
if (options.resolve) {
|
params.set("resolve", "true");
|
||||||
params.set("resolve", "true");
|
}
|
||||||
}
|
if (options?.since_id) {
|
||||||
if (options.since_id) {
|
params.set("since_id", options.since_id);
|
||||||
params.set("since_id", options.since_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.get<z.infer<typeof Account>[]>(
|
return this.get<z.infer<typeof Account>[]>(
|
||||||
|
|
@ -2639,7 +2668,7 @@ export class Client extends BaseClient {
|
||||||
role_id: string,
|
role_id: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.delete<void>(
|
return this.delete(
|
||||||
`/api/v1/accounts/${account_id}/roles/${role_id}`,
|
`/api/v1/accounts/${account_id}/roles/${role_id}`,
|
||||||
undefined,
|
undefined,
|
||||||
extra,
|
extra,
|
||||||
|
|
@ -2672,7 +2701,7 @@ export class Client extends BaseClient {
|
||||||
domain: string,
|
domain: string,
|
||||||
extra?: RequestInit,
|
extra?: RequestInit,
|
||||||
): Promise<Output<void>> {
|
): Promise<Output<void>> {
|
||||||
return this.delete<void>("/api/v1/domain_blocks", { domain }, extra);
|
return this.delete("/api/v1/domain_blocks", { domain }, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { generateChallenge } from "@/challenges";
|
import { generateChallenge } from "@/challenges";
|
||||||
import { randomString } from "@/math";
|
import { randomString } from "@/math";
|
||||||
|
import { Client as VersiaClient } from "@versia/client-ng";
|
||||||
import { Note, Token, User, db } from "@versia/kit/db";
|
import { Note, Token, User, db } from "@versia/kit/db";
|
||||||
import { Notes, Users } from "@versia/kit/tables";
|
import { Notes, Users } from "@versia/kit/tables";
|
||||||
import { solveChallenge } from "altcha-lib";
|
import { solveChallenge } from "altcha-lib";
|
||||||
|
|
@ -26,6 +27,52 @@ export function fakeRequest(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a client instance monkeypatched to use the test server
|
||||||
|
* instead of going through HTTP, and also doesn't throw on errors
|
||||||
|
* @param user User to automatically generate a token for
|
||||||
|
* @returns Client instance
|
||||||
|
*/
|
||||||
|
export const generateClient = async (
|
||||||
|
user?: User,
|
||||||
|
): Promise<
|
||||||
|
VersiaClient & {
|
||||||
|
[Symbol.asyncDispose](): Promise<void>;
|
||||||
|
}
|
||||||
|
> => {
|
||||||
|
const token = user
|
||||||
|
? await Token.insert({
|
||||||
|
accessToken: randomString(32, "hex"),
|
||||||
|
tokenType: "bearer",
|
||||||
|
userId: user.id,
|
||||||
|
applicationId: null,
|
||||||
|
code: randomString(32, "hex"),
|
||||||
|
scope: "read write follow push",
|
||||||
|
})
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const client = new VersiaClient(
|
||||||
|
new URL(config.http.base_url),
|
||||||
|
token?.data.accessToken,
|
||||||
|
);
|
||||||
|
|
||||||
|
// biome-ignore lint/complexity/useLiteralKeys: Overriding private properties
|
||||||
|
client["fetch"] = (
|
||||||
|
input: RequestInfo | string | URL | Request,
|
||||||
|
init?: RequestInit,
|
||||||
|
): Promise<Response> => {
|
||||||
|
return Promise.resolve(app.fetch(new Request(input, init)));
|
||||||
|
};
|
||||||
|
|
||||||
|
// @ts-expect-error This is REAL monkeypatching done by REAL programmers, BITCH!
|
||||||
|
client[Symbol.asyncDispose] = async (): Promise<void> => {
|
||||||
|
await token?.delete();
|
||||||
|
};
|
||||||
|
|
||||||
|
return client as VersiaClient & {
|
||||||
|
[Symbol.asyncDispose](): Promise<void>;
|
||||||
|
};
|
||||||
|
};
|
||||||
export const deleteOldTestUsers = async (): Promise<void> => {
|
export const deleteOldTestUsers = async (): Promise<void> => {
|
||||||
// Deletes all users that match the test username (test-<32 random characters>)
|
// Deletes all users that match the test username (test-<32 random characters>)
|
||||||
await db.delete(Users).where(like(Users.username, "test-%"));
|
await db.delete(Users).where(like(Users.username, "test-%"));
|
||||||
|
|
|
||||||
|
|
@ -40,5 +40,6 @@ export const applyToHono = (app: OpenAPIHono<HonoEnv>): void => {
|
||||||
});
|
});
|
||||||
|
|
||||||
serverAdapter.setBasePath("/admin/queues");
|
serverAdapter.setBasePath("/admin/queues");
|
||||||
|
// @ts-ignore Causes infinite instantiation for some reason
|
||||||
app.route("/admin/queues", serverAdapter.registerPlugin());
|
app.route("/admin/queues", serverAdapter.registerPlugin());
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue