# Dotfiles Test Suite Design

## Goal

Add bats-core unit tests for the dotfiles handling and distro bootstrap logic in neoche's entrypoint scripts.

## Approach

Shell script unit tests using bats-core. Real local git repos as fixtures (created at test runtime). Stubs for binaries that shouldn't run in tests (nvim, ttyd, machine-exec, nohup).

## Refactoring

Extract dotfiles handling (entrypoint-volume.sh lines 41-75) into a sourceable `dotfiles-apply.sh` so tests don't need to run the full entrypoint which starts services.

## Test Structure

```
tests/
  test_helper/
    setup.bash          # shared setup/teardown, PATH stubs, temp HOME
  dotfiles.bats         # dotfiles cloning + file placement
  bootstrap-distro.bats # distro bootstrap
```

Fixtures are ephemeral -- created via `git init` + `git commit` in setup(), torn down in teardown().

## Test Cases

| # | Test | Asserts |
|---|------|---------|
| 1 | Plain .config/nvim repo | $HOME/.config/nvim/init.lua exists |
| 2 | dot_bashrc file | $HOME/.bashrc exists with correct content |
| 3 | dot_config/ directory | $HOME/.config/ populated |
| 4 | Nested chezmoi: executable_init.lua | File renamed, +x permission set |
| 5 | Nested chezmoi: readonly_, empty_ | Prefixes stripped, files exist |
| 6 | Mixed repo (.config/ + dot_*) | Both paths applied |
| 7 | Token injection | Clone URL contains token |
| 8 | Empty repo | No errors, no files in .config/ |
| 9 | Existing $HOME/.config/nvim | Distro bootstrap skipped |
| 10 | Each distro name | bootstrap-distro.sh clones correct repo |
| 11 | Unknown distro name | Warns and exits 0 |

## Stubs

Fake scripts prepended to PATH for: nvim, ttyd, machine-exec, nohup. Each is a no-op that exits 0.

## Decisions

- bats-core over shunit2: better assertion library, widely used, supports parallel test execution
- Local git repos over mocked git: tests the real clone path including --depth 1
- Extracted function over full entrypoint: avoids starting machine-exec/ttyd in tests
- No container required: pure shell logic, runs in CI without docker
