Files
beads/cmd/bd/mol_test.go
Steve Yegge 6580178226 feat(mol): smart --var detection for distill accepts both syntaxes
Agents naturally use spawn-style (variable=value) for both spawn and
distill commands. Now distill accepts both:
- --var branch=feature-auth (spawn-style)
- --var feature-auth=branch (substitution-style)

Smart detection checks which side appears in the epic text:
- Right side found → spawn-style (left is varname)
- Left side found → substitution-style (left is value)
- Both found → prefers spawn-style (more common guess)

Embodies the Beads philosophy: watch what agents do, make their guess correct.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 11:10:04 -08:00

160 lines
3.7 KiB
Go

package main
import (
"strings"
"testing"
"github.com/steveyegge/beads/internal/types"
)
func TestParseDistillVar(t *testing.T) {
tests := []struct {
name string
varFlag string
searchableText string
wantFind string
wantVar string
wantErr bool
}{
{
name: "spawn-style: variable=value",
varFlag: "branch=feature-auth",
searchableText: "Implement feature-auth login flow",
wantFind: "feature-auth",
wantVar: "branch",
wantErr: false,
},
{
name: "substitution-style: value=variable",
varFlag: "feature-auth=branch",
searchableText: "Implement feature-auth login flow",
wantFind: "feature-auth",
wantVar: "branch",
wantErr: false,
},
{
name: "spawn-style with version number",
varFlag: "version=1.2.3",
searchableText: "Release version 1.2.3 to production",
wantFind: "1.2.3",
wantVar: "version",
wantErr: false,
},
{
name: "both found - prefers spawn-style",
varFlag: "api=api",
searchableText: "The api endpoint uses api keys",
wantFind: "api",
wantVar: "api",
wantErr: false,
},
{
name: "neither found - error",
varFlag: "foo=bar",
searchableText: "Nothing matches here",
wantFind: "",
wantVar: "",
wantErr: true,
},
{
name: "empty left side - error",
varFlag: "=value",
searchableText: "Some text with value",
wantFind: "",
wantVar: "",
wantErr: true,
},
{
name: "empty right side - error",
varFlag: "value=",
searchableText: "Some text with value",
wantFind: "",
wantVar: "",
wantErr: true,
},
{
name: "no equals sign - error",
varFlag: "noequals",
searchableText: "Some text",
wantFind: "",
wantVar: "",
wantErr: true,
},
{
name: "value with equals sign",
varFlag: "env=KEY=VALUE",
searchableText: "Set KEY=VALUE in config",
wantFind: "KEY=VALUE",
wantVar: "env",
wantErr: false,
},
{
name: "partial match in longer word - finds it",
varFlag: "name=auth",
searchableText: "authentication module",
wantFind: "auth",
wantVar: "name",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotFind, gotVar, err := parseDistillVar(tt.varFlag, tt.searchableText)
if tt.wantErr {
if err == nil {
t.Errorf("parseDistillVar() expected error, got none")
}
return
}
if err != nil {
t.Errorf("parseDistillVar() unexpected error: %v", err)
return
}
if gotFind != tt.wantFind {
t.Errorf("parseDistillVar() find = %q, want %q", gotFind, tt.wantFind)
}
if gotVar != tt.wantVar {
t.Errorf("parseDistillVar() var = %q, want %q", gotVar, tt.wantVar)
}
})
}
}
func TestCollectSubgraphText(t *testing.T) {
// Create a simple subgraph for testing
subgraph := &MoleculeSubgraph{
Issues: []*types.Issue{
{
Title: "Epic: Feature Auth",
Description: "Implement authentication",
Design: "Use OAuth2",
},
{
Title: "Add login endpoint",
Notes: "See RFC 6749",
},
},
}
text := collectSubgraphText(subgraph)
// Verify all fields are included
expected := []string{
"Epic: Feature Auth",
"Implement authentication",
"Use OAuth2",
"Add login endpoint",
"See RFC 6749",
}
for _, exp := range expected {
if !strings.Contains(text, exp) {
t.Errorf("collectSubgraphText() missing %q", exp)
}
}
}