test: add action-helper, send-currency, permission-ranks, catalog-tree, and audit test suites (77 files, 405 tests)
This commit is contained in:
1 parent
2e9db75eca
commit
ac3c42f308
4 files changed
+394
-71
No files matched your search
@@ -1,42 +1,54 @@
|
|||||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
import { describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const mockError = vi.hoisted(() => vi.fn());
|
const loggerError = vi.hoisted(() => vi.fn());
|
||||||
|
|
||||||
vi.mock("@/lib/logger", () => ({
|
vi.mock("@/lib/logger", () => ({
|
||||||
logger: { error: mockError },
|
logger: { error: loggerError },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
import { wrapAction, actionError } from "./action-helper";
|
import { wrapAction, actionError } from "./action-helper";
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
mockError.mockReset();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("wrapAction", () => {
|
describe("wrapAction", () => {
|
||||||
it("returns success with data when fn resolves", async () => {
|
it("returns success result on happy path", async () => {
|
||||||
const result = await wrapAction(async () => "hello", "testAction");
|
const fn = vi.fn().mockResolvedValue({ id: 1 });
|
||||||
expect(result).toEqual({ success: true, data: "hello" });
|
const result = await wrapAction(fn, "test_action");
|
||||||
|
expect(result.success).toBe(true);
|
||||||
|
expect(result.data).toEqual({ id: 1 });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns failure and logs when fn throws", async () => {
|
it("returns error result on thrown exception", async () => {
|
||||||
const result = await wrapAction(async () => {
|
const fn = vi.fn().mockRejectedValue(new Error("DB error"));
|
||||||
throw new Error("boom");
|
const result = await wrapAction(fn, "failing_action");
|
||||||
}, "testAction");
|
expect(result.success).toBe(false);
|
||||||
expect(result).toEqual({ success: false, error: "boom" });
|
expect(result.error).toBe("DB error");
|
||||||
expect(mockError).toHaveBeenCalledWith("Action failed: testAction", {
|
expect(loggerError).toHaveBeenCalled();
|
||||||
action: "testAction",
|
|
||||||
error: "boom",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("catches non-Error values gracefully", async () => {
|
||||||
|
const fn = vi.fn().mockRejectedValue("string error");
|
||||||
|
const result = await wrapAction(fn, "bad_action");
|
||||||
|
expect(result.success).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns data returned by fn", async () => {
|
||||||
|
const fn = vi.fn().mockResolvedValue(undefined);
|
||||||
|
const result = await wrapAction(fn, "void_action");
|
||||||
|
expect(result.success).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("actionError", () => {
|
describe("actionError", () => {
|
||||||
it("returns failure result and logs", () => {
|
it("returns failure result with message", () => {
|
||||||
const result = actionError("myAction", "something went wrong");
|
const result = actionError("some_action", "something went wrong");
|
||||||
expect(result).toEqual({ success: false, error: "something went wrong" });
|
expect(result.success).toBe(false);
|
||||||
expect(mockError).toHaveBeenCalledWith("Action failed: myAction", {
|
expect(result.error).toBe("something went wrong");
|
||||||
action: "myAction",
|
|
||||||
error: "something went wrong",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("logs the error", () => {
|
||||||
|
actionError("audit_action", "audit failed");
|
||||||
|
expect(loggerError).toHaveBeenCalledWith(
|
||||||
|
"Action failed: audit_action",
|
||||||
|
expect.objectContaining({ action: "audit_action", error: "audit failed" }),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,78 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getRankPermissionColumn,
|
||||||
|
toPermissionValue,
|
||||||
|
splitRankUpdateFields,
|
||||||
|
RANK_GENERAL_FIELDS,
|
||||||
|
} from "./permission-ranks";
|
||||||
|
|
||||||
|
describe("getRankPermissionColumn", () => {
|
||||||
|
it("returns rank_N for valid rank", () => {
|
||||||
|
expect(getRankPermissionColumn(1)).toBe("rank_1");
|
||||||
|
expect(getRankPermissionColumn(255)).toBe("rank_255");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws for invalid rank", () => {
|
||||||
|
expect(() => getRankPermissionColumn(0)).toThrow("Invalid rank id");
|
||||||
|
expect(() => getRankPermissionColumn(256)).toThrow("Invalid rank id");
|
||||||
|
expect(() => getRankPermissionColumn(1.5)).toThrow("Invalid rank id");
|
||||||
|
expect(() => getRankPermissionColumn(-1)).toThrow("Invalid rank id");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("toPermissionValue", () => {
|
||||||
|
it("returns numeric value for valid input", () => {
|
||||||
|
expect(toPermissionValue(5)).toBe(5);
|
||||||
|
expect(toPermissionValue("10")).toBe(10);
|
||||||
|
expect(toPermissionValue("255")).toBe(255);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("clamps to 0-255 range", () => {
|
||||||
|
expect(toPermissionValue(-1)).toBe(0);
|
||||||
|
expect(toPermissionValue(256)).toBe(255);
|
||||||
|
expect(toPermissionValue(999)).toBe(255);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns 0 for non-numeric strings", () => {
|
||||||
|
expect(toPermissionValue("abc")).toBe(0);
|
||||||
|
expect(toPermissionValue(NaN)).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("splitRankUpdateFields", () => {
|
||||||
|
it("splits rank general fields from permission fields", () => {
|
||||||
|
const { rankFields, permissionFields } = splitRankUpdateFields({
|
||||||
|
rank_name: "Moderator",
|
||||||
|
level: 5,
|
||||||
|
cmd_ban: "1",
|
||||||
|
cmd_kick: "1",
|
||||||
|
});
|
||||||
|
expect(rankFields).toEqual({ rank_name: "Moderator", level: 5 });
|
||||||
|
expect(permissionFields).toEqual({ cmd_ban: 1, cmd_kick: 1 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("skips id field and invalid keys", () => {
|
||||||
|
const { rankFields, permissionFields } = splitRankUpdateFields({
|
||||||
|
id: 5,
|
||||||
|
"": "test",
|
||||||
|
});
|
||||||
|
expect(rankFields).toEqual({});
|
||||||
|
expect(permissionFields).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns empty objects for empty input", () => {
|
||||||
|
const { rankFields, permissionFields } = splitRankUpdateFields({});
|
||||||
|
expect(rankFields).toEqual({});
|
||||||
|
expect(permissionFields).toEqual({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("RANK_GENERAL_FIELDS", () => {
|
||||||
|
it("contains expected fields", () => {
|
||||||
|
expect(RANK_GENERAL_FIELDS.has("rank_name")).toBe(true);
|
||||||
|
expect(RANK_GENERAL_FIELDS.has("badge")).toBe(true);
|
||||||
|
expect(RANK_GENERAL_FIELDS.has("level")).toBe(true);
|
||||||
|
expect(RANK_GENERAL_FIELDS.has("nonexistent")).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user