chore: add Biome for lint and fix all lint errors
- Install @biomejs/biome as devDependency at root - Configure biome.json with 2-space indent, double quotes, Tailwind CSS support - Add lint/lint:fix/format/format:fix scripts to root and app package.json - Fix noNonNullAssertion: env vars extracted to variables with suppression, <div role=button> replaced with <button> - Fix noUnusedVariables: remove unused destructured vars - Fix useIterableCallbackReturn: arrow functions with block body - Fix noExplicitAny: recharts Tooltip formatters - Fix noLabelWithoutControl: add htmlFor+id or use <span> for non-input labels - Fix noStaticElementInteractions/useKeyWithClickEvents: role+keyboard events for overlays - Fix noArrayIndexKey: use error string as key - Fix CSS parse: enable tailwindDirectives parser - Normalize formatting across 80 files with biome check --write
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { describe, test, expect, mock, beforeEach } from "bun:test";
|
||||
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
||||
import { PaymentStatus } from "../src/generated/prisma/client";
|
||||
|
||||
const mockPrisma = {
|
||||
@@ -23,7 +23,9 @@ mock.module("../src/lib/prisma", () => ({
|
||||
|
||||
beforeEach(() => {
|
||||
for (const model of Object.values(mockPrisma)) {
|
||||
for (const fn of Object.values(model as Record<string, ReturnType<typeof mock>>)) {
|
||||
for (const fn of Object.values(
|
||||
model as Record<string, ReturnType<typeof mock>>,
|
||||
)) {
|
||||
fn.mockClear();
|
||||
}
|
||||
}
|
||||
@@ -32,7 +34,6 @@ beforeEach(() => {
|
||||
|
||||
const {
|
||||
createPeriodicExpenseSchema,
|
||||
updatePeriodicExpenseSchema,
|
||||
createNonPeriodicExpenseSchema,
|
||||
payExpenseSchema,
|
||||
buildDueDate,
|
||||
@@ -54,7 +55,7 @@ describe("schemas", () => {
|
||||
const result = createPeriodicExpenseSchema.parse({
|
||||
description: "Gimnasio",
|
||||
defaultDueDay: 10,
|
||||
defaultAmount: 1500.50,
|
||||
defaultAmount: 1500.5,
|
||||
periods: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
||||
});
|
||||
expect(result.description).toBe("Gimnasio");
|
||||
@@ -67,7 +68,7 @@ describe("schemas", () => {
|
||||
defaultDueDay: 10,
|
||||
defaultAmount: 100,
|
||||
periods: [1],
|
||||
})
|
||||
}),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
@@ -78,7 +79,7 @@ describe("schemas", () => {
|
||||
defaultDueDay: 10,
|
||||
defaultAmount: 100,
|
||||
periods: [1],
|
||||
})
|
||||
}),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
@@ -89,7 +90,7 @@ describe("schemas", () => {
|
||||
defaultDueDay: 0,
|
||||
defaultAmount: 100,
|
||||
periods: [1],
|
||||
})
|
||||
}),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
@@ -100,7 +101,7 @@ describe("schemas", () => {
|
||||
defaultDueDay: 32,
|
||||
defaultAmount: 100,
|
||||
periods: [1],
|
||||
})
|
||||
}),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
@@ -111,7 +112,7 @@ describe("schemas", () => {
|
||||
defaultDueDay: 15,
|
||||
defaultAmount: 0,
|
||||
periods: [1],
|
||||
})
|
||||
}),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
@@ -122,7 +123,7 @@ describe("schemas", () => {
|
||||
defaultDueDay: 15,
|
||||
defaultAmount: 100,
|
||||
periods: [],
|
||||
})
|
||||
}),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
@@ -133,7 +134,7 @@ describe("schemas", () => {
|
||||
defaultDueDay: 15,
|
||||
defaultAmount: 100,
|
||||
periods: [0, 13],
|
||||
})
|
||||
}),
|
||||
).toThrow();
|
||||
});
|
||||
});
|
||||
@@ -154,7 +155,7 @@ describe("schemas", () => {
|
||||
description: "Ropa",
|
||||
amount: -100,
|
||||
dueDate: "2026-06-15T00:00:00.000Z",
|
||||
})
|
||||
}),
|
||||
).toThrow();
|
||||
});
|
||||
});
|
||||
@@ -175,9 +176,7 @@ describe("schemas", () => {
|
||||
});
|
||||
|
||||
test("rejects zero amountPayed", () => {
|
||||
expect(() =>
|
||||
payExpenseSchema.parse({ amountPayed: 0 })
|
||||
).toThrow();
|
||||
expect(() => payExpenseSchema.parse({ amountPayed: 0 })).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -244,7 +243,12 @@ describe("createPeriodicExpense", () => {
|
||||
defaultAmount: 1500,
|
||||
periods: [6],
|
||||
};
|
||||
const created = { id: 1, ...input, isDeleted: false, createdAt: new Date() };
|
||||
const created = {
|
||||
id: 1,
|
||||
...input,
|
||||
isDeleted: false,
|
||||
createdAt: new Date(),
|
||||
};
|
||||
mockPrisma.periodicExpense.create.mockResolvedValueOnce(created);
|
||||
|
||||
const result = await createPeriodicExpense(input);
|
||||
@@ -339,7 +343,11 @@ describe("listExpenses", () => {
|
||||
|
||||
test("combines status, periodicExpenseId, and search filters", async () => {
|
||||
mockPrisma.expense.findMany.mockResolvedValueOnce([]);
|
||||
await listExpenses({ status: "PENDING", periodicExpenseId: 1, search: "Agua" });
|
||||
await listExpenses({
|
||||
status: "PENDING",
|
||||
periodicExpenseId: 1,
|
||||
search: "Agua",
|
||||
});
|
||||
expect(mockPrisma.expense.findMany).toHaveBeenCalledWith({
|
||||
where: {
|
||||
status: "PENDING",
|
||||
@@ -406,13 +414,15 @@ describe("payExpense", () => {
|
||||
});
|
||||
|
||||
test("defaults paymentDate to now when not provided", async () => {
|
||||
mockPrisma.expense.update.mockImplementationOnce(async ({ where, data }) => ({
|
||||
id: where.id,
|
||||
...data,
|
||||
status: PaymentStatus.PAYED,
|
||||
amountPayed: data.amountPayed,
|
||||
paymentDate: data.paymentDate,
|
||||
}));
|
||||
mockPrisma.expense.update.mockImplementationOnce(
|
||||
async ({ where, data }) => ({
|
||||
id: where.id,
|
||||
...data,
|
||||
status: PaymentStatus.PAYED,
|
||||
amountPayed: data.amountPayed,
|
||||
paymentDate: data.paymentDate,
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await payExpense(1, { amountPayed: 1500 });
|
||||
expect(result.status).toBe(PaymentStatus.PAYED);
|
||||
@@ -424,7 +434,13 @@ describe("generateExpensesForCurrentMonth", () => {
|
||||
test("skips existing expenses to avoid duplicates", async () => {
|
||||
const { month } = getCurrentYearMonthUTC();
|
||||
mockPrisma.periodicExpense.findMany.mockResolvedValueOnce([
|
||||
{ id: 1, description: "Gas", defaultDueDay: 15, defaultAmount: 2000, periods: [month] },
|
||||
{
|
||||
id: 1,
|
||||
description: "Gas",
|
||||
defaultDueDay: 15,
|
||||
defaultAmount: 2000,
|
||||
periods: [month],
|
||||
},
|
||||
]);
|
||||
mockPrisma.expense.findFirst.mockResolvedValueOnce({ id: 99 });
|
||||
|
||||
@@ -471,11 +487,23 @@ describe("generateExpensesForCurrentMonth", () => {
|
||||
|
||||
describe("generateMonthlyExpense", () => {
|
||||
test("creates expense for given periodic expense", async () => {
|
||||
const periodic = { id: 1, description: "Gas", defaultDueDay: 15, defaultAmount: 2000, periods: [6] };
|
||||
mockPrisma.periodicExpense.findUniqueOrThrow.mockResolvedValueOnce(periodic);
|
||||
const periodic = {
|
||||
id: 1,
|
||||
description: "Gas",
|
||||
defaultDueDay: 15,
|
||||
defaultAmount: 2000,
|
||||
periods: [6],
|
||||
};
|
||||
mockPrisma.periodicExpense.findUniqueOrThrow.mockResolvedValueOnce(
|
||||
periodic,
|
||||
);
|
||||
mockPrisma.expense.findFirst.mockResolvedValueOnce(null);
|
||||
mockPrisma.expense.create.mockResolvedValueOnce({
|
||||
id: 1, description: "Gas", periodicExpenseId: 1, amount: 2000, status: "PENDING",
|
||||
id: 1,
|
||||
description: "Gas",
|
||||
periodicExpenseId: 1,
|
||||
amount: 2000,
|
||||
status: "PENDING",
|
||||
});
|
||||
|
||||
const result = await generateMonthlyExpense(1);
|
||||
@@ -485,7 +513,11 @@ describe("generateMonthlyExpense", () => {
|
||||
test("returns existing expense instead of duplicating", async () => {
|
||||
const existing = { id: 99, description: "Gas", periodicExpenseId: 1 };
|
||||
mockPrisma.periodicExpense.findUniqueOrThrow.mockResolvedValueOnce({
|
||||
id: 1, description: "Gas", defaultDueDay: 15, defaultAmount: 2000, periods: [6],
|
||||
id: 1,
|
||||
description: "Gas",
|
||||
defaultDueDay: 15,
|
||||
defaultAmount: 2000,
|
||||
periods: [6],
|
||||
});
|
||||
mockPrisma.expense.findFirst.mockResolvedValueOnce(existing);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user