Files
beads/cmd/bd/prime_test.go
Abhinav Gupta 09a9ffa922 feat(prime): add --stealth flag for flush-only workflow
Add a `--stealth` flag to `bd prime` that outputs a simplified
workflow using only `bd sync --flush-only`, omitting all git
operations (commit, push, pull).

This addresses use cases where git operations need to be deferred
or handled separately from the bd workflow (e.g. bd init --stealth),
where committing files is may not desired as part of the Claude
conversation.

In stealth mode, the close protocol shows only the flush step.

Includes tests for current and existing functionality.

To make testing easier,
refactor output functions to accept `io.Writer` parameters
instead of writing directly to `os.Stdout`,
and convert `isEphemeralBranch` from a function to a
variable for stubbing.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 18:08:33 -08:00

111 lines
3.0 KiB
Go

package main
import (
"bytes"
"strings"
"testing"
)
func TestOutputContextFunction(t *testing.T) {
tests := []struct {
name string
mcpMode bool
stealthMode bool
ephemeralMode bool
expectText []string
rejectText []string
}{
{
name: "CLI Normal (non-ephemeral)",
mcpMode: false,
stealthMode: false,
ephemeralMode: false,
expectText: []string{"Beads Workflow Context", "bd sync", "git push"},
rejectText: []string{"bd sync --flush-only", "--from-main"},
},
{
name: "CLI Normal (ephemeral)",
mcpMode: false,
stealthMode: false,
ephemeralMode: true,
expectText: []string{"Beads Workflow Context", "bd sync --from-main", "ephemeral branch"},
rejectText: []string{"bd sync --flush-only", "git push"},
},
{
name: "CLI Stealth",
mcpMode: false,
stealthMode: true,
ephemeralMode: false, // stealth mode overrides ephemeral detection
expectText: []string{"Beads Workflow Context", "bd sync --flush-only"},
rejectText: []string{"git push", "git pull", "git commit", "git status", "git add"},
},
{
name: "MCP Normal (non-ephemeral)",
mcpMode: true,
stealthMode: false,
ephemeralMode: false,
expectText: []string{"Beads Issue Tracker Active", "bd sync", "git push"},
rejectText: []string{"bd sync --flush-only", "--from-main"},
},
{
name: "MCP Normal (ephemeral)",
mcpMode: true,
stealthMode: false,
ephemeralMode: true,
expectText: []string{"Beads Issue Tracker Active", "bd sync --from-main", "ephemeral branch"},
rejectText: []string{"bd sync --flush-only", "git push"},
},
{
name: "MCP Stealth",
mcpMode: true,
stealthMode: true,
ephemeralMode: false, // stealth mode overrides ephemeral detection
expectText: []string{"Beads Issue Tracker Active", "bd sync --flush-only"},
rejectText: []string{"git push", "git pull", "git commit", "git status", "git add"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer stubIsEphemeralBranch(tt.ephemeralMode)()
var buf bytes.Buffer
err := outputPrimeContext(&buf, tt.mcpMode, tt.stealthMode)
if err != nil {
t.Fatalf("outputPrimeContext failed: %v", err)
}
output := buf.String()
for _, expected := range tt.expectText {
if !strings.Contains(output, expected) {
t.Errorf("Expected text not found: %s", expected)
}
}
for _, rejected := range tt.rejectText {
if strings.Contains(output, rejected) {
t.Errorf("Unexpected text found: %s", rejected)
}
}
})
}
}
// stubIsEphemeralBranch temporarily replaces isEphemeralBranch
// with a stub returning returnValue.
//
// Returns a function to restore the original isEphemeralBranch.
// Usage:
//
// defer stubIsEphemeralBranch(true)()
func stubIsEphemeralBranch(isEphem bool) func() {
original := isEphemeralBranch
isEphemeralBranch = func() bool {
return isEphem
}
return func() {
isEphemeralBranch = original
}
}