package analytics import ( "context" "errors" "testing" "time" "github.com/carlosframework/platform/internal/applog" "github.com/carlosframework/platform/internal/release" ) // TestAnalyticsKeysRefuseEmptyApp: the day-file builders refuse an empty // app, account, box or date, and UpsertDay refuses before touching the // store, so nothing lands under apps///analytics/. func TestAnalyticsKeysRefuseEmptyApp(t *testing.T) { for _, c := range []struct{ acct, app, box, date string }{ {"bab", "", "box-a", "2026-10-16"}, {"", "web", "box-a", "2026-10-16"}, {"bab", "web", "", "2026-10-16"}, {"bab", "web", "box-a", ""}, {"bab", "web", "box-a", "2026/10/16"}, } { if k, err := DayKey(c.acct, c.app, c.box, c.date); !errors.Is(err, applog.ErrBadKeySegment) || k != "" { t.Errorf("DayKey%+v = (%q, %v)", c, k, err) } } if k, err := Prefix("bab", ""); !errors.Is(err, applog.ErrBadKeySegment) || k != "" { t.Fatalf("Prefix = (%q, %v)", k, err) } if k, err := BoxPrefix("bab", "", "box-a"); !errors.Is(err, applog.ErrBadKeySegment) || k != "" { t.Fatalf("BoxPrefix = (%q, %v)", k, err) } ctx := context.Background() s := release.NewDirStore(t.TempDir()) err := UpsertDay(ctx, s, "bab", "", Delta{Box: "box-a", Date: "2026-10-16", Seq: 1}) if !errors.Is(err, applog.ErrBadKeySegment) { t.Fatalf("UpsertDay = %v", err) } if keys, _ := s.List(ctx, "apps/"); len(keys) != 0 { t.Fatalf("UpsertDay wrote %v", keys) } if _, err := ReadRange(ctx, s, "bab", "", time.Now(), time.Now()); !errors.Is(err, applog.ErrBadKeySegment) { t.Fatalf("ReadRange = %v", err) } if got := must(t)(BoxPrefix("bab", "web", "box-a")); got != "apps/bab/web/analytics/box-a/days/" { t.Fatalf("valid BoxPrefix moved: %q", got) } }