> ## Documentation Index
> Fetch the complete documentation index at: https://sonamu.cartanova.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Vitest Debug

> Debugging tests

This covers effective methods for debugging tests written with Vitest.

## Vitest Debugging Methods

Sonamu uses Vitest as its test framework. It provides various debugging methods.

## Using VSCode Debugger

### 1. launch.json Configuration

`.vscode/launch.json`:

```json theme={null}
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Current Test File",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["vitest", "run", "${file}"],
      "cwd": "${workspaceFolder}",
      "console": "integratedTerminal",
      "sourceMaps": true,
      "resolveSourceMapLocations": ["${workspaceFolder}/**", "!**/node_modules/**"]
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Debug All Tests",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["vitest", "run"],
      "cwd": "${workspaceFolder}",
      "console": "integratedTerminal",
      "sourceMaps": true
    }
  ]
}
```

### 2. Running the Debugger

1. **Open test file**
   * Open the `.test.ts` file you want to debug

2. **Set breakpoints**
   * Click to the left of the line number to show a red dot

3. **Start debugger**
   * Press F5 or select "Debug Current Test File" from the "Run and Debug" panel

4. **Debug**
   * When paused at a breakpoint, inspect variables
   * Use F10 (Step Over), F11 (Step Into), etc.

## Console Logging

### Using console.log

The simplest debugging method:

```typescript theme={null}
test("create user", async () => {
  const email = "test@example.com";

  console.log("Test started:", email);

  const user = await UserModel.create({ email });
  console.log("Created user:", user);

  expect(user.email).toBe(email);
});
```

### Structured Logging

```typescript theme={null}
test("logging complex objects", async () => {
  const data = {
    user: { id: 1, email: "test@example.com" },
    items: [1, 2, 3],
  };

  // Pretty print
  console.log(JSON.stringify(data, null, 2));

  // Or
  console.dir(data, { depth: null });
});
```

## Running Specific Tests

### test.only

```typescript theme={null}
// Run only this test
test.only("test to debug", async () => {
  const result = await complexOperation();
  expect(result).toBeDefined();
});

// Other tests are skipped
test("test to skip", async () => {
  // ...
});
```

### describe.only

```typescript theme={null}
// Run only tests in this block
describe.only("User API", () => {
  test("create user", async () => {
    // ...
  });

  test("get user", async () => {
    // ...
  });
});

// Other describe blocks are skipped
describe("Order API", () => {
  test("create order", async () => {
    // ...
  });
});
```

### Running Specific Tests via CLI

```bash theme={null}
# Specific file only
pnpm vitest run src/models/user.model.test.ts

# Specific pattern
pnpm vitest run user

# Specific test name
pnpm vitest run -t "create user"
```

## Watch Mode

### Auto Re-run

```bash theme={null}
# Run in watch mode
pnpm vitest watch

# Or
pnpm test --watch
```

When you modify a file, related tests are automatically re-run.

### Watch Mode Shortcuts

During test execution:

* `a`: Re-run all tests
* `f`: Re-run failed tests only
* `t`: Filter specific tests
* `q`: Quit

## UI Mode (vitest --ui)

### Running

```bash theme={null}
pnpm vitest --ui
```

Opens `http://localhost:51204/__vitest__/` in the browser

**Features:**

* Visualize test hierarchy
* Filter failed tests
* Re-run individual tests
* Check code coverage
* View console output

## Error Debugging

### Detailed Error Messages

```typescript theme={null}
test("improve error message", async () => {
  const userId = 999;

  // Basic error
  expect(await UserModel.findById(userId)).toBeDefined();

  // Detailed error message
  const user = await UserModel.findById(userId);
  expect(user, `User ID ${userId} not found`).toBeDefined();
});
```

### Checking Errors with try-catch

```typescript theme={null}
test("error detail analysis", async () => {
  try {
    await riskyOperation();
    expect.fail("Error should have occurred");
  } catch (error) {
    // Check error details
    console.log("Error type:", error.constructor.name);
    console.log("Error message:", error.message);
    console.log("Stack trace:", error.stack);

    expect(error).toBeInstanceOf(BadRequestException);
  }
});
```

