fix(api): 🐛 Fix bugs where favourite/unfavourite could return negative values (+ add tests)

This commit is contained in:
Jesse Wierzbinski 2024-06-03 21:12:55 -10:00
parent d2767b0862
commit 1d55570abd
No known key found for this signature in database
5 changed files with 161 additions and 18 deletions

View file

@ -0,0 +1,55 @@
import { afterAll, describe, expect, test } from "bun:test";
import { config } from "config-manager";
import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils";
import type { Status as APIStatus } from "~/types/mastodon/status";
import { meta } from "./favourite";
const { users, tokens, deleteUsers } = await getTestUsers(5);
const timeline = (await getTestStatuses(2, users[0])).toReversed();
afterAll(async () => {
await deleteUsers();
});
// /api/v1/statuses/:id/favourite
describe(meta.route, () => {
test("should return 401 if not authenticated", async () => {
const response = await sendTestRequest(
new Request(
new URL(
meta.route.replace(":id", timeline[0].id),
config.http.base_url,
),
{
method: "POST",
},
),
);
expect(response.status).toBe(401);
});
test("should favourite post", async () => {
const response = await sendTestRequest(
new Request(
new URL(
meta.route.replace(":id", timeline[0].id),
config.http.base_url,
),
{
method: "POST",
headers: {
Authorization: `Bearer ${tokens[1].accessToken}`,
},
},
),
);
expect(response.status).toBe(200);
const json = (await response.json()) as APIStatus;
expect(json.favourited).toBe(true);
expect(json.favourites_count).toBe(1);
});
});

View file

@ -6,7 +6,6 @@ import { z } from "zod";
import { createLike } from "~/database/entities/Like";
import { db } from "~/drizzle/db";
import { Note } from "~/packages/database-interface/note";
import type { Status as APIStatus } from "~/types/mastodon/status";
export const meta = applyConfig({
allowedMethods: ["POST"],
@ -56,10 +55,10 @@ export default (app: Hono) =>
await createLike(user, note);
}
return jsonResponse({
...(await note.toAPI(user)),
favourited: true,
favourites_count: note.getStatus().likeCount + 1,
} as APIStatus);
const newNote = await Note.fromId(id, user.id);
if (!newNote) return errorResponse("Record not found", 404);
return jsonResponse(await newNote.toAPI(user));
},
);

View file

@ -0,0 +1,91 @@
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
import { config } from "config-manager";
import { getTestStatuses, getTestUsers, sendTestRequest } from "~/tests/utils";
import type { Status as APIStatus } from "~/types/mastodon/status";
import { meta } from "./unfavourite";
const { users, tokens, deleteUsers } = await getTestUsers(5);
const timeline = (await getTestStatuses(2, users[0])).toReversed();
afterAll(async () => {
await deleteUsers();
});
// /api/v1/statuses/:id/unfavourite
describe(meta.route, () => {
test("should return 401 if not authenticated", async () => {
const response = await sendTestRequest(
new Request(
new URL(
meta.route.replace(":id", timeline[0].id),
config.http.base_url,
),
{
method: "POST",
},
),
);
expect(response.status).toBe(401);
});
test("should be able to unfavourite post that is not favourited", async () => {
const response = await sendTestRequest(
new Request(
new URL(
meta.route.replace(":id", timeline[0].id),
config.http.base_url,
),
{
method: "POST",
headers: {
Authorization: `Bearer ${tokens[1].accessToken}`,
},
},
),
);
expect(response.status).toBe(200);
});
test("should unfavourite post", async () => {
beforeAll(async () => {
await sendTestRequest(
new Request(
new URL(
`/api/v1/statuses/${timeline[1].id}/favourite`,
config.http.base_url,
),
{
method: "POST",
headers: {
Authorization: `Bearer ${tokens[1].accessToken}`,
},
},
),
);
});
const response = await sendTestRequest(
new Request(
new URL(
meta.route.replace(":id", timeline[1].id),
config.http.base_url,
),
{
method: "POST",
headers: {
Authorization: `Bearer ${tokens[1].accessToken}`,
},
},
),
);
expect(response.status).toBe(200);
const json = (await response.json()) as APIStatus;
expect(json.favourited).toBe(false);
expect(json.favourites_count).toBe(0);
});
});

View file

@ -5,7 +5,6 @@ import type { Hono } from "hono";
import { z } from "zod";
import { deleteLike } from "~/database/entities/Like";
import { Note } from "~/packages/database-interface/note";
import type { Status as APIStatus } from "~/types/mastodon/status";
export const meta = applyConfig({
allowedMethods: ["POST"],
@ -44,10 +43,10 @@ export default (app: Hono) =>
await deleteLike(user, note);
return jsonResponse({
...(await note.toAPI(user)),
favourited: false,
favourites_count: note.getStatus().likeCount - 1,
} as APIStatus);
const newNote = await Note.fromId(id, user.id);
if (!newNote) return errorResponse("Record not found", 404);
return jsonResponse(await newNote.toAPI(user));
},
);

View file

@ -6,7 +6,6 @@ import type { Hono } from "hono";
import { z } from "zod";
import { Notes } from "~/drizzle/schema";
import { Note } from "~/packages/database-interface/note";
import type { Status as APIStatus } from "~/types/mastodon/status";
export const meta = applyConfig({
allowedMethods: ["POST"],
@ -59,10 +58,10 @@ export default (app: Hono) =>
await existingReblog.delete();
return jsonResponse({
...(await foundStatus.toAPI(user)),
reblogged: false,
reblogs_count: foundStatus.getStatus().reblogCount - 1,
} as APIStatus);
const newNote = await Note.fromId(id, user.id);
if (!newNote) return errorResponse("Record not found", 404);
return jsonResponse(await newNote.toAPI(user));
},
);