Skip to content

Commit c636903

Browse files
authored
test: clarify repo-level test layout (#170)
1 parent 74b725b commit c636903

11 files changed

Lines changed: 66 additions & 14 deletions

File tree

AGENTS.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ CLI input
5656
- Colocate unit tests with the code they cover (`src/core/foo.ts` + `src/core/foo.test.ts`, `src/ui/AppHost.*.test.tsx`, `src/ui/lib/*.test.ts`).
5757
- Put shared unit-test helpers in `test/helpers/`.
5858
- Name test helpers so they explicitly include `Test` and are clearly test-only (`createTestDiffFile`).
59-
- Keep other repo-level `test/` files for cross-cutting integration, PTY/session, CLI transcript, and smoke coverage.
59+
- Use repo-level `test/` directories by intent:
60+
- `test/cli/` for black-box CLI contract coverage.
61+
- `test/session/` for daemon/session integration and end-to-end flows.
62+
- `test/pty/` for PTY-backed live UI integration tests.
63+
- `test/smoke/` for opt-in terminal transcript smoke coverage.
6064

6165
## code comments
6266

@@ -110,7 +114,7 @@ CLI input
110114
## verification
111115

112116
- For rendering changes: run `bun run typecheck`, `bun test`, `bun run test:integration`, `bun run test:tty-smoke`, and do one real TTY smoke run on an actual diff.
113-
- For interaction, layout, scrolling, navigation, windowing, or other terminal-native behavior: add or update PTY integration coverage in `test/integration/*.integration.ts` and run it with `bun run test:integration`.
117+
- For interaction, layout, scrolling, navigation, windowing, or other terminal-native behavior: add or update PTY integration coverage in `test/pty/*-integration.test.ts` and run it with `bun run test:integration`.
114118
- For CLI, config, or pager work: make sure the relevant source invocation still works (`diff`, `show`, `patch`, or `pager`).
115119
- Preserve current interaction model unless the user asks to change it explicitly.
116120

CONTRIBUTING.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,17 @@ bun run publish:prebuilt:npm -- --dry-run
9191
- CLI, config, or pager changes: verify the relevant source invocation still works, such as `diff`, `show`, `patch`, or `pager`.
9292
- Packaging or release changes: run the pack and prebuilt checks locally before opening a PR.
9393

94+
## Test layout
95+
96+
- Most unit tests are colocated in `src/` beside the code they cover.
97+
- `test/helpers/` contains shared test-only fixtures used by those unit tests.
98+
- `test/cli/` covers black-box CLI behavior.
99+
- `test/session/` covers daemon, broker, and session-CLI integration flows.
100+
- `test/pty/` covers PTY-backed live UI integration.
101+
- `test/smoke/` contains opt-in transcript-based TTY smoke tests.
102+
103+
See [`test/README.md`](test/README.md) for the intent behind each top-level test category.
104+
94105
## Architecture
95106

96107
```text

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
"lint:fix": "oxlint . --fix",
5050
"prepare": "simple-git-hooks",
5151
"test": "\"${npm_execpath:-bun}\" test",
52-
"test:integration": "\"${npm_execpath:-bun}\" test ./test/integration/tuistory-hunk.integration.ts",
53-
"test:tty-smoke": "HUNK_RUN_TTY_SMOKE=1 \"${npm_execpath:-bun}\" test test/tty-render-smoke.test.ts",
52+
"test:integration": "\"${npm_execpath:-bun}\" test ./test/pty",
53+
"test:tty-smoke": "HUNK_RUN_TTY_SMOKE=1 \"${npm_execpath:-bun}\" test ./test/smoke",
5454
"check:pack": "bun run ./scripts/check-pack.ts",
5555
"check:prebuilt-pack": "bun run ./scripts/check-prebuilt-pack.ts",
5656
"smoke:prebuilt-install": "bun run ./scripts/smoke-prebuilt-install.ts",

test/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Test layout
2+
3+
Most Hunk tests are colocated in `src/` beside the code they cover.
4+
5+
The top-level `test/` tree is reserved for cases that intentionally exercise the product across module, process, repo, or terminal boundaries.
6+
7+
## Structure
8+
9+
```text
10+
test/
11+
helpers/ shared unit-test fixtures
12+
cli/ black-box CLI contracts
13+
session/ daemon, broker, and session-CLI flows
14+
pty/ live PTY-driven UI integration
15+
smoke/ thin terminal transcript sanity checks
16+
```
17+
18+
## What lives here
19+
20+
- `test/helpers/` — shared test-only builders and fixtures reused by colocated unit tests.
21+
- `test/cli/` — black-box CLI contract tests that spawn the real entrypoint and assert help, version, pager fallback, and friendly error output.
22+
- `test/session/` — daemon, broker, and session-CLI coverage. These tests often start subprocesses, create temp repos/files, and verify cross-process behavior.
23+
- `test/pty/` — PTY-backed live UI integration tests for resize, navigation, mouse input, layout changes, and note visibility.
24+
- `test/smoke/` — opt-in terminal transcript smoke coverage for real TTY rendering (`bun run test:tty-smoke`).
25+
26+
## Why these are not colocated
27+
28+
These tests do not belong to a single source file. They usually verify product-level behavior such as:
29+
30+
- command-line contracts
31+
- subprocess and daemon lifecycle
32+
- live session brokering
33+
- PTY / terminal rendering behavior
34+
- full review-flow interactions across multiple modules
35+
36+
If a test mainly targets one module or helper, keep it colocated in `src/`.
37+
If it needs a real repo, subprocess, daemon, PTY, or transcript-level assertion, it likely belongs under `test/`.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function git(cwd: string, ...args: string[]) {
1818
}
1919
}
2020

21-
describe("CLI help output", () => {
21+
describe("CLI entrypoint contracts", () => {
2222
test("bare hunk prints standard help without terminal takeover sequences", () => {
2323
const proc = Bun.spawnSync(["bun", "run", "src/main.tsx"], {
2424
cwd: process.cwd(),
@@ -89,7 +89,7 @@ describe("CLI help output", () => {
8989
});
9090

9191
test("prints the package version for --version without terminal takeover sequences", () => {
92-
const expectedVersion = require("../package.json").version;
92+
const expectedVersion = require("../../package.json").version;
9393
const proc = Bun.spawnSync(["bun", "run", "src/main.tsx", "--version"], {
9494
cwd: process.cwd(),
9595
stdin: "ignore",
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ function runGit(args: string[], cwd: string, allowExitCodeOne = false) {
8787
return proc.stdout;
8888
}
8989

90-
/** Build a fresh helper that tracks its own temp directories for one integration test file. */
91-
export function createTuistoryHarness() {
90+
/** Build a fresh PTY test helper that tracks its own temp directories for one integration test file. */
91+
export function createPtyHarness() {
9292
const tempDirs: string[] = [];
9393

9494
function makeTempDir(prefix: string) {

test/integration/tuistory-hunk.integration.ts renamed to test/pty/ui-integration.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { afterEach, describe, expect, setDefaultTimeout, test } from "bun:test";
2-
import { createTuistoryHarness } from "./tuistoryHarness";
2+
import { createPtyHarness } from "./harness";
33

4-
const harness = createTuistoryHarness();
4+
const harness = createPtyHarness();
55

66
/** Give PTY-backed startup and redraws enough headroom for slower CI machines. */
77
setDefaultTimeout(20_000);
@@ -10,7 +10,7 @@ afterEach(() => {
1010
harness.cleanup();
1111
});
1212

13-
describe("Hunk integration via tuistory", () => {
13+
describe("live UI integration", () => {
1414
test("real PTY sessions can toggle wrapped lines on and off", async () => {
1515
const fixture = harness.createLongWrapFilePair();
1616
const session = await harness.launchHunk({
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ afterEach(() => {
194194
cleanupTempDirs();
195195
});
196196

197-
describe("live session end-to-end", () => {
197+
describe("session broker end-to-end", () => {
198198
test("a live Hunk session auto-starts the daemon and renders CLI comments inline", async () => {
199199
if (!ttyToolsAvailable) {
200200
return;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ afterEach(() => {
128128
cleanupTempDirs();
129129
});
130130

131-
describe("session CLI", () => {
131+
describe("session CLI integration", () => {
132132
test("list/get/context expose live Hunk sessions through the daemon", async () => {
133133
if (!ttyToolsAvailable) {
134134
return;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ afterEach(async () => {
6767
);
6868
});
6969

70-
describe("mcp serve process lifecycle", () => {
70+
describe("session daemon lifecycle", () => {
7171
test("exits cleanly after SIGTERM instead of hot-looping after server shutdown", async () => {
7272
const port = await reserveLoopbackPort();
7373
const proc = Bun.spawn(["bun", "run", "src/main.tsx", "mcp", "serve"], {

0 commit comments

Comments
 (0)