## Debugging Async Code

### Checking async/await

```typescript theme={null}
test("debugging async operations", async () => {
  console.log("1. Started");

  const promise1 = fetchUser(1);
  console.log("2. fetchUser called");

  const promise2 = fetchOrders(1);
  console.log("3. fetchOrders called");

  const [user, orders] = await Promise.all([promise1, promise2]);
  console.log("4. All completed:", { user, orders });

  expect(user).toBeDefined();
});
```

### Increasing Timeout

```typescript theme={null}
test("slow operation", async () => {
  // Increase from default 5 seconds to 30 seconds
  const result = await slowOperation();
  expect(result).toBeDefined();
}, 30000); // 30 second timeout
```

## Debugging Mocks

### Checking Mock Calls

```typescript theme={null}
import { vi } from "vitest";

test("debugging mock calls", async () => {
  const mockFn = vi.fn().mockResolvedValue({ id: 1 });

  await mockFn("test");
  await mockFn("test2");

  // Check mock calls
  console.log("Call count:", mockFn.mock.calls.length);
  console.log("First call:", mockFn.mock.calls[0]);
  console.log("All calls:", mockFn.mock.calls);

  expect(mockFn).toHaveBeenCalledTimes(2);
  expect(mockFn).toHaveBeenCalledWith("test");
});
```

### Checking Mock Reset

```typescript theme={null}
beforeEach(() => {
  // Reset mocks before each test
  vi.clearAllMocks();
});

test("check mock state", () => {
  const mockFn = vi.fn();

  // Before call
  console.log("Before call:", mockFn.mock.calls.length); // 0

  mockFn("test");

  // After call
  console.log("After call:", mockFn.mock.calls.length); // 1
});
```

## Checking Database State

### Query Logging

```typescript theme={null}
test("check DB query", async () => {
  // Enable query logging (during development)
  const result = await UserModel.getPuri("r")
    .table("users")
    .select("*")
    .where({ email: "test@example.com" })
    .debug() // Output query
    .getOne();

  console.log("Result:", result);
});
```

### Checking Data After Test

```typescript theme={null}
test("verify data creation", async () => {
  const email = "test@example.com";

  await UserModel.create({ email });

  // Check directly from DB
  const users = await UserModel.getPuri("r").table("users").select("*").getMany();

  console.log("All users:", users);

  const created = users.find((u) => u.email === email);
  console.log("Created user:", created);

  expect(created).toBeDefined();
});
```

## Coverage Debugging

### Checking Coverage

```bash theme={null}
# Generate coverage
pnpm test --coverage

# Open HTML report
open coverage/index.html
```

### Finding Uncovered Code

```typescript theme={null}
// src/models/user.model.ts
class UserModelClass extends BaseModelClass {
  async createUser(email: string) {
    if (!email) {
      // This branch is not tested
      throw new Error("Email required");
    }

    return this.save({ email });
  }
}

// Add test
test("error when creating without email", async () => {
  await expect(UserModel.createUser("")).rejects.toThrow("Email required");
});
```

## Vitest Configuration Debugging

### Checking Configuration

`vitest.config.ts`:

```typescript theme={null}
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    globals: true,
    include: ["src/**/*.test.ts"],

    // Debugging options
    bail: 1, // Stop on first failure
    reporters: ["verbose"], // Verbose output
    logHeapUsage: true, // Output memory usage

    // Increase timeouts
    testTimeout: 10000,
    hookTimeout: 10000,
  },
});
```

### Checking Environment Variables

```typescript theme={null}
test("debugging environment variables", () => {
  console.log("NODE_ENV:", process.env.NODE_ENV);
  console.log("DB_HOST:", process.env.DB_HOST);
  console.log("All env vars:", process.env);
});
```

## Debugging Parallel Execution

### Disabling Isolation Mode

Some tests may have issues when running in parallel:

