package contracts import ( "encoding/json" "testing" ) func TestTaskScheduleOptionalFieldsSchema(t *testing.T) { schema, err := CompileCurrent("http-task-detail.schema.json") if err != nil { t.Fatal(err) } for _, mode := range []string{"asr", "full"} { fixture, err := Files.ReadFile("schema/examples/config-read-task-" + mode + ".json") if err != nil { t.Fatal(err) } for _, tc := range []struct { name string omit []string set map[string]any valid bool }{ {name: "explicit null end and empty exclusions", valid: true}, {name: "omitted end", omit: []string{"ends_at"}, valid: true}, {name: "omitted exclusions", omit: []string{"excluded_dates"}, valid: true}, {name: "both omitted", omit: []string{"ends_at", "excluded_dates"}, valid: true}, {name: "explicit end and exclusions", set: map[string]any{"ends_at": "2026-12-31T20:00:00+08:00", "excluded_dates": []any{"2026-10-01"}}, valid: true}, {name: "missing start", omit: []string{"starts_at"}}, {name: "missing time zone", omit: []string{"time_zone"}}, {name: "missing weekly windows", omit: []string{"weekly_windows"}}, {name: "null exclusions", set: map[string]any{"excluded_dates": nil}}, {name: "wrong exclusions type", set: map[string]any{"excluded_dates": "2026-10-01"}}, {name: "invalid excluded date", set: map[string]any{"excluded_dates": []any{"2026-02-30"}}}, {name: "duplicate exclusions", set: map[string]any{"excluded_dates": []any{"2026-10-01", "2026-10-01"}}}, {name: "invalid end", set: map[string]any{"ends_at": "not-a-time"}}, {name: "empty end", set: map[string]any{"ends_at": ""}}, {name: "numeric end", set: map[string]any{"ends_at": 123}}, {name: "unknown schedule property", set: map[string]any{"unknown": true}}, } { t.Run(mode+"/"+tc.name, func(t *testing.T) { var doc map[string]any if err := json.Unmarshal(fixture, &doc); err != nil { t.Fatal(err) } schedule := doc["schedule"].(map[string]any) for _, field := range tc.omit { delete(schedule, field) } for field, value := range tc.set { schedule[field] = value } if err := schema.Validate(doc); (err == nil) != tc.valid { t.Fatalf("valid=%t, want %t: %v", err == nil, tc.valid, err) } }) } } }