chore: sync local project state
This commit is contained in:
229
internal/httpapi/admission_state_api_test.go
Normal file
229
internal/httpapi/admission_state_api_test.go
Normal file
@@ -0,0 +1,229 @@
|
||||
package httpapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"supply-intelligence/internal/admission"
|
||||
"supply-intelligence/internal/discovery"
|
||||
"supply-intelligence/internal/domain"
|
||||
"supply-intelligence/internal/gatewayconsumer"
|
||||
"supply-intelligence/internal/probe"
|
||||
"supply-intelligence/internal/publish"
|
||||
"supply-intelligence/internal/repository"
|
||||
)
|
||||
|
||||
func TestAdmissionStateEndpointReturnsCurrentCandidateAndPackageTruth(t *testing.T) {
|
||||
repo := repository.NewMemoryRepository()
|
||||
repo.UpsertDiscoveryCandidateContext(nil, domain.DiscoveryCandidate{
|
||||
CandidateID: "cand-1",
|
||||
AccountID: 301,
|
||||
Platform: "openai",
|
||||
Model: "gpt-4.1-mini",
|
||||
Source: "manual_seed",
|
||||
Status: domain.DiscoveryCandidateStatusDiscovered,
|
||||
ReasonCode: "earlier_state",
|
||||
DiscoveredAt: time.Unix(90, 0).UTC(),
|
||||
UpdatedAt: time.Unix(90, 0).UTC(),
|
||||
Version: 1,
|
||||
})
|
||||
repo.UpsertDiscoveryCandidateContext(nil, domain.DiscoveryCandidate{
|
||||
CandidateID: "cand-2",
|
||||
AccountID: 301,
|
||||
Platform: "openai",
|
||||
Model: "gpt-4.1-mini",
|
||||
Source: "manual_seed",
|
||||
Status: domain.DiscoveryCandidateStatusTestPassed,
|
||||
ReasonCode: "ready_for_package",
|
||||
DiscoveredAt: time.Unix(100, 0).UTC(),
|
||||
UpdatedAt: time.Unix(110, 0).UTC(),
|
||||
Version: 2,
|
||||
})
|
||||
repo.UpsertSupplyPackage(nil, domain.SupplyPackage{
|
||||
PackageID: 9,
|
||||
Platform: "openai",
|
||||
Model: "gpt-4.1-mini",
|
||||
Status: "draft",
|
||||
Source: "manual_seed",
|
||||
})
|
||||
_, _ = repo.AppendPackageEventContext(nil, domain.PackageChangeEvent{
|
||||
EventID: "evt-other-newer",
|
||||
EventType: publish.PackagePublishedEventType,
|
||||
PackageID: 10,
|
||||
Platform: "openai",
|
||||
Model: "gpt-4.1",
|
||||
OccurredAt: time.Unix(130, 0).UTC(),
|
||||
Version: 1,
|
||||
GatewaySyncStatus: domain.GatewaySyncStatusFailed,
|
||||
})
|
||||
_, _ = repo.AppendPackageEventContext(nil, domain.PackageChangeEvent{
|
||||
EventID: "evt-old",
|
||||
EventType: publish.PackagePublishedEventType,
|
||||
PackageID: 9,
|
||||
Platform: "openai",
|
||||
Model: "gpt-4.1-mini",
|
||||
OccurredAt: time.Unix(100, 0).UTC(),
|
||||
Version: 1,
|
||||
GatewaySyncStatus: domain.GatewaySyncStatusPending,
|
||||
})
|
||||
_, _ = repo.AppendPackageEventContext(nil, domain.PackageChangeEvent{
|
||||
EventID: "evt-latest",
|
||||
EventType: publish.PackagePublishedEventType,
|
||||
PackageID: 9,
|
||||
Platform: "openai",
|
||||
Model: "gpt-4.1-mini",
|
||||
OccurredAt: time.Unix(120, 0).UTC(),
|
||||
Version: 2,
|
||||
GatewaySyncStatus: domain.GatewaySyncStatusApplied,
|
||||
})
|
||||
server := NewServer(repo, probe.NewService(repo), publish.NewService(repo), gatewayconsumer.NewService(repo), nil, discovery.NewService(repo), admission.NewService(nil, nil, []admission.TestSuite{}, nil, nil), nil, nil)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/internal/supply-intelligence/models/openai/gpt-4.1-mini/admission-state", nil)
|
||||
rr := httptest.NewRecorder()
|
||||
server.Routes().ServeHTTP(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("expected implemented admission-state endpoint, got status=%d body=%s", rr.Code, rr.Body.String())
|
||||
}
|
||||
|
||||
var body struct {
|
||||
Platform string `json:"platform"`
|
||||
Model string `json:"model"`
|
||||
Candidate *domain.DiscoveryCandidate `json:"candidate"`
|
||||
Package *domain.SupplyPackage `json:"package"`
|
||||
GatewaySyncStatus domain.GatewaySyncStatus `json:"gateway_sync_status"`
|
||||
LastEvent *domain.PackageChangeEvent `json:"last_event"`
|
||||
}
|
||||
if err := json.NewDecoder(rr.Body).Decode(&body); err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if body.Candidate == nil || body.Candidate.CandidateID != "cand-2" || body.Candidate.Status != domain.DiscoveryCandidateStatusTestPassed {
|
||||
t.Fatalf("expected latest candidate truth, got %+v", body.Candidate)
|
||||
}
|
||||
if body.Package == nil || body.Package.Status != "draft" {
|
||||
t.Fatalf("expected package truth, got %+v", body.Package)
|
||||
}
|
||||
if body.LastEvent == nil || body.LastEvent.EventID != "evt-latest" {
|
||||
t.Fatalf("expected latest matching event truth, got %+v", body.LastEvent)
|
||||
}
|
||||
if body.GatewaySyncStatus != domain.GatewaySyncStatusApplied {
|
||||
t.Fatalf("expected gateway sync status from latest matching event, got %q", body.GatewaySyncStatus)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdmissionStateEndpointReflectsPublishTransitionAndAck(t *testing.T) {
|
||||
repo := repository.NewMemoryRepository()
|
||||
repo.UpsertDiscoveryCandidateContext(nil, domain.DiscoveryCandidate{
|
||||
CandidateID: "cand-publish",
|
||||
AccountID: 401,
|
||||
Platform: "openai",
|
||||
Model: "gpt-4.1-mini",
|
||||
Source: "manual_seed",
|
||||
Status: domain.DiscoveryCandidateStatusTestPassed,
|
||||
DiscoveredAt: time.Unix(100, 0).UTC(),
|
||||
UpdatedAt: time.Unix(110, 0).UTC(),
|
||||
Version: 2,
|
||||
})
|
||||
repo.UpsertSupplyPackage(nil, domain.SupplyPackage{
|
||||
PackageID: 21,
|
||||
Platform: "openai",
|
||||
Model: "gpt-4.1-mini",
|
||||
Status: "draft",
|
||||
Source: "manual_seed",
|
||||
UpdatedAt: time.Unix(110, 0).UTC(),
|
||||
Version: 1,
|
||||
})
|
||||
publishService := publish.NewService(repo)
|
||||
if _, err := publishService.PublishDraft(nil, publish.PublishDraftInput{EventID: "evt-publish", Platform: "openai", Model: "gpt-4.1-mini", OccurredAt: time.Unix(120, 0).UTC()}); err != nil {
|
||||
t.Fatalf("publish draft: %v", err)
|
||||
}
|
||||
server := NewServer(repo, probe.NewService(repo), publishService, gatewayconsumer.NewService(repo), nil, discovery.NewService(repo), admission.NewService(nil, nil, []admission.TestSuite{}, nil, nil), nil, nil)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/internal/supply-intelligence/models/openai/gpt-4.1-mini/admission-state", nil)
|
||||
rr := httptest.NewRecorder()
|
||||
server.Routes().ServeHTTP(rr, req)
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("expected status 200, got=%d body=%s", rr.Code, rr.Body.String())
|
||||
}
|
||||
var body struct {
|
||||
Candidate *domain.DiscoveryCandidate `json:"candidate"`
|
||||
Package *domain.SupplyPackage `json:"package"`
|
||||
GatewaySyncStatus domain.GatewaySyncStatus `json:"gateway_sync_status"`
|
||||
}
|
||||
if err := json.NewDecoder(rr.Body).Decode(&body); err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if body.Candidate == nil || body.Candidate.Status != domain.DiscoveryCandidateStatusPublished {
|
||||
t.Fatalf("expected published candidate, got %+v", body.Candidate)
|
||||
}
|
||||
if body.Package == nil || body.Package.Status != "active" {
|
||||
t.Fatalf("expected active package, got %+v", body.Package)
|
||||
}
|
||||
if body.GatewaySyncStatus != domain.GatewaySyncStatusPending {
|
||||
t.Fatalf("expected pending sync status, got %q", body.GatewaySyncStatus)
|
||||
}
|
||||
|
||||
_, err := repo.AckPackageEvent(nil, "evt-publish", "gateway", domain.GatewayAckResultApplied, "ok", time.Unix(130, 0).UTC())
|
||||
if err != nil {
|
||||
t.Fatalf("ack event: %v", err)
|
||||
}
|
||||
ackedReq := httptest.NewRequest(http.MethodGet, "/internal/supply-intelligence/models/openai/gpt-4.1-mini/admission-state", nil)
|
||||
ackedRR := httptest.NewRecorder()
|
||||
server.Routes().ServeHTTP(ackedRR, ackedReq)
|
||||
var ackedBody struct {
|
||||
GatewaySyncStatus domain.GatewaySyncStatus `json:"gateway_sync_status"`
|
||||
}
|
||||
if err := json.NewDecoder(ackedRR.Body).Decode(&ackedBody); err != nil {
|
||||
t.Fatalf("decode acked response: %v", err)
|
||||
}
|
||||
if ackedBody.GatewaySyncStatus != domain.GatewaySyncStatusApplied {
|
||||
t.Fatalf("expected applied sync status after ack, got %q", ackedBody.GatewaySyncStatus)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdmissionStateEndpointOmitsForeignLatestEvent(t *testing.T) {
|
||||
repo := repository.NewMemoryRepository()
|
||||
repo.UpsertSupplyPackage(nil, domain.SupplyPackage{
|
||||
PackageID: 9,
|
||||
Platform: "openai",
|
||||
Model: "gpt-4.1-mini",
|
||||
Status: "draft",
|
||||
Source: "manual_seed",
|
||||
})
|
||||
_, _ = repo.AppendPackageEventContext(nil, domain.PackageChangeEvent{
|
||||
EventID: "evt-only-other-model",
|
||||
EventType: publish.PackagePublishedEventType,
|
||||
PackageID: 10,
|
||||
Platform: "openai",
|
||||
Model: "gpt-4.1",
|
||||
OccurredAt: time.Unix(130, 0).UTC(),
|
||||
Version: 1,
|
||||
GatewaySyncStatus: domain.GatewaySyncStatusFailed,
|
||||
})
|
||||
server := NewServer(repo, probe.NewService(repo), publish.NewService(repo), gatewayconsumer.NewService(repo), nil, discovery.NewService(repo), admission.NewService(nil, nil, []admission.TestSuite{}, nil, nil), nil, nil)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/internal/supply-intelligence/models/openai/gpt-4.1-mini/admission-state", nil)
|
||||
rr := httptest.NewRecorder()
|
||||
server.Routes().ServeHTTP(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("expected implemented admission-state endpoint, got status=%d body=%s", rr.Code, rr.Body.String())
|
||||
}
|
||||
|
||||
var body struct {
|
||||
GatewaySyncStatus domain.GatewaySyncStatus `json:"gateway_sync_status"`
|
||||
LastEvent *domain.PackageChangeEvent `json:"last_event"`
|
||||
}
|
||||
if err := json.NewDecoder(rr.Body).Decode(&body); err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if body.LastEvent != nil {
|
||||
t.Fatalf("expected no last event for unrelated latest event, got %+v", body.LastEvent)
|
||||
}
|
||||
if body.GatewaySyncStatus != "" {
|
||||
t.Fatalf("expected empty gateway sync status without matching event, got %q", body.GatewaySyncStatus)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user