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 { Dataset } from "./fixtures/dataset.ts";
10import AnalyticsEngineTestWorker from "./fixtures/worker.ts";
11
12const { test, beforeAll, afterAll, deploy, destroy } = Test.make({
13 providers: Cloudflare.providers(),
14});
15
16const logLevel = Effect.provideService(
17 MinimumLogLevel,
18 process.env.DEBUG ? "Debug" : "Info",
19);
20
21const Stack = Alchemy.Stack(
22 "AnalyticsEngineBindingStack",
23 {
24 providers: Cloudflare.providers(),
25 state: Cloudflare.state(),
26 },
27 Effect.gen(function* () {
28 const dataset = yield* Dataset;
29 const worker = yield* AnalyticsEngineTestWorker;
30 return {
31 dataset: dataset.dataset,
32 url: worker.url.as<string>(),
33 };
34 }),
35);
36
37const stack = beforeAll(deploy(Stack));
38afterAll.skipIf(!!process.env.NO_DESTROY)(destroy(Stack));
39
40test(
41 "deployed worker can write data points through the Analytics Engine binding",
42 Effect.gen(function* () {
43 const { url } = yield* stack;
44 expect(url).toBeTypeOf("string");
45
46 const client = yield* HttpClient.HttpClient;
47 const res = yield* client.get(`${url}/write`).pipe(
48 Effect.flatMap((res) =>
49 res.status === 200 ? Effect.succeed(res) : Effect.fail(res),
50 ),
51 Effect.retry({
52 schedule: Schedule.exponential("500 millis"),
53 times: 10,
54 }),
55 );
56 expect(res.status).toBe(200);
57 const body = (yield* res.json) as { ok: boolean };
58 expect(body.ok).toBe(true);
59 }).pipe(logLevel),
60 {
61 tags: [
62 "provider:cloudflare",
63 "provider:cloudflare:analyticsengine",
64 "provider:cloudflare:worker",
65 "live",
66 ],
67 timeout: 180_000,
68 },
69);