ProofedMesh/services/admin-api/internal/store/memory_test.go
CTO Agent 65514559dc
Some checks failed
validate / Rego (opa fmt + opa test) (push) Successful in 12s
validate / JSON Schema (ajv) (push) Has been cancelled
services: add admin-api Go service (per-diem rates CRUD, in-memory + Postgres stub store, HTML templates, 13/13 go tests pass, go vet clean)
2026-10-25 17:28:14 +00:00

138 lines
3.7 KiB
Go

package store
import (
"context"
"errors"
"testing"
"time"
"basicstack.de/proofedmesh/services/admin-api/internal/model"
)
func d(s string) time.Time {
t, err := time.Parse("2006-01-02", s)
if err != nil {
panic(err)
}
return t
}
func rateDE(validFrom, validTo string) model.NewRateInput {
in := model.NewRateInput{
Country: "DE", Currency: "EUR",
FullDay: "28.00", PartialDayMin8h: "14.00",
ArrivalDay: "14.00", DepartureDay: "14.00",
ValidFrom: d(validFrom),
SourceRegulation: "test",
}
if validTo != "" {
t := d(validTo)
in.ValidTo = &t
}
return in
}
func TestMemory_CreateAndGet(t *testing.T) {
m := NewMemory()
ctx := context.Background()
r, err := m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
if err != nil {
t.Fatalf("create: %v", err)
}
if r.RateID != "PDR-1" {
t.Errorf("expected PDR-1, got %s", r.RateID)
}
got, err := m.Get(ctx, "PDR-1")
if err != nil {
t.Fatalf("get: %v", err)
}
if got.FullDay != "28.00" {
t.Errorf("roundtrip full_day: %s", got.FullDay)
}
}
func TestMemory_Get_NotFound(t *testing.T) {
m := NewMemory()
_, err := m.Get(context.Background(), "PDR-999")
if !errors.Is(err, ErrNotFound) {
t.Fatalf("expected ErrNotFound, got %v", err)
}
}
func TestMemory_OverlapRejected(t *testing.T) {
m := NewMemory()
ctx := context.Background()
if _, err := m.Create(ctx, rateDE("2026-01-01", "2026-12-31"), "admin", time.Now()); err != nil {
t.Fatalf("first create: %v", err)
}
// Overlap on the last day of 2026
_, err := m.Create(ctx, rateDE("2026-12-31", ""), "admin", time.Now())
if !errors.Is(err, ErrOverlap) {
t.Fatalf("expected ErrOverlap, got %v", err)
}
}
func TestMemory_RetireChangesValidTo(t *testing.T) {
m := NewMemory()
ctx := context.Background()
r, _ := m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
updated, err := m.Retire(ctx, r.RateID, d("2026-06-30"), "admin2", time.Now())
if err != nil {
t.Fatalf("retire: %v", err)
}
if updated.ValidTo == nil || !updated.ValidTo.Equal(d("2026-06-30")) {
t.Errorf("valid_to not set to 2026-06-30: %v", updated.ValidTo)
}
}
func TestMemory_Retire_BeforeValidFrom_Rejected(t *testing.T) {
m := NewMemory()
ctx := context.Background()
r, _ := m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
_, err := m.Retire(ctx, r.RateID, d("2025-12-01"), "admin2", time.Now())
if err == nil {
t.Fatal("expected error for valid_to before valid_from")
}
}
func TestMemory_AttachAttestation(t *testing.T) {
m := NewMemory()
ctx := context.Background()
r, _ := m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
err := m.AttachAttestation(ctx, r.RateID, "sha256:0000000000000000000000000000000000000000000000000000000000000001")
if err != nil {
t.Fatalf("attach: %v", err)
}
got, _ := m.Get(ctx, r.RateID)
if got.RateChangeAttestationRef == nil {
t.Fatal("expected attestation ref to be set")
}
}
func TestMemory_AttachAttestation_BadRef_Rejected(t *testing.T) {
m := NewMemory()
ctx := context.Background()
r, _ := m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
err := m.AttachAttestation(ctx, r.RateID, "not-a-hash")
if err == nil {
t.Fatal("expected error for malformed attestation ref")
}
}
func TestMemory_List_FilterByCountry(t *testing.T) {
m := NewMemory()
ctx := context.Background()
_, _ = m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
fr := rateDE("2026-01-01", "")
fr.Country = "FR"
_, _ = m.Create(ctx, fr, "admin", time.Now())
all, _ := m.List(ctx, ListFilter{})
if len(all) != 2 {
t.Fatalf("expected 2 total, got %d", len(all))
}
de, _ := m.List(ctx, ListFilter{Country: "DE"})
if len(de) != 1 || de[0].Country != "DE" {
t.Fatalf("country filter failed: %+v", de)
}
}