88 "errors"
99 "os"
1010 "path/filepath"
11+ "slices"
12+ "sort"
1113 "strings"
1214 "sync"
1315 "testing"
@@ -18,6 +20,15 @@ import (
1820 _ "modernc.org/sqlite"
1921)
2022
23+ func sortedJSONKeys (payload map [string ]any ) []string {
24+ keys := make ([]string , 0 , len (payload ))
25+ for key := range payload {
26+ keys = append (keys , key )
27+ }
28+ sort .Strings (keys )
29+ return keys
30+ }
31+
2132func TestCLIHelp (t * testing.T ) {
2233 var stdout bytes.Buffer
2334 var stderr bytes.Buffer
@@ -179,21 +190,19 @@ func TestStatusJSONContractContainsStableTopLevelFields(t *testing.T) {
179190 if err := json .Unmarshal (stdout .Bytes (), & payload ); err != nil {
180191 t .Fatalf ("Unmarshal: %v" , err )
181192 }
182- required := []string {
183- "repository_root" ,
184- "state_path" ,
185- "current_worktree" ,
193+ wantKeys := []string {
194+ "counts" ,
186195 "current_branch" ,
196+ "current_worktree" ,
187197 "protected_branch" ,
188198 "protected_branch_sha" ,
189199 "protected_upstream" ,
190- "counts" ,
191200 "recent_events" ,
201+ "repository_root" ,
202+ "state_path" ,
192203 }
193- for _ , key := range required {
194- if _ , ok := payload [key ]; ! ok {
195- t .Fatalf ("expected status json key %q in %+v" , key , payload )
196- }
204+ if gotKeys := sortedJSONKeys (payload ); ! slices .Equal (gotKeys , wantKeys ) {
205+ t .Fatalf ("expected exact status json keys %v, got %v" , wantKeys , gotKeys )
197206 }
198207}
199208
@@ -227,17 +236,11 @@ func TestEventsLifecycleJSONContractContainsStableFields(t *testing.T) {
227236 if err := json .Unmarshal ([]byte (line ), & payload ); err != nil {
228237 t .Fatalf ("Unmarshal line %q: %v" , line , err )
229238 }
230- for _ , key := range []string {"event" , "repository_root" , "timestamp" } {
231- if _ , ok := payload [key ]; ! ok {
232- t .Fatalf ("expected lifecycle key %q in %+v" , key , payload )
233- }
234- }
235239 if payload ["event" ] == "integrated" {
236240 foundIntegrated = true
237- for _ , key := range []string {"branch" , "sha" , "submission_id" } {
238- if _ , ok := payload [key ]; ! ok {
239- t .Fatalf ("expected integrated lifecycle key %q in %+v" , key , payload )
240- }
241+ wantKeys := []string {"branch" , "event" , "repository_root" , "sha" , "status" , "submission_id" , "timestamp" }
242+ if gotKeys := sortedJSONKeys (payload ); ! slices .Equal (gotKeys , wantKeys ) {
243+ t .Fatalf ("expected integrated lifecycle keys %v, got %v" , wantKeys , gotKeys )
241244 }
242245 }
243246 }
@@ -265,16 +268,20 @@ func TestDaemonJSONLogContractContainsStableFields(t *testing.T) {
265268 if len (lines ) < 2 {
266269 t .Fatalf ("expected daemon json log lines, got %q" , stdout .String ())
267270 }
268- for _ , line := range lines {
269- var payload map [string ]any
270- if err := json .Unmarshal ([]byte (line ), & payload ); err != nil {
271- t .Fatalf ("Unmarshal line %q: %v" , line , err )
272- }
273- for _ , key := range []string {"level" , "event" , "repo" , "timestamp" } {
274- if _ , ok := payload [key ]; ! ok {
275- t .Fatalf ("expected daemon log key %q in %+v" , key , payload )
276- }
277- }
271+ var first map [string ]any
272+ if err := json .Unmarshal ([]byte (lines [0 ]), & first ); err != nil {
273+ t .Fatalf ("Unmarshal first line %q: %v" , lines [0 ], err )
274+ }
275+ if gotKeys := sortedJSONKeys (first ); ! slices .Equal (gotKeys , []string {"event" , "level" , "message" , "repo" , "timestamp" }) {
276+ t .Fatalf ("unexpected daemon started json keys: %v" , gotKeys )
277+ }
278+
279+ var last map [string ]any
280+ if err := json .Unmarshal ([]byte (lines [len (lines )- 1 ]), & last ); err != nil {
281+ t .Fatalf ("Unmarshal last line %q: %v" , lines [len (lines )- 1 ], err )
282+ }
283+ if gotKeys := sortedJSONKeys (last ); ! slices .Equal (gotKeys , []string {"cycle" , "event" , "level" , "message" , "repo" , "timestamp" }) {
284+ t .Fatalf ("unexpected daemon terminal json keys: %v" , gotKeys )
278285 }
279286}
280287
0 commit comments