Repterm
Guides

Debugging

Tips and techniques for debugging failing Repterm tests

Verbose Output

Run tests with the --verbose flag to see detailed output, including full command results, terminal snapshots, and timing information.

repterm --verbose tests/

Debugging Techniques

Inspect Terminal State

Use terminal.snapshot() to capture and inspect the current state of the terminal at any point during a test. This is useful when expect or waitForText fails and you need to see what the terminal actually contains.

test('debug example', async ({ $, terminal }) => {
  await $`some-command`;

  // Print the current terminal content for debugging
  const snapshot = terminal.snapshot();
  console.log('Terminal state:', snapshot);
});

Use silent: true for Reliable Exit Codes

In PTY and recording modes, CommandResult.code may be -1 because the exit code is not always reliably captured through the PTY layer. If your test depends on exit codes, use silent: true to run the command outside the PTY.

test('check exit code', async ({ $ }) => {
  const result = await $({ silent: true })`grep "pattern" /some/file`;

  // Exit code is reliable with silent: true
  await expect(result).toFail();
});

Handle ANSI Escape Codes

Terminal output often includes ANSI escape codes for colors and formatting. These invisible characters can cause text matching to fail. Use terminal.snapshot() to inspect the raw terminal state, or use waitForText with stripAnsi option for terminal-level text matching.

test('ansi handling', async ({ terminal }) => {
  const proc = terminal.run('ls --color=always', { interactive: true });

  // proc.expect() matches text in terminal output
  await proc.expect('filename');

  // Use snapshot to inspect raw terminal state for debugging
  const snapshot = terminal.snapshot();
  console.log('Raw terminal:', snapshot);
});

Adjust Timeouts

If waitForText or expect times out, the text may simply not have appeared yet. Increase the timeout to give slow commands more time.

test('slow command', async ({ terminal }) => {
  const proc = terminal.run('slow-build-tool', {
    interactive: true,
    timeout: 60_000, // 60 seconds
  });

  await proc.expect('Build complete');
});

Quick Symptom Lookup

SymptomLikely CauseAction
--record fails to startMissing asciinema or tmuxInstall dependencies: brew install asciinema tmux (macOS) or apt-get install asciinema tmux (Ubuntu)
code === -1Running under PTY or recording modeAssert on output content instead of exit code, or use silent: true
waitForText timeoutText not present in output, or hidden by ANSI escape codesIncrease the timeout, use terminal.snapshot() to inspect state, or try stripAnsi: false
0 tests foundWrong file path or empty filterVerify the test file path and check that { record: true } is set if using --record

Common Patterns

Debugging a Flaky Test

test('flaky test', async ({ $, terminal }) => {
  const result = await $`flaky-command`;

  // Log output for debugging
  console.log('stdout:', result.stdout);
  console.log('stderr:', result.stderr);
  console.log('exit code:', result.code);

  // Snapshot the terminal to see full context
  const snapshot = terminal.snapshot();
  console.log('terminal:', snapshot);

  await expect(result).toSucceed();
});

Isolating Failures in Multi-Step Tests

Use test.step to narrow down which part of a multi-step test is failing:

test('multi-step', async ({ $ }) => {
  await test.step('setup', async () => {
    const result = await $`mkdir -p /tmp/debug-test`;
    await expect(result).toSucceed();
  });

  await test.step('action', async () => {
    const result = await $`some-command /tmp/debug-test`;
    await expect(result).toSucceed();
  });

  await test.step('verify', async () => {
    const result = await $`ls /tmp/debug-test`;
    await expect(result).toContainInOutput('expected-file');
  });
});