package app import ( "context" "errors" "testing" "time" "supply-intelligence/internal/domain" "supply-intelligence/internal/repository" ) type failingRepository struct { repository.Repository err error } func (r *failingRepository) UpsertSupplyPackage(ctx context.Context, pkg domain.SupplyPackage) error { return r.err } func TestNewApplication(t *testing.T) { application := New() if application == nil { t.Fatalf("expected application") } if application.Repo == nil { t.Fatalf("expected repository") } if application.ProbeService == nil { t.Fatalf("expected probe service") } if application.PublishService == nil { t.Fatalf("expected publish service") } if application.DiscoveryService == nil { t.Fatalf("expected discovery service") } if application.GatewayConsumerService == nil { t.Fatalf("expected gateway consumer service") } if application.GatewayPoller == nil { t.Fatalf("expected gateway poller") } if application.GatewayRuntime == nil { t.Fatalf("expected gateway runtime") } if application.Server == nil { t.Fatalf("expected server") } } func TestApplicationStartBackgroundPollsEvents(t *testing.T) { application := New() application.Repo.AppendPackageEvent(context.Background(), domain.PackageChangeEvent{ EventID: "evt-app-runtime-1", EventType: "supply_package_published", PackageID: 11, Platform: "openai", Model: "gpt-4.1-mini", OccurredAt: time.Unix(2, 0).UTC(), Version: 1, GatewaySyncStatus: domain.GatewaySyncStatusPending, }) ctx, cancel := context.WithCancel(context.Background()) defer cancel() application.StartBackground(ctx) defer application.StopBackground() deadline := time.Now().Add(1500 * time.Millisecond) for time.Now().Before(deadline) { items, _ := application.Repo.ListPackageEventsAfter(context.Background(), "") if len(items) == 1 && items[0].GatewaySyncStatus == domain.GatewaySyncStatusApplied { return } time.Sleep(20 * time.Millisecond) } items, _ := application.Repo.ListPackageEventsAfter(context.Background(), "") t.Fatalf("expected background runtime to apply event, got %+v", items) } func TestApplicationStartBackgroundHandlesNilRuntime(t *testing.T) { application := New() application.GatewayRuntime = nil application.StartBackground(context.Background()) if application.GatewayRuntime != nil { t.Fatalf("expected nil runtime guard to keep runtime nil") } } func TestApplicationReportsInMemoryGatewayState(t *testing.T) { application := New() if !application.IsInMemoryGatewayState() { t.Fatalf("expected in-memory gateway state") } } func TestAdmissionPackageAdapterReturnsUpsertError(t *testing.T) { repoErr := errors.New("insert failed") adapter := &admissionPackageAdapter{repo: &failingRepository{Repository: repository.NewMemoryRepository(), err: repoErr}} packageID, err := adapter.UpsertDraftPackage(context.Background(), "openai", "gpt-4.1-mini", "admission") if !errors.Is(err, repoErr) { t.Fatalf("expected repo error, got packageID=%d err=%v", packageID, err) } if packageID != 0 { t.Fatalf("expected zero package id on error, got %d", packageID) } }