Compare commits
No commits in common. "24314c9c95ffe820955b99f42b1254a8ac8d0545" and "e70a72f5b84d890d0d393c6193231b6aef2133a1" have entirely different histories.
24314c9c95
...
e70a72f5b8
|
|
@ -12,7 +12,6 @@ Transcript-based shell integration test runner. Bun + TypeScript.
|
||||||
- `--clean-env` — start with empty environment
|
- `--clean-env` — start with empty environment
|
||||||
- `--path <path>` — prepend to `$PATH` (repeatable)
|
- `--path <path>` — prepend to `$PATH` (repeatable)
|
||||||
- `--timeout <dur>` — per-command timeout (default `10s`)
|
- `--timeout <dur>` — per-command timeout (default `10s`)
|
||||||
- `-t, --filter <pattern>` — only run files whose path contains `<pattern>`
|
|
||||||
- `-v, --verbose` — print each command as it runs
|
- `-v, --verbose` — print each command as it runs
|
||||||
- `--port-from <n>` — auto-assign `$PORT` starting from n (default `5400`)
|
- `--port-from <n>` — auto-assign `$PORT` starting from n (default `5400`)
|
||||||
- `--parallel` — run files in parallel
|
- `--parallel` — run files in parallel
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,6 @@ Options:
|
||||||
--clean-env Start with empty environment
|
--clean-env Start with empty environment
|
||||||
--path <path> Prepend <path> to PATH (repeatable)
|
--path <path> Prepend <path> to PATH (repeatable)
|
||||||
--timeout <dur> Per-command timeout (default: "10s")
|
--timeout <dur> Per-command timeout (default: "10s")
|
||||||
-t, --filter Only run files matching <pattern> (substring match)
|
|
||||||
-v, --verbose Print each command as it runs
|
-v, --verbose Print each command as it runs
|
||||||
--port-from <n> Auto-assign $PORT starting from n (default: "5400")
|
--port-from <n> Auto-assign $PORT starting from n (default: "5400")
|
||||||
--parallel Run files in parallel
|
--parallel Run files in parallel
|
||||||
|
|
|
||||||
57
STDIN.md
57
STDIN.md
|
|
@ -1,57 +0,0 @@
|
||||||
# Stdin / Prompt Support
|
|
||||||
|
|
||||||
## The challenge
|
|
||||||
|
|
||||||
Currently, the shell's stdin is consumed by the script itself (`buildScript` writes all commands at once, then `proc.stdin.end()`). There's no channel left to feed stdin to individual commands.
|
|
||||||
|
|
||||||
## Simplest design: heredoc injection
|
|
||||||
|
|
||||||
Add a `< ` prefix for stdin lines in `.shout` files. At script-build time, transform the command into a heredoc pipe. No runtime changes needed.
|
|
||||||
|
|
||||||
**Syntax:**
|
|
||||||
|
|
||||||
```
|
|
||||||
$ read -p "Name: " name && echo "Hello, $name"
|
|
||||||
< Chris
|
|
||||||
Name: Hello, Chris
|
|
||||||
|
|
||||||
$ cat
|
|
||||||
< line one
|
|
||||||
< line two
|
|
||||||
line one
|
|
||||||
line two
|
|
||||||
|
|
||||||
$ grep -c foo
|
|
||||||
< foo bar
|
|
||||||
< baz
|
|
||||||
< foo baz
|
|
||||||
2
|
|
||||||
```
|
|
||||||
|
|
||||||
**Implementation:** In `parse.ts`, collect `< ` lines as a new `stdin: string[]` field on `Command`. In `buildScript`, when `cmd.stdin` is non-empty, wrap the command:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# instead of:
|
|
||||||
some_command
|
|
||||||
# generate:
|
|
||||||
some_command <<'__SHOUT_STDIN__'
|
|
||||||
line one
|
|
||||||
line two
|
|
||||||
__SHOUT_STDIN__
|
|
||||||
```
|
|
||||||
|
|
||||||
This is ~30 lines of change across parse + run, and fits cleanly into the existing architecture.
|
|
||||||
|
|
||||||
## What it wouldn't handle
|
|
||||||
|
|
||||||
- **Interactive prompts with branching** (send input, read output, decide next input) — would require per-command execution, a much bigger refactor
|
|
||||||
- **Timing-sensitive input** (send after a delay) — same issue
|
|
||||||
- **Binary stdin** — heredocs are text-only
|
|
||||||
|
|
||||||
## Alternative: named pipes (more complex)
|
|
||||||
|
|
||||||
For each command needing stdin, create a FIFO in the temp dir and redirect from it. Shout would write to the FIFO from the Node side at the right time. This could support interactive flows but adds significant complexity to the sentinel-based output parsing — you'd need to synchronize "when to write the next stdin chunk."
|
|
||||||
|
|
||||||
## Recommendation
|
|
||||||
|
|
||||||
The heredoc approach covers the 90% case (testing CLIs that read input, `cat`, `read`, piped filters) with minimal change.
|
|
||||||
|
|
@ -80,26 +80,20 @@ program
|
||||||
.option("--timeout <dur>", "Per-command timeout", "10s")
|
.option("--timeout <dur>", "Per-command timeout", "10s")
|
||||||
.option("-v, --verbose", "Print each command as it runs")
|
.option("-v, --verbose", "Print each command as it runs")
|
||||||
.option("--port-from <n>", "Auto-assign $PORT starting from <n>", "5400")
|
.option("--port-from <n>", "Auto-assign $PORT starting from <n>", "5400")
|
||||||
.option("-t, --filter <pattern>", "Only run files matching <pattern> (substring match)")
|
|
||||||
.option("--parallel", "Run files in parallel")
|
.option("--parallel", "Run files in parallel")
|
||||||
.action(async (fileArgs: string[], opts) => {
|
.action(async (fileArgs: string[], opts) => {
|
||||||
const timeoutMs = parseDuration(opts.timeout)
|
const timeoutMs = parseDuration(opts.timeout)
|
||||||
const paths = fileArgs.length > 0 ? fileArgs : ["."]
|
const paths = fileArgs.length > 0 ? fileArgs : ["."]
|
||||||
let files = await findShoutFiles(paths)
|
const files = await findShoutFiles(paths)
|
||||||
|
|
||||||
|
if (files.length === 0) {
|
||||||
|
console.error("No .shout files found")
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
const start = performance.now()
|
const start = performance.now()
|
||||||
const results: TestResult[] = []
|
const results: TestResult[] = []
|
||||||
const cwd = process.cwd()
|
const cwd = process.cwd()
|
||||||
|
|
||||||
if (opts.filter) {
|
|
||||||
const pattern = opts.filter
|
|
||||||
files = files.filter(f => relative(cwd, f).includes(pattern))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (files.length === 0) {
|
|
||||||
console.error(opts.filter ? `No .shout files matching "${opts.filter}"` : "No .shout files found")
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
const portFrom = parseInt(opts.portFrom, 10)
|
const portFrom = parseInt(opts.portFrom, 10)
|
||||||
if (Number.isNaN(portFrom)) {
|
if (Number.isNaN(portFrom)) {
|
||||||
console.error("--port-from must be an integer")
|
console.error("--port-from must be an integer")
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,6 @@ Options:
|
||||||
--clean-env Start with empty environment
|
--clean-env Start with empty environment
|
||||||
--path <path> Prepend <path> to PATH (repeatable)
|
--path <path> Prepend <path> to PATH (repeatable)
|
||||||
--timeout <dur> Per-command timeout (default: "10s")
|
--timeout <dur> Per-command timeout (default: "10s")
|
||||||
-t, --filter Only run files matching <pattern> (substring match)
|
|
||||||
-v, --verbose Print each command as it runs
|
-v, --verbose Print each command as it runs
|
||||||
--port-from <n> Auto-assign $PORT starting from n (default: "5400")
|
--port-from <n> Auto-assign $PORT starting from n (default: "5400")
|
||||||
--parallel Run files in parallel
|
--parallel Run files in parallel
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user