1import * as Alchemy from "alchemy";
2import * as Cloudflare from "alchemy/Cloudflare";
3import * as Test from "alchemy/Test/Bun";
4import { expect } from "bun:test";
5import * as Effect from "effect/Effect";
6import * as HttpClient from "effect/http/HttpClient";
7import * as HttpClientRequest from "effect/http/HttpClientRequest";
8import Stack from "../alchemy.run.ts";
9import type { User } from "../src/schema.ts";
10
11const { test, beforeAll, afterAll, deploy, destroy } = Test.make({
12 providers: Cloudflare.providers(),
13 state: Alchemy.localState(),
14});
15
16const stack = beforeAll(destroy(Stack).pipe(Effect.andThen(deploy(Stack))));
17afterAll.skipIf(!!process.env.NO_DESTROY)(destroy(Stack));
18
19test(
20 "migrates named objects and keeps their users isolated",
21 Effect.gen(function* () {
22 const { url } = yield* stack;
23 const baseUrl = url.replace(/\/+$/, "");
24 const teamA = `${baseUrl}/objects/team-a/users`;
25 const teamB = `${baseUrl}/objects/team-b/users`;
26
27 const initial = yield* Test.getWhenReady(teamA);
28 expect(initial.status).toBe(200);
29 expect(yield* initial.json).toEqual({ users: [] });
30
31 const created = yield* HttpClient.execute(
32 HttpClientRequest.post(teamA).pipe(
33 HttpClientRequest.bodyJsonUnsafe({ name: "Ada" }),
34 ),
35 );
36 expect(created.status).toBe(201);
37 const { user } = (yield* created.json) as { user: User };
38 expect(user.name).toBe("Ada");
39 expect(user.id).toBeNumber();
40
41 const saved = yield* HttpClient.get(teamA);
42 expect(saved.status).toBe(200);
43 expect(yield* saved.json).toEqual({ users: [user] });
44
45 const isolated = yield* HttpClient.get(teamB);
46 expect(isolated.status).toBe(200);
47 expect(yield* isolated.json).toEqual({ users: [] });
48
49 const repeated = yield* HttpClient.get(teamA);
50 expect(repeated.status).toBe(200);
51 expect(yield* repeated.json).toEqual({ users: [user] });
52
53 const invalid = yield* HttpClient.execute(
54 HttpClientRequest.post(teamA).pipe(
55 HttpClientRequest.bodyJsonUnsafe({ name: " " }),
56 ),
57 );
58 expect(invalid.status).toBe(400);
59 }),
60 { timeout: 120_000 },
61);