1import * as Alchemy from "@/index.ts";
2import * as Cloudflare from "@/Cloudflare";
3import * as Test from "@/Test/Alchemy";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8import * as HttpClient from "effect/http/HttpClient";
9import SendEmailWorker from "./fixtures/worker.ts";
10
11const { test, beforeAll, afterAll, deploy, destroy } = Test.make({
12 providers: Cloudflare.providers(),
13});
14
15const logLevel = Effect.provideService(
16 MinimumLogLevel,
17 process.env.DEBUG ? "Debug" : "Info",
18);
19
20const FROM = process.env.CLOUDFLARE_TEST_EMAIL_FROM;
21const TO = process.env.CLOUDFLARE_TEST_EMAIL_TO;
22const skip = !FROM || !TO;
23
24const Stack = Alchemy.Stack(
25 "SendEmailBindingStack",
26 {
27 providers: Cloudflare.providers(),
28 state: Cloudflare.state(),
29 },
30 Effect.gen(function* () {
31 const worker = yield* SendEmailWorker;
32 return { url: worker.url.as<string>() };
33 }),
34);
35
36const stack = beforeAll(deploy(Stack));
37afterAll.skipIf(!!process.env.NO_DESTROY || skip)(destroy(Stack));
38
39// The send_email binding only delivers from a domain with Email Routing
40// enabled to a verified destination address — supply such a pair via
41// CLOUDFLARE_TEST_EMAIL_FROM / CLOUDFLARE_TEST_EMAIL_TO to run this test.
42test.skipIf(skip)(
43 "sends an email through the Worker send_email binding",
44 Effect.gen(function* () {
45 const { url } = yield* stack;
46 const client = yield* HttpClient.HttpClient;
47
48 const sendUrl = `${url}/send?from=${encodeURIComponent(FROM!)}&to=${encodeURIComponent(TO!)}`;
49 const res = yield* client.get(sendUrl).pipe(
50 Effect.flatMap((res) =>
51 res.status === 200 ? Effect.succeed(res) : Effect.fail(res),
52 ),
53 Effect.retry({
54 schedule: Schedule.exponential("500 millis"),
55 times: 10,
56 }),
57 );
58 const body = (yield* res.json) as { ok: boolean; message?: string };
59 if (!body.ok) {
60 throw new Error(`send_email failed: ${body.message}`);
61 }
62 expect(body.ok).toBe(true);
63 }).pipe(logLevel),
64 {
65 tags: [
66 "provider:cloudflare",
67 "provider:cloudflare:email",
68 "provider:cloudflare:worker",
69 "live",
70 ],
71 timeout: 180_000,
72 },
73);