```typescript theme={null}
// vitest.config.ts
export default defineConfig({
  test: {
    pool: "forks",
    maxWorkers: 1, // Single worker
    isolate: false, // Disable isolation
  },
});
```

### Sequential Execution

```bash theme={null}
# Sequential execution
pnpm vitest run --no-threads
```

## Snapshot Debugging

### Updating Snapshots

```bash theme={null}
# Update snapshots
pnpm vitest run -u

# Specific file only
pnpm vitest run -u src/models/user.model.test.ts
```

### Checking Snapshots

```typescript theme={null}
test("snapshot debugging", () => {
  const data = {
    id: 1,
    name: "Test",
    timestamp: new Date().toISOString(),
  };

  // timestamp keeps changing
  expect(data).toMatchSnapshot();

  // Exclude dynamic values
  expect({
    ...data,
    timestamp: expect.any(String),
  }).toMatchSnapshot();
});
```

## Type Check Debugging

### Checking Type Errors

```bash theme={null}
# Run type check only
pnpm vitest typecheck

# Or
pnpm tsc --noEmit
```

### Type Tests

```typescript theme={null}
// src/**/*type-safety.test.ts
import { expectTypeOf } from "vitest";

test("verify type safety", () => {
  const user = { id: 1, email: "test@example.com" };

  expectTypeOf(user.id).toEqualTypeOf<number>();
  expectTypeOf(user.email).toEqualTypeOf<string>();
});
```

## Test Isolation Issues

### Checking beforeEach/afterEach

```typescript theme={null}
describe("User Tests", () => {
  let testUser: User;

  beforeEach(async () => {
    console.log("Setup started");
    testUser = await UserModel.create({
      email: "test@example.com",
    });
    console.log("Setup completed:", testUser.id);
  });

  afterEach(async () => {
    console.log("Cleanup started");
    if (testUser) {
      await UserModel.del(testUser.id);
    }
    console.log("Cleanup completed");
  });

  test("test 1", async () => {
    expect(testUser).toBeDefined();
  });
});
```

## Memory Leak Debugging

### Checking Memory Usage

```typescript theme={null}
// vitest.config.ts
export default defineConfig({
  test: {
    logHeapUsage: true, // Output memory usage
  },
});
```

### Checking Resource Cleanup

```typescript theme={null}
test("verify resource cleanup", async () => {
  const db = createConnection();

  try {
    await db.query("SELECT 1");
  } finally {
    await db.destroy(); // Always cleanup
    console.log("DB connection cleanup completed");
  }
});
```

## Best Practices

### 1. Test in Small Units

```typescript theme={null}
// Too large test
test("entire user flow", async () => {
  // Create, read, update, delete all included
});

// Split into small units
test("create user", async () => {});
test("get user", async () => {});
test("update user", async () => {});
test("delete user", async () => {});
```

### 2. Meaningful Test Names

```typescript theme={null}
// Unclear name
test("test1", async () => {});

// Clear name
test("BadRequestException when creating user without email", async () => {
  await expect(UserModel.create({ email: "" })).rejects.toThrow(BadRequestException);
});
```

### 3. AAA Pattern (Arrange-Act-Assert)

```typescript theme={null}
test("create user", async () => {
  // Arrange
  const email = "test@example.com";
  const name = "Test User";

  // Act
  const user = await UserModel.create({ email, name });

  // Assert
  expect(user.email).toBe(email);
  expect(user.name).toBe(name);
});
```

### 4. Sufficient Information on Failure

```typescript theme={null}
test("verify complex conditions", async () => {
  const result = await complexCalculation();

  // Make clear what went wrong on failure
  expect(result.total, `total should be ${result.expected} but was ${result.total}`).toBe(
    result.expected,
  );
});
```

## Related Documentation

* [Using Naite](/en/troubleshooting/debugging/using-naite)
* [Writing Tests](/en/testing/writing-tests/test-structure)
* [Debugging with Naite](/en/testing/naite/debugging-tests)
* [Source Maps](/en/troubleshooting/debugging/source-maps)
