fix(#1): Address code review findings

- Convert ApiResponse to discriminated union for type-safe error handling
- Add HealthStatus type with HealthState literal union
- Make BaseEntity fields readonly for immutability
- Add GlobalExceptionFilter with structured logging
- Add port validation with clear error messages in main.ts
- Improve parseDate to log warnings for invalid dates
- Add comprehensive Button tests (variants, onClick, disabled)
- Add slugify edge case tests (empty, special chars, numbers)
- Create ESLint configs for all packages
- Remove compiled JS files from src directories
- Convert .prettierrc.js to .prettierrc.json

Refs #1

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-01-28 15:07:04 -06:00
parent f277afde36
commit 355cf2124b
33 changed files with 411 additions and 191 deletions

View File

@@ -1,5 +1,5 @@
import { describe, expect, it, afterEach } from "vitest";
import { render, screen, cleanup } from "@testing-library/react";
import { describe, expect, it, afterEach, vi } from "vitest";
import { render, screen, cleanup, fireEvent } from "@testing-library/react";
import { Button } from "./Button.js";
afterEach(() => {
@@ -12,20 +12,75 @@ describe("Button", () => {
expect(screen.getByRole("button")).toHaveTextContent("Click me");
});
it("should apply variant styles", () => {
render(<Button variant="danger">Delete</Button>);
const button = screen.getByRole("button");
expect(button.className).toContain("bg-red-600");
describe("variants", () => {
it("should apply primary variant styles by default", () => {
render(<Button>Primary</Button>);
const button = screen.getByRole("button");
expect(button.className).toContain("bg-blue-600");
});
it("should apply secondary variant styles", () => {
render(<Button variant="secondary">Secondary</Button>);
const button = screen.getByRole("button");
expect(button.className).toContain("bg-gray-200");
});
it("should apply danger variant styles", () => {
render(<Button variant="danger">Delete</Button>);
const button = screen.getByRole("button");
expect(button.className).toContain("bg-red-600");
});
});
it("should apply size styles", () => {
render(<Button size="lg">Large Button</Button>);
const button = screen.getByRole("button");
expect(button.className).toContain("px-6");
describe("sizes", () => {
it("should apply medium size by default", () => {
render(<Button>Medium</Button>);
const button = screen.getByRole("button");
expect(button.className).toContain("px-4");
});
it("should apply small size styles", () => {
render(<Button size="sm">Small</Button>);
const button = screen.getByRole("button");
expect(button.className).toContain("px-3");
});
it("should apply large size styles", () => {
render(<Button size="lg">Large Button</Button>);
const button = screen.getByRole("button");
expect(button.className).toContain("px-6");
});
});
describe("onClick", () => {
it("should call onClick handler when clicked", () => {
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click me</Button>);
fireEvent.click(screen.getByRole("button"));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it("should not call onClick when disabled", () => {
const handleClick = vi.fn();
render(
<Button onClick={handleClick} disabled>
Disabled
</Button>
);
fireEvent.click(screen.getByRole("button"));
expect(handleClick).not.toHaveBeenCalled();
});
});
it("should pass through additional props", () => {
render(<Button disabled>Disabled</Button>);
expect(screen.getByRole("button")).toBeDisabled();
});
it("should merge custom className with default styles", () => {
render(<Button className="custom-class">Custom</Button>);
const button = screen.getByRole("button");
expect(button.className).toContain("custom-class");
expect(button.className).toContain("bg-blue-600");
});
});