Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions apps/server/src/preview/ServerBrowserContexts.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
// @effect-diagnostics nodeBuiltinImport:off - Hands a real file on disk to a real desktop browser.
import * as NodeEvents from "node:events";
import * as NodeFS from "node:fs";
import * as NodeOS from "node:os";
import * as NodePath from "node:path";

import { INCOGNITO_BROWSER_PROFILE_ID } from "@t3tools/contracts";
import { chromium, type Browser, type BrowserContext, type BrowserType } from "playwright-core";
Expand All @@ -12,6 +16,7 @@ const launches = vi.hoisted(() => ({
mkdir: vi.fn().mockResolvedValue(undefined),
rm: vi.fn().mockResolvedValue(undefined),
}));
const launchPersistentChromium = chromium.launchPersistentContext.bind(chromium);
vi.spyOn(chromium, "launch").mockImplementation(launches.launch);
vi.spyOn(chromium, "launchPersistentContext").mockImplementation(launches.persistent);
vi.mock("node:fs/promises", () => ({ mkdir: launches.mkdir, rm: launches.rm }));
Expand Down Expand Up @@ -327,4 +332,45 @@ describe("ServerBrowserContexts", () => {
expect(browser.close).toHaveBeenCalledTimes(1);
expect(browser.created[0]?.close).toHaveBeenCalled();
});

it("uploads a file over 50 MB to a desktop tab, which shares the server's filesystem", async () => {
const directory = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-desktop-upload-"));
const userDataDir = NodePath.join(directory, "profile");
const pool = new ServerBrowserContexts(options());
try {
const desktop = await launchPersistentChromium(userDataDir, {
headless: true,
args: ["--remote-debugging-port=0"],
});
try {
const [port] = NodeFS.readFileSync(
NodePath.join(userDataDir, "DevToolsActivePort"),
"utf8",
).split("\n");
const { browser, page } = await pool.connectDesktopPage(`http://127.0.0.1:${port}`);
try {
const file = NodePath.join(directory, "large.bin");
NodeFS.writeFileSync(file, "");
NodeFS.truncateSync(file, 51 * 1024 * 1024);
await page.setContent(`<input type="file">`);
await page.locator("input").setInputFiles(file);
expect(
await page.$eval("input", (input) =>
Array.from(
(input as unknown as { files: ArrayLike<{ name: string; size: number }> }).files,
({ name, size }) => ({ name, size }),
),
),
).toEqual([{ name: "large.bin", size: 51 * 1024 * 1024 }]);
} finally {
await browser.close();
}
} finally {
await pool.close();
await desktop.close();
}
} finally {
NodeFS.rmSync(directory, { recursive: true, force: true });
}
});
});
3 changes: 2 additions & 1 deletion apps/server/src/preview/ServerBrowserContexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ export class ServerBrowserContexts {

async connectDesktopPage(endpoint: string) {
const { chromium } = loadPlaywright();
const browser = await chromium.connectOverCDP(endpoint, { timeout: 15_000 });
// Only a same-machine desktop backend gets the browser channel, so uploads can pass file paths.
const browser = await chromium.connectOverCDP(endpoint, { isLocal: true, timeout: 15_000 });
const page = browser.contexts().flatMap((context) => context.pages())[0];
if (!page) {
await browser.close().catch(constVoid);
Expand Down
Loading