Skip to content
File

Blob: tests/e2e/global-setup.ts

typescript94 lines
1import { mkdtemp, rm, writeFile } from "node:fs/promises";
2import { tmpdir } from "node:os";
3import { join } from "node:path";
4 
5import {
6 applyMigrations,
7 generateEmojiData,
8 seedTestUser,
9 startDevServer,
10 stopDevServer,
11 closeContextLogs,
12 printFailureContext,
13 printLogTails,
14 type E2eContext,
15 type E2eContextFile,
16} from "./harness";
17import { startMockOidcProvider, type MockOidcServer } from "./oidc-mock";
18 
19export type { E2eContextFile } from "./harness";
20export const E2E_CONTEXT_PATH_ENV = "BLAND_E2E_CONTEXT_PATH";
21 
22export default async function globalSetup(): Promise<() => Promise<void>> {
23 const tempDir = await mkdtemp(join(tmpdir(), "bland-e2e-"));
24 let ctx: E2eContext | null = null;
25 let mockOidc: MockOidcServer | null = null;
26 console.log(`[e2e] temp state: ${tempDir}`);
27 
28 try {
29 await generateEmojiData();
30 await applyMigrations(tempDir);
31 await seedTestUser(tempDir);
32 mockOidc = await startMockOidcProvider();
33 console.log(`[e2e] mock OIDC provider issuer: ${mockOidc.issuer}`);
34 ctx = await startDevServer(tempDir, mockOidc.issuer);
35 
36 const contextFile: E2eContextFile = {
37 baseUrl: ctx.baseUrl,
38 tempDir,
39 oidcIssuer: mockOidc.issuer,
40 };
41 
42 const contextPath = join(tempDir, ".e2e-context.json");
43 await writeFile(contextPath, JSON.stringify(contextFile));
44 
45 process.env.BLAND_E2E_BASE_URL = ctx.baseUrl;
46 process.env[E2E_CONTEXT_PATH_ENV] = contextPath;
47 
48 const captured = { ctx, mockOidc };
49 return async () => {
50 await teardown(captured.ctx, captured.mockOidc, tempDir);
51 };
52 } catch (error) {
53 if (ctx) {
54 await stopDevServer(ctx.serverProcess);
55 await closeContextLogs(ctx);
56 }
57 if (mockOidc) {
58 await mockOidc.close().catch(() => undefined);
59 }
60 
61 if (process.env.BLAND_E2E_PRESERVE === "1") {
62 if (ctx) {
63 printFailureContext(ctx);
64 await printLogTails(ctx);
65 }
66 console.log(`[e2e] temp state preserved after setup failure: ${tempDir}`);
67 } else {
68 if (ctx) await rm(ctx.devVarsPath, { force: true });
69 await rm(tempDir, { recursive: true, force: true });
70 console.log(`[e2e] temp state cleaned up after setup failure`);
71 }
72 
73 throw error;
74 }
75}
76 
77async function teardown(ctx: E2eContext, mockOidc: MockOidcServer | null, tempDir: string): Promise<void> {
78 await stopDevServer(ctx.serverProcess);
79 await closeContextLogs(ctx);
80 if (mockOidc) {
81 await mockOidc.close().catch(() => undefined);
82 }
83 
84 if (process.env.BLAND_E2E_PRESERVE === "1") {
85 printFailureContext(ctx);
86 await printLogTails(ctx);
87 console.log(`[e2e] temp state preserved: ${tempDir}`);
88 } else {
89 await rm(ctx.devVarsPath, { force: true });
90 await rm(tempDir, { recursive: true, force: true });
91 console.log(`[e2e] temp state cleaned up`);
92 }
93}