1import * as AWS from "@/AWS";
2import { EventSourceMapping } from "@/AWS/Lambda";
3import * as Provider from "@/Provider";
4import * as Test from "@/Test/Alchemy";
5import * as Lambda from "@distilled.cloud/aws/lambda";
6import { expect } from "alchemy-test";
7import * as Effect from "effect/Effect";
8import * as Schedule from "effect/Schedule";
9import EventSourceMappingFunctionLive, {
10 EventSourceMappingFunction,
11} from "./fixtures/event-source-mapping-handler.ts";
12
13const { test } = Test.make({ providers: AWS.providers() });
14
15// Canonical `list()` test (AWS account/region-scoped collection): deploy a
16// minimal Lambda Function + SQS Queue + EventSourceMapping (wired via the
17// `consumeQueueMessages(queue, ...)` event source), resolve the provider from
18// context with the typed `Provider.findProvider(EventSourceMapping)`, call
19// `list()`, and assert the deployed mapping appears in the exhaustively
20// paginated result.
21test.provider(
22 "list enumerates the deployed event source mapping",
23 (stack) =>
24 Effect.gen(function* () {
25 yield* stack.destroy();
26
27 const fn = yield* stack.deploy(
28 EventSourceMappingFunction.pipe(
29 Effect.provide(EventSourceMappingFunctionLive),
30 ),
31 );
32
33 const provider = yield* Provider.findProvider(EventSourceMapping);
34 const all = yield* provider.list();
35
36 expect(all.length).toBeGreaterThan(0);
37 expect(all.some((m) => m.functionArn === fn.functionArn)).toBe(true);
38
39 const mine = all.find((m) => m.functionArn === fn.functionArn)!;
40 expect(mine.uuid).toBeTruthy();
41 expect(mine.eventSourceMappingArn).toContain("event-source-mapping");
42 expect(mine.state).toBeTruthy();
43
44 yield* stack.destroy();
45
46 // Out-of-band proof the destroy removed both the mapping and the host
47 // function from the cloud (bounded retry for delete propagation).
48 yield* Lambda.getEventSourceMapping({ UUID: mine.uuid }).pipe(
49 Effect.flatMap(() =>
50 Effect.fail(
51 new Error(`Event source mapping ${mine.uuid} still exists`),
52 ),
53 ),
54 Effect.catchTag("ResourceNotFoundException", () => Effect.void),
55 Effect.retry({
56 schedule: Schedule.max([
57 Schedule.exponential(500),
58 Schedule.recurs(8),
59 ]),
60 }),
61 );
62 yield* Lambda.getFunction({ FunctionName: fn.functionName }).pipe(
63 Effect.flatMap(() =>
64 Effect.fail(new Error(`Function ${fn.functionName} still exists`)),
65 ),
66 Effect.catchTag("ResourceNotFoundException", () => Effect.void),
67 Effect.retry({
68 schedule: Schedule.max([
69 Schedule.exponential(500),
70 Schedule.recurs(8),
71 ]),
72 }),
73 );
74 }).pipe(Effect.onError(() => stack.destroy().pipe(Effect.ignore))),
75 {
76 tags: ["provider:aws", "provider:aws:lambda", "provider:aws:sqs", "live"],
77 timeout: 240_000,
78 },
79);