Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

109 lines
3.6 KiB
Go

package agents
import "testing"
// gortexGroupCount counts the gortex-authored hook groups under one
// event in a settings root.
func gortexGroupCount(root map[string]any, event string) int {
hooks, _ := root["hooks"].(map[string]any)
arr, _ := hooks[event].([]any)
n := 0
for _, e := range arr {
if hookGroupIsGortex(e) {
n++
}
}
return n
}
func TestUpsertGeminiHooks_InstallsSessionStartAndAfterTool(t *testing.T) {
root := map[string]any{}
if !UpsertGeminiHooks(root, "gemini", ApplyOpts{}) {
t.Fatal("expected the first install to report a change")
}
hooks, ok := root["hooks"].(map[string]any)
if !ok {
t.Fatal("hooks key not written")
}
for _, event := range []string{"SessionStart", "AfterTool"} {
arr, ok := hooks[event].([]any)
if !ok || len(arr) != 1 {
t.Fatalf("%s: want one group, got %v", event, hooks[event])
}
group := arr[0].(map[string]any)
inner := group["hooks"].([]any)[0].(map[string]any)
if inner["command"] != "gortex hook --agent gemini" {
t.Errorf("%s command=%v", event, inner["command"])
}
if inner["timeout"] != geminiHookTimeoutMS {
t.Errorf("%s timeout=%v want %d (milliseconds)", event, inner["timeout"], geminiHookTimeoutMS)
}
}
// AfterTool carries a tool matcher; SessionStart does not.
if _, ok := hooks["AfterTool"].([]any)[0].(map[string]any)["matcher"]; !ok {
t.Error("AfterTool group should carry a matcher")
}
if _, ok := hooks["SessionStart"].([]any)[0].(map[string]any)["matcher"]; ok {
t.Error("SessionStart group should not carry a matcher")
}
}
func TestUpsertGeminiHooks_Idempotent(t *testing.T) {
root := map[string]any{}
UpsertGeminiHooks(root, "gemini", ApplyOpts{})
if UpsertGeminiHooks(root, "gemini", ApplyOpts{}) {
t.Error("a second install without Force should be a no-op")
}
if got := gortexGroupCount(root, "SessionStart"); got != 1 {
t.Errorf("SessionStart gortex groups=%d want 1 (no duplicate)", got)
}
}
func TestUpsertGeminiHooks_PreservesExistingUserHooks(t *testing.T) {
root := map[string]any{
"hooks": map[string]any{
"AfterTool": []any{
map[string]any{"hooks": []any{map[string]any{"type": "command", "command": "my-own-linter", "name": "user"}}},
},
},
}
UpsertGeminiHooks(root, "gemini", ApplyOpts{})
arr := root["hooks"].(map[string]any)["AfterTool"].([]any)
if len(arr) != 2 {
t.Fatalf("expected the user's hook to be preserved alongside gortex's, got %d groups", len(arr))
}
// The user's entry must survive untouched.
first := arr[0].(map[string]any)["hooks"].([]any)[0].(map[string]any)
if first["command"] != "my-own-linter" {
t.Errorf("user hook clobbered: %v", first)
}
}
func TestUpsertGeminiHooks_ForceReplacesGortexOnly(t *testing.T) {
root := map[string]any{}
UpsertGeminiHooks(root, "gemini", ApplyOpts{})
// Add a user hook to AfterTool, then force-reinstall.
hooks := root["hooks"].(map[string]any)
hooks["AfterTool"] = append(hooks["AfterTool"].([]any),
map[string]any{"hooks": []any{map[string]any{"type": "command", "command": "user-linter", "name": "user"}}})
if !UpsertGeminiHooks(root, "gemini", ApplyOpts{Force: true}) {
t.Fatal("Force reinstall should report a change")
}
if got := gortexGroupCount(root, "AfterTool"); got != 1 {
t.Errorf("Force should leave exactly one gortex group, got %d", got)
}
// The user's hook still survives.
arr := hooks["AfterTool"].([]any)
foundUser := false
for _, e := range arr {
inner := e.(map[string]any)["hooks"].([]any)[0].(map[string]any)
if inner["command"] == "user-linter" {
foundUser = true
}
}
if !foundUser {
t.Error("Force must not remove the user's own hook")
}
}