From c4b872c5ec54340b1e62d7578ace400340573ce2 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 26 Apr 2026 18:16:11 +0300 Subject: test: bring every package above the 80% coverage target Per-package coverage was below the AGENTS.md target in six packages: cmd/ask 0.0% -> 83.3% cmd/hexai-tmux-edit 10.0% -> 93.3% cmd/hexai-tmux-action 27.8% -> 95.7% cmd/hexai-mcp-server 41.9% -> 88.2% internal/taskproxy 61.8% -> 98.2% internal/filelock 77.3% -> 100.0% The four cmd packages each had a main() that mixed flag parsing, struct construction, and runtime delegation, so nothing called from a test hit those statements. Each main() is now a one-line wrapper around a testable runMain(args, stdin, stdout, stderr) int that uses flag.NewFlagSet (instead of the global flag.Parse) so tests can drive it repeatedly. The deprecation banner in hexai-mcp-server is now a package-level constant, kept identical, so tests can assert on it directly without redirecting os.Stderr. The internal packages got new tests for paths that were previously unreachable: filelock's retry-then-success and non-EWOULDBLOCK error branches, and taskproxy's NewRunner / findTaskBinary / detectRepoRoot / runTaskCommand helpers (the ones that shell out to git and task). Co-Authored-By: Claude Opus 4.7 (1M context) --- cmd/ask/main.go | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'cmd/ask/main.go') diff --git a/cmd/ask/main.go b/cmd/ask/main.go index afab992..fbd5bb0 100644 --- a/cmd/ask/main.go +++ b/cmd/ask/main.go @@ -3,20 +3,33 @@ package main import ( "context" "fmt" + "io" "os" "codeberg.org/snonux/hexai/internal/askcli" ) -func main() { - d := askcli.NewDispatcher(nil) - code, err := d.Dispatch(context.Background(), os.Args[1:], os.Stdin, os.Stdout, os.Stderr) +// dispatcher is the minimal interface runMain depends on; it matches +// (*askcli.Dispatcher).Dispatch so a real dispatcher satisfies it directly. +type dispatcher interface { + Dispatch(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) (int, error) +} + +// dispatcherFactory is a test seam: override to inject a fake dispatcher so +// runMain can be exercised without a real `task` binary on PATH. +var dispatcherFactory = func() dispatcher { + return askcli.NewDispatcher(nil) +} + +func main() { os.Exit(runMain(os.Args[1:], os.Stdin, os.Stdout, os.Stderr)) } + +// runMain dispatches the command and returns the process exit code; errors +// are printed to stderr. The dispatcher's exit code is returned regardless +// of err so callers see Taskwarrior's own exit code on failure paths. +func runMain(args []string, stdin io.Reader, stdout, stderr io.Writer) int { + code, err := dispatcherFactory().Dispatch(context.Background(), args, stdin, stdout, stderr) if err != nil { - // Print the internal error so callers get a useful diagnostic message. - fmt.Fprintln(os.Stderr, err) - os.Exit(code) - } - if code != 0 { - os.Exit(code) + fmt.Fprintln(stderr, err) } + return code } -- cgit v1.2.3