Integration tests for the side-effect-committed caching policy on api/v1/send and /api/v1/agents/{email}/messages/{id}/reply. The standard handlers don't have a natural code path to "5xx after SES already accepted" — that scenario is a panic recovery, late context cancel, or a follow-up DB write th
(t *testing.T)
| 32 | // the API value directly (rather than the bound httptest.Server) so a |
| 33 | // test can register its own routes against the same store + guard. |
| 34 | func newAPIWithIdempotency(t *testing.T) (*agent.API, *identity.Store, string) { |
| 35 | t.Helper() |
| 36 | pool := testutil.TestDB(t) |
| 37 | store := identity.NewStore(pool) |
| 38 | smtpRelay := outbound.NewSMTPRelay(&config.OutboundSMTPConfig{}) |
| 39 | sender := outbound.NewSender(smtpRelay, "test.e2a.dev") |
| 40 | noopUsage := usage.NewNoopUsageTracker() |
| 41 | api := agent.NewAPI(store, sender, smtpRelay, nil, noopUsage, "e2a.dev", "test.e2a.dev", "agents.e2a.dev", "", false) |
| 42 | api.SetIdempotencyStore(idempotency.NewStore(pool)) |
| 43 | |
| 44 | ctx := context.Background() |
| 45 | user, err := store.CreateOrGetUser(ctx, "guard-sideeffect-owner@example.com", "Owner", "google-guard-sideeffect-"+t.Name()) |
| 46 | if err != nil { |
| 47 | t.Fatalf("CreateOrGetUser: %v", err) |
| 48 | } |
| 49 | key, err := store.CreateAPIKey(ctx, user.ID, "guard-sideeffect-key", nil) |
| 50 | if err != nil { |
| 51 | t.Fatalf("CreateAPIKey: %v", err) |
| 52 | } |
| 53 | return api, store, key.PlaintextKey |
| 54 | } |
| 55 | |
| 56 | func TestIdempotencyGuard_5xxAfterSideEffect_CachesResponse(t *testing.T) { |
| 57 | api, _, apiKey := newAPIWithIdempotency(t) |
no test coverage detected