test: add boost cleanup service tests and expand booster role test coverage

This commit is contained in:
MythEclipse
2026-06-06 03:11:59 +07:00
parent a796034241
commit 0f6d9110a3
3 changed files with 234 additions and 2 deletions
+56 -2
View File
@@ -2,7 +2,6 @@ import { describe, expect, test } from "bun:test";
import { BoosterRoleService } from "./boosterRoleService";
import type { BoosterRoleRecord } from "./drizzleBoosterRoleStore";
import type { RoleRepository } from "./discordRoleRepository";
import { ValidationError, NotFoundError, PermissionError } from "../domain/errors";
class MemoryRoleStore {
private records = new Map<string, BoosterRoleRecord>();
@@ -48,7 +47,7 @@ class FakeRoleRepository implements RoleRepository {
async createRole(input: { name: string; color: string | null; colors?: { primaryColor: string; secondaryColor?: string; tertiaryColor?: string } | null; permissions: string[]; position: number }) {
const id = `created-${this.roles.size + 1}`;
this.roles.set(id, { id, ...input });
this.roles.set(id, { id, name: input.name, color: input.color, colors: input.colors, permissions: input.permissions, position: input.position });
return { id };
}
@@ -58,6 +57,10 @@ class FakeRoleRepository implements RoleRepository {
this.roles.set(roleId, { ...role, ...input });
}
getRole(roleId: string) {
return this.roles.get(roleId) ?? null;
}
async assignRole(userId: string, roleId: string) {
this.assignedRoles.push({ userId, roleId });
}
@@ -160,4 +163,55 @@ describe("BoosterRoleService", () => {
expect(roles.deletedRoleIds).toEqual(["created-1"]);
expect(roles.roles.has("created-1")).toBe(false);
});
test("recolors only the stored role owned by the user", async () => {
const store = new MemoryRoleStore();
const roles = new FakeRoleRepository([]);
const service = new BoosterRoleService(store, roles, { anchorPosition: 10 });
const claimed = await service.claimRole({ guildId: "guild", userId: "user", name: "First Role", color: null, isBoosting: true });
await service.recolorRole({ guildId: "guild", userId: "user", color: "#FF0000" });
const updated = roles.getRole(claimed.roleId);
expect(updated).not.toBeNull();
expect(updated!.colors).toEqual({ primaryColor: "#FF0000" });
// Other user cannot recolor
await expect(service.recolorRole({ guildId: "guild", userId: "attacker", color: "#00FF00" })).rejects.toThrow("No booster role found");
});
test("recolors role with gradient colors (primary + secondary)", async () => {
const store = new MemoryRoleStore();
const roles = new FakeRoleRepository([]);
const service = new BoosterRoleService(store, roles, { anchorPosition: 10 });
const claimed = await service.claimRole({ guildId: "guild", userId: "user", name: "First Role", color: null, isBoosting: true });
await service.recolorRole({ guildId: "guild", userId: "user", color: "#FF0000", color2: "#0000FF" });
const updated = roles.getRole(claimed.roleId);
expect(updated).not.toBeNull();
expect(updated!.colors).toEqual({ primaryColor: "#FF0000", secondaryColor: "#0000FF" });
});
test("deletes the stored role owned by the user", async () => {
const store = new MemoryRoleStore();
const roles = new FakeRoleRepository([]);
const service = new BoosterRoleService(store, roles, { anchorPosition: 10 });
const claimed = await service.claimRole({ guildId: "guild", userId: "user", name: "First Role", color: null, isBoosting: true });
await service.deleteRole({ guildId: "guild", userId: "user" });
expect(roles.deletedRoleIds).toEqual([claimed.roleId]);
expect(roles.roles.has(claimed.roleId)).toBe(false);
expect(await store.findByUser("guild", "user")).toBeNull();
});
test("rejects delete by non-owner user", async () => {
const store = new MemoryRoleStore();
const roles = new FakeRoleRepository([]);
const service = new BoosterRoleService(store, roles, { anchorPosition: 10 });
await service.claimRole({ guildId: "guild", userId: "user", name: "First Role", color: null, isBoosting: true });
await expect(service.deleteRole({ guildId: "guild", userId: "attacker" })).rejects.toThrow("No booster role found");
});
});