( provider: string, testFn: (context: SharedWorkspaceContext) => Promise<void> )
| 91 | * @param testFn - Test function to run with the workspace context |
| 92 | */ |
| 93 | export async function withSharedWorkspace( |
| 94 | provider: string, |
| 95 | testFn: (context: SharedWorkspaceContext) => Promise<void> |
| 96 | ): Promise<void> { |
| 97 | const env = getSharedEnv(); |
| 98 | const projectPath = getSharedRepoPath(); |
| 99 | |
| 100 | // Generate unique branch name for this test |
| 101 | const branchName = generateBranchName(`test-${provider}`); |
| 102 | const trunkBranch = await detectDefaultTrunkBranch(projectPath); |
| 103 | |
| 104 | // Trust the project so workspace creation can run under the test trust gate. |
| 105 | await trustProject(env, projectPath); |
| 106 | |
| 107 | // Create workspace |
| 108 | const result = await env.orpc.workspace.create({ |
| 109 | projectPath, |
| 110 | branchName, |
| 111 | trunkBranch, |
| 112 | }); |
| 113 | |
| 114 | if (!result.success) { |
| 115 | throw new Error(`Failed to create workspace: ${result.error}`); |
| 116 | } |
| 117 | |
| 118 | const metadata = result.metadata; |
| 119 | const workspaceId = metadata.id; |
| 120 | |
| 121 | // Setup provider with API key |
| 122 | const apiKey = getApiKey(provider === "openai" ? "OPENAI_API_KEY" : "ANTHROPIC_API_KEY"); |
| 123 | await setupProviders(env, { |
| 124 | [provider]: { apiKey }, |
| 125 | }); |
| 126 | |
| 127 | // Create stream collector |
| 128 | const collector = createStreamCollector(env.orpc, workspaceId); |
| 129 | collector.start(); |
| 130 | |
| 131 | // Wait for subscription to be ready |
| 132 | await collector.waitForSubscription(); |
| 133 | |
| 134 | // Wait for init to complete (if there's an init hook) |
| 135 | try { |
| 136 | await collector.waitForEvent("init-end", INIT_HOOK_WAIT_MS); |
| 137 | } catch { |
| 138 | // Init hook might not exist - that's OK |
| 139 | } |
| 140 | |
| 141 | try { |
| 142 | await testFn({ env, workspaceId, metadata, collector }); |
| 143 | } finally { |
| 144 | const stopPromise = collector.waitForStop().catch((error) => { |
| 145 | console.warn("Failed to stop StreamCollector during test cleanup:", error); |
| 146 | }); |
| 147 | |
| 148 | const stopTimedOut = await Promise.race([ |
| 149 | stopPromise.then(() => false), |
| 150 | new Promise<boolean>((resolve) => setTimeout(() => resolve(true), 2000)), |
no test coverage detected