1import * as Cloudflare from "@/Cloudflare/index.ts";
2import * as Test from "@/Test/Alchemy";
3import { describe, expect } from "alchemy-test";
4import * as Effect from "effect/Effect";
5import * as FileSystem from "effect/FileSystem";
6import * as Path from "effect/Path";
7import { MinimumLogLevel } from "effect/References";
8import * as pathe from "pathe";
9import { cloneFixture } from "../Utils/Fixture.ts";
10import { expectUrlContains } from "../Utils/Http.ts";
11
12const { test } = Test.make({ providers: Cloudflare.providers(), dev: true });
13
14const logLevel = Effect.provideService(
15 MinimumLogLevel,
16 process.env.DEBUG ? "Debug" : "Info",
17);
18
19const fixtureDir = pathe.resolve(
20 import.meta.dirname,
21 "../../../../../examples/cloudflare-website-vocs",
22);
23const tempRoot = pathe.resolve(import.meta.dirname, "../../../.tmp");
24
25describe.concurrent(
26 "Vocs dev",
27 { tags: ["provider:cloudflare", "provider:cloudflare:website", "local"] },
28 () => {
29 test.provider(
30 "Vocs dev: serves SSR, MDX and assets locally and responds to source edits",
31 (stack) =>
32 Effect.gen(function* () {
33 const fs = yield* FileSystem.FileSystem;
34 const path = yield* Path.Path;
35
36 yield* stack.destroy();
37
38 const rootDir = yield* cloneFixture(fixtureDir, {
39 prefix: "alchemy-vocs-dev-",
40 tempRoot,
41 entries: [
42 "package.json",
43 "public",
44 "src",
45 "tsconfig.json",
46 "vocs.config.ts",
47 ],
48 });
49
50 const site = yield* stack.deploy(
51 Cloudflare.Website.Vocs("VocsLocal", {
52 rootDir,
53 dev: { port: 0 },
54 memo: {
55 include: [
56 "src/**",
57 "public/**",
58 "package.json",
59 "tsconfig.json",
60 "vocs.config.ts",
61 ],
62 },
63 }),
64 );
65
66 expect(site.url).toMatch(/^http:\/\/localhost:\d+/);
67 yield* expectUrlContains(`${site.url!}/`, "Alchemy with Vocs", {
68 timeout: "180 seconds",
69 headers: { accept: "text/html", "user-agent": "Mozilla/5.0" },
70 label: "Vocs dev SSR home",
71 });
72 yield* expectUrlContains(`${site.url!}/guide`, "Deployment guide", {
73 timeout: "60 seconds",
74 headers: { accept: "text/html", "user-agent": "Mozilla/5.0" },
75 label: "Vocs dev MDX guide",
76 });
77 yield* expectUrlContains(
78 `${site.url!}/hello.txt`,
79 "hello from the Vocs public directory",
80 {
81 timeout: "60 seconds",
82 headers: { accept: "text/html", "user-agent": "Mozilla/5.0" },
83 label: "Vocs dev public asset",
84 },
85 );
86
87 const pagePath = path.join(rootDir, "src/pages/index.mdx");
88 const page = yield* fs.readFileString(pagePath);
89 yield* fs.writeFileString(
90 pagePath,
91 page.replace(
92 "No Wrangler configuration or Vocs adapter setup is required.",
93 "This Vocs page was updated through HMR.",
94 ),
95 );
96 yield* expectUrlContains(
97 `${site.url!}/?__alchemy_cb=${Date.now()}`,
98 "This Vocs page was updated through HMR.",
99 {
100 timeout: "120 seconds",
101 headers: { accept: "text/html", "user-agent": "Mozilla/5.0" },
102 label: "Vocs dev page after source edit",
103 },
104 );
105
106 yield* stack.destroy();
107 }).pipe(logLevel),
108 { timeout: 300_000 },
109 );
110 },
111);