返回 DeepSeek-Reasonix
upload.test.ts
根目录 / desktop / electron / src / main / browser / upload.test.ts
1 import assert from "node:assert/strict";
2 import { test } from "node:test";
3 import { JSDOM } from "jsdom";
4 import { FakePage } from "./fakeGuestViews.js";
5 import { REGISTRY_KEY } from "./snapshot.js";
6 import { uploadFiles } from "./upload.js";
7
8 function callInDOM(dom: JSDOM, params: unknown): unknown {
9 const call = params as { functionDeclaration: string; arguments: Array<{ value: unknown }> };
10 const fn = dom.window.eval(`(${call.functionDeclaration})`) as (...args: unknown[]) => unknown;
11 return fn(...call.arguments.map((arg) => arg.value));
12 }
13
14 test("upload keeps the original snapshot node when another file input takes its CSS position", async () => {
15 const dom = new JSDOM('<input type="file" id="upload">', { runScripts: "outside-only" });
16 try {
17 (dom.window as unknown as Record<string, unknown>)[REGISTRY_KEY] = { docId: "doc", snapshotId: "snap", refs: new Map([["e1", dom.window.document.querySelector("input")]]) };
18 const page = new FakePage(1);
19 let replaced = false;
20 page.debugger.respond = (method, params) => {
21 if (method === "Runtime.enable") {
22 if (replaced) dom.window.document.querySelector("input")!.outerHTML = '<input type="file" id="upload">';
23 page.debugger.emit("Runtime.executionContextCreated", { context: { id: 1, auxData: { isDefault: false } } });
24 }
25 if (method === "Runtime.callFunctionOn") {
26 const node = callInDOM(dom, params);
27 return { result: node ? { objectId: "original-input" } : { subtype: "null" } };
28 }
29 return {};
30 };
31 const located = { ref: "e1", snapshotId: "snap", tag: "input", type: "file", path: "html > body:nth-child(2) > input:nth-child(1)", frame: page.mainFrame, binding: { prefix: "", frameTreeNodeId: 100, docId: "doc" }, isMainFrame: true };
32 assert.deepEqual(await uploadFiles(page, located, ["/tmp/file"], () => {}, () => {}), { executed: true });
33 page.debugger.commands.length = 0;
34 replaced = true;
35 const result = await uploadFiles(page, located, ["/tmp/file"], () => {}, () => {});
36 assert.equal(result.executed, false);
37 assert.equal(page.debugger.commands.some((command) => command.method === "DOM.setFileInputFiles"), false);
38 } finally {
39 dom.window.close();
40 }
41 });
42
43 test("upload treats script-shaped document and reference values as data", async () => {
44 const dom = new JSDOM('<input type="file">', { runScripts: "outside-only" });
45 try {
46 const docId = '\"); globalThis.compromised = true; //';
47 const snapshotId = "'); throw new Error('injected'); //";
48 const ref = "` ${globalThis.compromised = true} \\ \n \u2028";
49 const input = dom.window.document.querySelector("input");
50 const globals = dom.window as unknown as Record<string, unknown>;
51 globals[REGISTRY_KEY] = { docId, snapshotId, refs: new Map([[ref, input]]) };
52 const page = new FakePage(1);
53 page.debugger.respond = (method, params) => {
54 if (method === "Runtime.enable") page.debugger.emit("Runtime.executionContextCreated", { context: { id: 1, auxData: { isDefault: false } } });
55 if (method === "Runtime.callFunctionOn") {
56 const node = callInDOM(dom, params);
57 assert.equal(node, input);
58 return { result: { objectId: "original-input" } };
59 }
60 return {};
61 };
62 const located = { ref, snapshotId, tag: "input", type: "file", path: "unused", frame: page.mainFrame, binding: { prefix: "", frameTreeNodeId: 100, docId }, isMainFrame: true };
63 assert.deepEqual(await uploadFiles(page, located, ["/tmp/file"], () => {}, () => {}), { executed: true });
64 assert.equal(globals.compromised, undefined);
65 } finally {
66 dom.window.close();
67 }
68 });
69
69 lines TYPESCRIPT