> ## Documentation Index
> Fetch the complete documentation index at: https://mako-docs.devinagiffy.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Guide

> How to write and run tests for Hitler

## Test Framework

Hitler uses [Vitest](https://vitest.dev) for testing. Vitest is fast, compatible with Jest APIs, and works great with TypeScript.

## Running Tests

```bash theme={null}
# Run all tests once
pnpm test

# Watch mode (re-runs on file changes)
pnpm test:watch

# With coverage report
pnpm test:coverage
```

## Test Structure

```
/tests
  setup.ts                    # Global test setup
  /utils
    factories.ts              # Test data factories
    mock-database.ts          # Mock Drizzle ORM
    test-helpers.ts           # Utility functions
  /unit
    pattern-detection.test.ts # Pure function tests
    rules.test.ts             # Business rules tests
    sdk-client.test.ts        # SDK tests
    shared-schemas.test.ts    # Zod schema tests
    eod-parser.test.ts        # EOD emoji/status parsing tests
  /integration
    tasks.service.test.ts     # Service tests

/packages/*/src/**/*.test.ts  # Package-specific tests
```

## Writing Tests

### Unit Tests

For pure functions without side effects:

```typescript theme={null}
import { describe, it, expect } from "vitest";
import { calculateScore } from "@hitler/rules";

describe("calculateScore", () => {
  it("should return 100 for perfect metrics", () => {
    const result = calculateScore({
      tasksCompleted: 10,
      tasksTotal: 10,
      moodAverage: 5,
    });
    expect(result).toBe(100);
  });

  it("should return 0 when all tasks are overdue", () => {
    const result = calculateScore({
      tasksCompleted: 0,
      tasksTotal: 10,
      overdueCount: 10,
    });
    expect(result).toBe(0);
  });
});
```

### Using Test Factories

Create consistent test data with factories:

```typescript theme={null}
import { createTask, createUser, createMood } from "../utils/factories";
import { daysAgo, daysFromNow } from "../utils/test-helpers";

describe("TaskService", () => {
  it("should identify overdue tasks", () => {
    const overdueTask = createTask({
      status: "pending",
      dueDate: daysAgo(3), // Due 3 days ago
    });

    const futureTask = createTask({
      status: "pending",
      dueDate: daysFromNow(5), // Due in 5 days
    });

    expect(isOverdue(overdueTask)).toBe(true);
    expect(isOverdue(futureTask)).toBe(false);
  });
});
```

### Testing with Mocks

For tests that need external dependencies:

```typescript theme={null}
import { describe, it, expect, vi, beforeEach } from "vitest";

// Mock the module
vi.mock("@hitler/observability", () => ({
  logger: {
    info: vi.fn(),
    error: vi.fn(),
  },
}));

describe("NotificationService", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("should log when notification is sent", async () => {
    const { logger } = await import("@hitler/observability");

    await sendNotification({ userId: "123", message: "Hello" });

    expect(logger.info).toHaveBeenCalledWith(
      expect.stringContaining("notification"),
      expect.any(Object)
    );
  });
});
```

### Integration Tests

For testing services with mocked database:

```typescript theme={null}
import { describe, it, expect, beforeEach } from "vitest";
import { createMockDatabase, MockDatabase } from "../utils/mock-database";
import { TasksService } from "@hitler/api/modules/tasks";

describe("TasksService Integration", () => {
  let db: MockDatabase;
  let service: TasksService;

  beforeEach(() => {
    db = createMockDatabase();
    service = new TasksService(db);
  });

  it("should create task draft", async () => {
    const draft = await service.createDraft({
      title: "Test Task",
      userId: "user-1",
      organizationId: "org-1",
      priority: 3,
    });

    expect(draft.id).toBeDefined();
    expect(draft.title).toBe("Test Task");
    expect(draft.status).toBe("pending");
  });

  it("should not confirm another user's draft", async () => {
    const draft = await service.createDraft({
      title: "Test",
      userId: "user-1",
      organizationId: "org-1",
      priority: 3,
    });

    await expect(
      service.confirmDraft(draft.id, "user-2") // Different user
    ).rejects.toThrow("Cannot confirm another user's draft");
  });
});
```

## Test Utilities

### Factories

Located in `tests/utils/factories.ts`:

```typescript theme={null}
// Create a task with optional overrides
createTask({ status: "completed", priority: 5 });

// Create a user with role
createUser({ role: "manager" });

// Create a mood entry
createMood({ value: 4, note: "Good day!" });

// Create an organization
createOrganization({ name: "Acme Corp" });
```

### Helpers

Located in `tests/utils/test-helpers.ts`:

```typescript theme={null}
// Date helpers
daysAgo(5); // Date 5 days in the past
daysFromNow(3); // Date 3 days in the future
hoursAgo(2); // Date 2 hours ago

// ID generators
generateId(); // Random UUID
generateSlug(); // Random slug like "acme-corp-a1b2"
```

## Coverage Targets

| Package          | Target | Why                              |
| ---------------- | ------ | -------------------------------- |
| `@hitler/rules`  | 95%+   | Pure business logic, critical    |
| `@hitler/shared` | 95%+   | Validation schemas, foundational |
| `@hitler/sdk`    | 75%+   | API client, external dependency  |
| `@hitler/api`    | 70%+   | Service logic with mocked DB     |

Check coverage with:

```bash theme={null}
pnpm test:coverage
```

## Best Practices

<AccordionGroup>
  <Accordion title="Keep tests independent">
    Each test should be able to run in isolation. Use `beforeEach` to reset state.

    ```typescript theme={null}
    beforeEach(() => {
      vi.clearAllMocks();
      db = createMockDatabase();
    });
    ```
  </Accordion>

  <Accordion title="Test behavior, not implementation">
    Focus on what the function does, not how it does it.

    ```typescript theme={null}
    // Good - tests behavior
    expect(task.isOverdue()).toBe(true);

    // Bad - tests implementation
    expect(task._checkDueDate()).toHaveBeenCalled();
    ```
  </Accordion>

  <Accordion title="Use descriptive test names">
    Test names should describe the scenario and expected outcome.

    ```typescript theme={null}
    // Good
    it("should mark task as overdue when due date is in the past")

    // Bad
    it("test overdue")
    ```
  </Accordion>

  <Accordion title="Avoid testing external libraries">
    Don't test that Zod validates correctly. Test your schemas work as expected.

    ```typescript theme={null}
    // Good - tests your schema
    expect(() => taskSchema.parse({ title: "" })).toThrow();

    // Bad - tests Zod itself
    expect(z.string().min(1).parse("")).toThrow();
    ```
  </Accordion>
</AccordionGroup>

## Debugging Tests

### Run a specific test file

```bash theme={null}
pnpm test tests/unit/rules.test.ts
```

### Run tests matching a pattern

```bash theme={null}
pnpm test -t "overdue"
```

### Verbose output

```bash theme={null}
pnpm test -- --reporter=verbose
```

### Debug in VS Code

Add this to `.vscode/launch.json`:

```json theme={null}
{
  "type": "node",
  "request": "launch",
  "name": "Debug Tests",
  "program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
  "args": ["run", "--reporter=verbose"],
  "console": "integratedTerminal"
}
```
