Skip to content
File

Blob: tests/e2e/global-setup.ts

typescript63 lines
1import { mkdtemp, rm, writeFile } from "node:fs/promises";
2import { tmpdir } from "node:os";
3import { join } from "node:path";
4 
5import {
6 applyMigrations,
7 closeContextLogs,
8 printFailureContext,
9 removeE2eDevVars,
10 seedInvite,
11 startDevServer,
12 stopDevServer,
13 type E2eContext,
14} from "./harness";
15 
16export const E2E_CONTEXT_PATH_ENV = "TESSERA_E2E_CONTEXT_PATH";
17 
18export interface PersistedE2eContext {
19 baseUrl: string;
20 tempDir: string;
21 invite: { email: string; token: string; password: string };
22}
23 
24export default async function globalSetup(): Promise<() => Promise<void>> {
25 const tempDir = await mkdtemp(join(tmpdir(), "tessera-e2e-"));
26 console.log(`[e2e] temp state: ${tempDir}`);
27 
28 await applyMigrations(tempDir);
29 const invite = await seedInvite(tempDir, "e2e-invitee@example.com");
30 const ctx = await startDevServer(tempDir);
31 
32 const persisted: PersistedE2eContext = {
33 baseUrl: ctx.baseUrl,
34 tempDir,
35 invite,
36 };
37 
38 const contextPath = join(tempDir, ".e2e-context.json");
39 await writeFile(contextPath, JSON.stringify(persisted));
40 
41 // Playwright reads `use.baseURL` once, before specs run. We set it here
42 // so the spec doesn't have to import the context file just to navigate.
43 process.env.TESSERA_E2E_BASE_URL = ctx.baseUrl;
44 process.env[E2E_CONTEXT_PATH_ENV] = contextPath;
45 
46 return async () => {
47 await teardown(ctx, tempDir);
48 };
49}
50 
51async function teardown(ctx: E2eContext, tempDir: string): Promise<void> {
52 await stopDevServer(ctx.serverProcess);
53 await closeContextLogs(ctx);
54 
55 if (process.env.TESSERA_E2E_PRESERVE === "1") {
56 printFailureContext(ctx);
57 console.log(`[e2e] temp state preserved: ${tempDir}`);
58 } else {
59 await removeE2eDevVars(ctx);
60 await rm(tempDir, { recursive: true, force: true });
61 }
62}