Files
agent-lib/internal/e2e/status_test.go
T

141 lines
4.0 KiB
Go
Raw Normal View History

package e2e
import (
"encoding/json"
"os"
"path/filepath"
"testing"
)
func statusRun(t *testing.T, env *syncEnv, jsonFlag bool) (string, error) {
t.Helper()
args := []string{"status", "--config", env.config}
if jsonFlag {
args = append(args, "--json")
}
cmd := agentLibCmd(args...)
cmd.Env = append(os.Environ(),
"HOME="+env.home, "USERPROFILE="+env.home,
"AGENT_LIB_STATE_DIR="+env.stateDir,
)
out, err := cmd.CombinedOutput()
return string(out), err
}
func TestStatusInSync(t *testing.T) {
h := newHarness(t)
env := newSyncEnv(t, h)
buildWorkRepo(t, h, env.workRepo)
env.writeConfig(t, env.workRepo, "")
syncOnce(t, env)
out, err := statusRun(t, env, false)
if err != nil {
t.Fatalf("in-sync status must exit 0: %v\n%s", err, out)
}
for _, want := range []string{"in sync", "deployed revision", "repository revision", "agent-lib"} {
if !contains(out, want) {
t.Errorf("status output missing %q:\n%s", want, out)
}
}
}
func TestStatusDriftNonZero(t *testing.T) {
h := newHarness(t)
env := newSyncEnv(t, h)
buildWorkRepo(t, h, env.workRepo)
env.writeConfig(t, env.workRepo, "")
syncOnce(t, env)
os.WriteFile(filepath.Join(env.home, ".agents/skills/own-skill/SKILL.md"),
[]byte("---\nname: Own Skill\n---\n# my edits\n"), 0o644)
p := filepath.Join(env.workRepo, "skills/own-skill/SKILL.md")
os.WriteFile(p, []byte("---\nname: Own Skill\ndescription: v2\n---\n# Upstream v2\n"), 0o644)
commitWorkRepo(t, h, env.workRepo, "change own-skill")
out, err := statusRun(t, env, false)
if err == nil {
t.Fatalf("blocked-update drift must exit non-zero:\n%s", out)
}
for _, want := range []string{"skipped", "own-skill", "locally modified", "drift"} {
if !contains(out, want) {
t.Errorf("status missing %q:\n%s", want, out)
}
}
jsonOut, err := statusRun(t, env, true)
if err == nil {
t.Fatalf("json status must keep the drift exit code:\n%s", jsonOut)
}
var report struct {
InSync bool `json:"in_sync"`
Drift bool `json:"problematic_drift"`
Skipped []struct {
Item string `json:"item"`
Reason string `json:"reason"`
} `json:"skipped_items"`
Pending []struct {
Item string `json:"item"`
} `json:"pending_changes"`
}
if err := json.Unmarshal([]byte(jsonOut), &report); err != nil {
t.Fatalf("status --json not parseable: %v\n%s", err, jsonOut)
}
if !report.Drift || report.InSync {
t.Errorf("json flags wrong: %+v", report)
}
if len(report.Skipped) != 1 || report.Skipped[0].Item != "skills/own-skill" {
t.Errorf("skipped item missing from json: %+v", report.Skipped)
}
}
func TestStatusUnrecognizedButNoDrift(t *testing.T) {
h := newHarness(t)
env := newSyncEnv(t, h)
buildWorkRepo(t, h, env.workRepo)
env.writeConfig(t, env.workRepo, "")
syncOnce(t, env)
mine := filepath.Join(env.home, ".agents/skills/my-own-thing")
os.MkdirAll(mine, 0o755)
os.WriteFile(filepath.Join(mine, "SKILL.md"), []byte("---\nname: Mine\n---\n"), 0o644)
out, err := statusRun(t, env, false)
if err != nil {
t.Fatalf("unrecognized items alone are not problematic drift:\n%s", out)
}
if !contains(out, "unrecognized local items") || !contains(out, "my-own-thing") {
t.Errorf("unrecognized item must be listed:\n%s", out)
}
if contains(out, "drift:") {
t.Errorf("no drift line expected:\n%s", out)
}
}
func TestStatusNeverSynced(t *testing.T) {
h := newHarness(t)
env := newSyncEnv(t, h)
buildWorkRepo(t, h, env.workRepo)
env.writeConfig(t, env.workRepo, "")
out, err := statusRun(t, env, true)
if err != nil {
t.Fatalf("fresh status must exit 0: %v\n%s", err, out)
}
var report struct {
DeployedRev string `json:"deployed_revision"`
Pending []struct {
Item string `json:"item"`
} `json:"pending_changes"`
}
if err := json.Unmarshal([]byte(out), &report); err != nil {
t.Fatalf("json not parseable: %v", err)
}
if report.DeployedRev != "" {
t.Errorf("never synced must have empty deployed revision: %q", report.DeployedRev)
}
if len(report.Pending) == 0 {
t.Error("fresh status must list everything as pending deploy")
}
}