1import * as Cloudflare from "@/Cloudflare";
2import { CloudflareEnvironment } from "@/Cloudflare/CloudflareEnvironment";
3import { findZoneByName } from "@/Cloudflare/Zone/lookup";
4import * as Provider from "@/Provider";
5import * as Test from "@/Test/Alchemy";
6import * as cache from "@distilled.cloud/cloudflare/cache";
7import { describe, expect } from "alchemy-test";
8import * as Effect from "effect/Effect";
9import { MinimumLogLevel } from "effect/References";
10import * as Schedule from "effect/Schedule";
11const { test } = Test.make({ providers: Cloudflare.providers() });
12
13const logLevel = Effect.provideService(
14 MinimumLogLevel,
15 process.env.DEBUG ? "Debug" : "Info",
16);
17
18const zoneName =
19 process.env.CLOUDFLARE_TEST_DNS_ZONE_NAME ?? "alchemy-test-2.us";
20
21const resolveZoneId = Effect.gen(function* () {
22 const { accountId } = yield* yield* CloudflareEnvironment;
23 const zone = yield* findZoneByName({ accountId, name: zoneName });
24 if (!zone) {
25 return yield* Effect.die(
26 new Error(`zone "${zoneName}" not found in account`),
27 );
28 }
29 return zone.id;
30});
31
32// The scoped API token the test harness mints propagates eventually-
33// consistently across Cloudflare's edge — a fresh token intermittently 403s.
34// Ride out the blips on the test's own out-of-band calls by retrying the
35// typed `Forbidden` error (part of each cache operation's error union via
36// distilled patches).
37const forbiddenRetrySchedule = Schedule.exponential("500 millis");
38
39const getSmartTieredCache = (zoneId: string) =>
40 cache.getSmartTieredCache({ zoneId }).pipe(
41 Effect.retry({
42 while: (e) => e._tag === "Forbidden",
43 schedule: forbiddenRetrySchedule,
44 times: 8,
45 }),
46 );
47
48// Normalize the setting to a known baseline so each run starts from the
49// same cloud state regardless of what a previous (possibly interrupted)
50// run left behind. Smart Tiered Cache defaults to "off".
51const setBaseline = (zoneId: string, value: "on" | "off") =>
52 cache.patchSmartTieredCache({ zoneId, value }).pipe(
53 Effect.retry({
54 while: (e) => e._tag === "Forbidden",
55 schedule: forbiddenRetrySchedule,
56 times: 8,
57 }),
58 );
59
60// Both cases mutate the same zone-level Smart Tiered Cache singleton with
61// opposite baselines; run them serially so they don't corrupt each other's
62// captured `initialValue` under the global concurrent test config.
63describe.sequential(
64 "SmartTieredCache",
65 {
66 tags: [
67 "provider:cloudflare",
68 "provider:cloudflare:cache",
69 "provider:cloudflare:zone",
70 "live",
71 ],
72 },
73 () => {
74 test.provider(
75 "enables Smart Tiered Cache and restores the original value on destroy",
76 (stack) =>
77 Effect.gen(function* () {
78 const zoneId = yield* resolveZoneId;
79
80 yield* stack.destroy();
81 // Known baseline: Smart Tiered Cache defaults to "off".
82 yield* setBaseline(zoneId, "off");
83
84 const setting = yield* stack.deploy(
85 Effect.gen(function* () {
86 return yield* Cloudflare.Cache.SmartTieredCache("SmartCache", {
87 zoneId,
88 });
89 }),
90 );
91
92 expect(setting.zoneId).toEqual(zoneId);
93 expect(setting.value).toEqual("on");
94 // The pre-management value was captured for restore-on-destroy.
95 expect(setting.initialValue).toEqual("off");
96 expect(setting.editable).toEqual(true);
97
98 // Out-of-band verification via the distilled API.
99 const live = yield* getSmartTieredCache(zoneId);
100 expect(live.value).toEqual("on");
101
102 yield* stack.destroy();
103
104 // Destroy restored the value the setting had before we managed it.
105 const restored = yield* getSmartTieredCache(zoneId);
106 expect(restored.value).toEqual("off");
107 }).pipe(logLevel),
108 );
109
110 test.provider(
111 "updates the setting in place and keeps the captured initial value",
112 (stack) =>
113 Effect.gen(function* () {
114 const zoneId = yield* resolveZoneId;
115
116 yield* stack.destroy();
117 // Known baseline: start from "on" so initialValue !== first desired
118 // value and the restore path is observable.
119 yield* setBaseline(zoneId, "on");
120
121 const initial = yield* stack.deploy(
122 Effect.gen(function* () {
123 return yield* Cloudflare.Cache.SmartTieredCache("SmartCache", {
124 zoneId,
125 enabled: false,
126 });
127 }),
128 );
129
130 expect(initial.value).toEqual("off");
131 expect(initial.initialValue).toEqual("on");
132
133 const updated = yield* stack.deploy(
134 Effect.gen(function* () {
135 return yield* Cloudflare.Cache.SmartTieredCache("SmartCache", {
136 zoneId,
137 enabled: true,
138 });
139 }),
140 );
141
142 // Same singleton patched in place; the original value survives the
143 // update so destroy still restores the pre-management state.
144 expect(updated.value).toEqual("on");
145 expect(updated.initialValue).toEqual("on");
146
147 const live = yield* getSmartTieredCache(zoneId);
148 expect(live.value).toEqual("on");
149
150 yield* stack.destroy();
151
152 const restored = yield* getSmartTieredCache(zoneId);
153 expect(restored.value).toEqual("on");
154
155 // Leave the zone at its Cloudflare default ("off") for other suites.
156 yield* setBaseline(zoneId, "off");
157 }).pipe(logLevel),
158 );
159
160 // Canonical `list()` test (zone-scoped singleton): there is no account-wide
161 // API for this per-zone setting, so `list()` enumerates every zone via
162 // `listAllZones` and reads the singleton in each. Assert the result is
163 // non-empty and contains the standing test zone.
164 test.provider("list enumerates the setting across all zones", (stack) =>
165 Effect.gen(function* () {
166 const zoneId = yield* resolveZoneId;
167
168 const provider = yield* Provider.findProvider(
169 Cloudflare.Cache.SmartTieredCache,
170 );
171 const all = yield* provider.list();
172
173 expect(all.length).toBeGreaterThan(0);
174 expect(all.some((s) => s.zoneId === zoneId)).toBe(true);
175
176 // `stack` is unused here (the singleton always exists on every zone),
177 // but keep the destroy bookends so the harness state stays clean.
178 yield* stack.destroy();
179 }).pipe(logLevel),
180 );
181 },
182);