package calfeed import ( "encoding/json" "testing" "github.com/lukaszkasprzak/lectio/internal/config" ) func TestJSONShape(t *testing.T) { days := []DayView{{ Date: "2026-01-06", Season: "time-after-epiphany", Week: 1, Weekday: "Tuesday", Colour: "white", Observed: CelView{Slug: "ef-epiphany", Name: "The Epiphany of the Lord", Rank: "class-1", Class: 1}, Others: []CelView{}, Cycles: Cycles{}, Readings: []ReadingView{{Part: "gospel", Citation: "Matt 2:1-12"}}, }} b, err := JSON("old", days) if err != nil { t.Fatal(err) } var out struct { Schema string `json:"schema"` Form string `json:"form"` Days []DayView `json:"days"` } if err := json.Unmarshal(b, &out); err != nil { t.Fatal(err) } if out.Schema != "lectio.calendar/1" || out.Form != "old" || len(out.Days) != 1 { t.Fatalf("bad envelope: %s", b) } if out.Days[0].Observed.Name != "The Epiphany of the Lord" { t.Fatalf("bad day: %s", b) } } // TestJSONCarriesSourceOffer pins the AGPL-3.0 ยง13 offer into the envelope. // A consumer of /api/calendar.json may never load a single HTML page, so the // footer link does not reach them -- the feed itself has to say where the // source is. Dropping these fields is a licence-compliance regression, not a // cosmetic one, which is why it is asserted rather than left to review. func TestJSONCarriesSourceOffer(t *testing.T) { b, err := JSON("new", nil) if err != nil { t.Fatal(err) } var out struct { Source string `json:"source"` License string `json:"license"` } if err := json.Unmarshal(b, &out); err != nil { t.Fatal(err) } if out.Source != config.SourceURL { t.Errorf("source = %q, want %q", out.Source, config.SourceURL) } if out.License != config.License { t.Errorf("license = %q, want %q", out.License, config.License) } }