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:
Jose Selesan
2026-06-04 10:48:07 -03:00
parent 53a797703e
commit 5b6ccf0fa6
81 changed files with 1565 additions and 794 deletions

View File

@@ -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);