104 lines
2.9 KiB
Go
104 lines
2.9 KiB
Go
package github
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// TestDisableIssueWatchWithError_StampsCauseAndDisables pins the self-heal
|
|
// contract for github_issue_watches: orphaned watcher is flipped to
|
|
// enabled=0 with a human-readable LastError + LastErrorAt timestamp.
|
|
func TestDisableIssueWatchWithError_StampsCauseAndDisables(t *testing.T) {
|
|
store := newTestStore(t)
|
|
ctx := context.Background()
|
|
|
|
iw := &IssueWatch{
|
|
WorkspaceID: "ws-1",
|
|
WorkflowID: "wf-1",
|
|
WorkflowStepID: "step-1",
|
|
AgentProfileID: "deleted-profile",
|
|
ExecutorProfileID: "exec-1",
|
|
Enabled: true,
|
|
}
|
|
if err := store.CreateIssueWatch(ctx, iw); err != nil {
|
|
t.Fatalf("create: %v", err)
|
|
}
|
|
|
|
const cause = `agent profile "Removed Kilo" (deleted-profile) was removed`
|
|
// Widen the window by 1s on each side to absorb SQLite second-precision
|
|
// timestamp rounding.
|
|
before := time.Now().UTC().Add(-time.Second)
|
|
if err := store.DisableIssueWatchWithError(ctx, iw.ID, cause); err != nil {
|
|
t.Fatalf("disable: %v", err)
|
|
}
|
|
after := time.Now().UTC().Add(time.Second)
|
|
|
|
got, err := store.GetIssueWatch(ctx, iw.ID)
|
|
if err != nil {
|
|
t.Fatalf("get: %v", err)
|
|
}
|
|
if got == nil {
|
|
t.Fatal("expected row, got nil")
|
|
}
|
|
if got.Enabled {
|
|
t.Error("Enabled should be false after self-heal")
|
|
}
|
|
if got.LastError != cause {
|
|
t.Errorf("LastError = %q, want %q", got.LastError, cause)
|
|
}
|
|
if got.LastErrorAt == nil {
|
|
t.Fatal("LastErrorAt should be set")
|
|
}
|
|
if got.LastErrorAt.Before(before) || got.LastErrorAt.After(after) {
|
|
t.Errorf("LastErrorAt %v outside [%v, %v]", got.LastErrorAt, before, after)
|
|
}
|
|
}
|
|
|
|
// TestDisableReviewWatchWithError_StampsCauseAndDisables mirrors the issue
|
|
// test for review watches.
|
|
func TestDisableReviewWatchWithError_StampsCauseAndDisables(t *testing.T) {
|
|
store := newTestStore(t)
|
|
ctx := context.Background()
|
|
|
|
rw := &ReviewWatch{
|
|
WorkspaceID: "ws-1",
|
|
WorkflowID: "wf-1",
|
|
WorkflowStepID: "step-1",
|
|
AgentProfileID: "deleted-profile",
|
|
ExecutorProfileID: "exec-1",
|
|
ReviewScope: "user_and_teams",
|
|
Enabled: true,
|
|
}
|
|
if err := store.CreateReviewWatch(ctx, rw); err != nil {
|
|
t.Fatalf("create: %v", err)
|
|
}
|
|
|
|
const cause = `agent profile "Removed Opencode" (deleted-profile) was removed`
|
|
before := time.Now().UTC().Add(-time.Second)
|
|
if err := store.DisableReviewWatchWithError(ctx, rw.ID, cause); err != nil {
|
|
t.Fatalf("disable: %v", err)
|
|
}
|
|
after := time.Now().UTC().Add(time.Second)
|
|
|
|
got, err := store.GetReviewWatch(ctx, rw.ID)
|
|
if err != nil {
|
|
t.Fatalf("get: %v", err)
|
|
}
|
|
if got == nil {
|
|
t.Fatal("expected row, got nil")
|
|
}
|
|
if got.Enabled {
|
|
t.Error("Enabled should be false after self-heal")
|
|
}
|
|
if got.LastError != cause {
|
|
t.Errorf("LastError = %q, want %q", got.LastError, cause)
|
|
}
|
|
if got.LastErrorAt == nil {
|
|
t.Fatal("LastErrorAt should be set")
|
|
}
|
|
if got.LastErrorAt.Before(before) || got.LastErrorAt.After(after) {
|
|
t.Errorf("LastErrorAt %v outside [%v, %v]", got.LastErrorAt, before, after)
|
|
}
|
|
}
|