| 1 | package analytics |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "testing" |
| 6 | "time" |
| 7 | |
| 8 | "github.com/carlosframework/platform/internal/release" |
| 9 | ) |
| 10 | |
| 11 | func TestReadRangeMergesBoxesAndDays(t *testing.T) { |
| 12 | ctx := context.Background() |
| 13 | s := release.NewDirStore(t.TempDir()) |
| 14 | d1 := delta("box-a", 1, 10) |
| 15 | d2 := delta("box-b", 1, 5) |
| 16 | d3 := delta("box-a", 2, 7) |
| 17 | d3.Date = "2026-09-08" |
| 18 | d3.Restarted = true |
| 19 | for _, d := range []Delta{d1, d2, d3} { |
| 20 | if err := UpsertDay(ctx, s, "bab", "web", d); err != nil { |
| 21 | t.Fatal(err) |
| 22 | } |
| 23 | } |
| 24 | from := time.Date(2026, 9, 7, 0, 0, 0, 0, time.UTC) |
| 25 | sum, err := ReadRange(ctx, s, "bab", "web", from, from.Add(24*time.Hour)) |
| 26 | if err != nil { |
| 27 | t.Fatal(err) |
| 28 | } |
| 29 | if len(sum.Days) != 2 || sum.Days[0].Date != "2026-09-07" || sum.Days[0].PV != 15 || sum.Days[1].PV != 7 { |
| 30 | t.Fatalf("days = %+v", sum.Days) |
| 31 | } |
| 32 | if sum.PV != 22 || sum.Pages["/"] != 22 || sum.Days[0].Hours[9] != 15 || !sum.Days[1].Restarted || sum.Days[0].Restarted { |
| 33 | t.Fatalf("summary = %+v", sum) |
| 34 | } |
| 35 | if sum.Visitors != sum.Days[0].Visitors+sum.Days[1].Visitors || sum.Days[0].Visitors < 1 { |
| 36 | t.Fatalf("visitors must be daily sums: %+v", sum) |
| 37 | } |
| 38 | if len(sum.Boxes) != 2 { |
| 39 | t.Fatalf("boxes = %v", sum.Boxes) |
| 40 | } |
| 41 | // An app with no day files reads as an empty summary, not an error. |
| 42 | empty, err := ReadRange(ctx, s, "bab", "nothing", from, from) |
| 43 | if err != nil || empty.PV != 0 || len(empty.Days) != 1 { |
| 44 | t.Fatalf("empty = %+v %v", empty, err) |
| 45 | } |
| 46 | } |
| 47 | |