1import * as Alchemy from "alchemy";
2import * as Hetzner from "alchemy/Hetzner";
3import * as Test from "alchemy/Test/Bun";
4import { expect } from "bun:test";
5import * as Console from "effect/Console";
6import * as Effect from "effect/Effect";
7import Stack from "../alchemy.run.ts";
8
9const { getWhenReady } = Test;
10
11const hasCreds = !!process.env.HCLOUD_TOKEN;
12
13const { test, beforeAll, afterAll, deploy, destroy } = Test.make({
14 providers: Hetzner.providers(),
15 state: Alchemy.localState(),
16 profile: process.env.ALCHEMY_PROFILE,
17});
18
19if (!hasCreds) {
20 test.skip("skipped without HCLOUD_TOKEN", Effect.void);
21} else {
22 const stack = beforeAll(deploy(Stack).pipe(Effect.tap(Console.log)), {
23 timeout: 600_000,
24 });
25 afterAll.skipIf(!!process.env.NO_DESTROY)(destroy(Stack));
26
27 const base = Effect.map(stack, ({ url }) => {
28 if (!url) throw new Error("expected the site to expose a url");
29 return url.replace(/\/+$/, "");
30 });
31
32 test(
33 "deploys and exposes a url",
34 Effect.gen(function* () {
35 const { url } = yield* stack;
36 expect(url).toBeString();
37 }),
38 { timeout: 180_000 },
39 );
40
41 test(
42 "serves documentation pages",
43 Effect.gen(function* () {
44 const url = yield* base;
45 const home = yield* getWhenReady(url);
46 expect(home.status).toBe(200);
47 expect(yield* home.text).toContain("Alchemy with Vocs");
48
49 const guide = yield* getWhenReady(`${url}/guide`);
50 expect(guide.status).toBe(200);
51 expect(yield* guide.text).toContain("Deployment guide");
52
53 const counter = yield* getWhenReady(`${url}/counter`);
54 expect(counter.status).toBe(200);
55 expect(yield* counter.text).toContain("Interactive component");
56 }),
57 { timeout: 180_000 },
58 );
59
60 test(
61 "serves public and generated assets",
62 Effect.gen(function* () {
63 const url = yield* base;
64 const asset = yield* getWhenReady(`${url}/hello.txt`);
65 expect(asset.status).toBe(200);
66 expect(yield* asset.text).toContain("Vocs public directory");
67
68 const llms = yield* getWhenReady(`${url}/llms.txt`);
69 expect(llms.status).toBe(200);
70 expect(yield* llms.text).toContain("Alchemy with Vocs");
71 }),
72 { timeout: 180_000 },
73 );
74}