MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / makeBrowserSurface

Function makeBrowserSurface

e2e/src/surfaces/browser.ts:163–329  ·  view source on GitHub ↗
(dir: string, target: Target)

Source from the content-addressed store, hash-verified

161// acquireUseRelease so a vitest timeout (fiber interruption) still closes the
162// browser and flushes video + trace — a bare promise would leak Chromium.
163export const makeBrowserSurface = (dir: string, target: Target): BrowserSurface => ({
164 session: (identity, drive) =>
165 Effect.acquireUseRelease(
166 Effect.promise(async () => {
167 const videoTmp = join(dir, ".video-tmp");
168 mkdirSync(videoTmp, { recursive: true });
169
170 // Watchable mode (E2E_FILM / E2E_DESK): slow each Playwright action so
171 // the recording is readable instead of flickering through states at
172 // machine speed. Off by default — normal CI runs stay fast.
173 const watchable = process.env.E2E_FILM === "1" || process.env.E2E_DESK === "1";
174 const slowMo = watchable ? 400 : undefined;
175 // On the desk (E2E_DESK), the browser is a real headed window on the
176 // virtual display — the desk's single screen recording films it next
177 // to the chat terminal, exactly like a developer tabbing over.
178 const browser = await chromium.launch(
179 process.env.E2E_DESK === "1"
180 ? {
181 headless: false,
182 args: ["--window-position=300,40", "--window-size=1100,830"],
183 slowMo,
184 }
185 : slowMo
186 ? { slowMo }
187 : {},
188 );
189 const context = await browser.newContext({
190 colorScheme: "dark",
191 viewport: { width: 1280, height: 800 },
192 recordVideo: { dir: videoTmp, size: { width: 1280, height: 800 } },
193 baseURL: target.baseUrl,
194 });
195 await context.tracing.start({
196 screenshots: true,
197 snapshots: true,
198 sources: true,
199 });
200 // Bake a synthetic URL bar into the recording so a shared session.mp4
201 // (and the step screenshots) shows which page each moment was on.
202 await installRecordingUrlBar(context);
203 if (identity.cookies?.length) {
204 await context.addCookies(
205 identity.cookies.map((cookie) => ({
206 ...cookie,
207 url: target.baseUrl,
208 })),
209 );
210 }
211 const page = await context.newPage();
212 // The session video's clock starts with the page; anchor it for the
213 // run's focus timeline (scripts/film.ts cuts on these).
214 markRecordingStart(dir, "browser");
215 // Main-frame navigations feed the viewer's synthetic URL bar — the
216 // recording itself is chromeless, so this is the only place the
217 // address the developer "typed" survives.
218 page.on("framenavigated", (frame) => {
219 if (frame === page.mainFrame()) markNavigation(dir, frame.url());
220 });

Callers 1

contextForFunction · 0.90

Calls 13

installRecordingUrlBarFunction · 0.90
markRecordingStartFunction · 0.90
markNavigationFunction · 0.90
appendTracesFunction · 0.90
execMethod · 0.80
pushMethod · 0.80
videoMethod · 0.80
startMethod · 0.65
setMethod · 0.65
getMethod · 0.65
deleteMethod · 0.65
responseMethod · 0.65

Tested by

no test coverage detected