mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(browser): avoid duplicate upload events (#103777)
This commit is contained in:
committed by
GitHub
parent
db39fe8072
commit
911f8ec68f
@@ -93,20 +93,6 @@ export async function armFileUploadViaPlaywright(opts: {
|
||||
return;
|
||||
}
|
||||
await fileChooser.setFiles(uploadPathsResult.paths);
|
||||
try {
|
||||
const input =
|
||||
typeof fileChooser.element === "function"
|
||||
? await Promise.resolve(fileChooser.element())
|
||||
: null;
|
||||
if (input) {
|
||||
await input.evaluate((el) => {
|
||||
el.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
el.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// Best-effort for sites that don't react to setFiles alone.
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// Ignore timeouts; the chooser may never appear.
|
||||
|
||||
@@ -45,16 +45,22 @@ vi.mock("./paths.js", () => {
|
||||
|
||||
const { setInputFilesViaPlaywright } = await import("./pw-tools-core.interactions.js");
|
||||
|
||||
function seedSingleLocatorPage(): { setInputFiles: ReturnType<typeof vi.fn> } {
|
||||
function seedSingleLocatorPage(): {
|
||||
setInputFiles: ReturnType<typeof vi.fn>;
|
||||
elementHandle: ReturnType<typeof vi.fn>;
|
||||
} {
|
||||
const setInputFiles = vi.fn(async () => {});
|
||||
const elementHandle = vi.fn(async () => {
|
||||
throw new Error("manual upload event dispatch is forbidden");
|
||||
});
|
||||
locator = {
|
||||
setInputFiles,
|
||||
elementHandle: vi.fn(async () => null),
|
||||
elementHandle,
|
||||
};
|
||||
page = {
|
||||
locator: vi.fn(() => ({ first: () => locator })),
|
||||
};
|
||||
return { setInputFiles };
|
||||
return { setInputFiles, elementHandle };
|
||||
}
|
||||
|
||||
describe("setInputFilesViaPlaywright", () => {
|
||||
@@ -68,8 +74,8 @@ describe("setInputFilesViaPlaywright", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("revalidates upload paths and uses resolved canonical paths for inputRef", async () => {
|
||||
const { setInputFiles } = seedSingleLocatorPage();
|
||||
it("sets resolved files once and leaves browser events to Playwright", async () => {
|
||||
const { setInputFiles, elementHandle } = seedSingleLocatorPage();
|
||||
|
||||
await setInputFilesViaPlaywright({
|
||||
cdpUrl: "http://127.0.0.1:18792",
|
||||
@@ -83,6 +89,8 @@ describe("setInputFilesViaPlaywright", () => {
|
||||
});
|
||||
expect(refLocator).toHaveBeenCalledWith(page, "e7");
|
||||
expect(setInputFiles).toHaveBeenCalledWith(["/private/tmp/openclaw/uploads/ok.txt"]);
|
||||
expect(setInputFiles).toHaveBeenCalledTimes(1);
|
||||
expect(elementHandle).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("throws and skips setInputFiles when use-time validation fails", async () => {
|
||||
|
||||
@@ -1497,17 +1497,6 @@ export async function setInputFilesViaPlaywright(opts: {
|
||||
} catch (err) {
|
||||
throw toFriendlyInteractionError(err, inputRef || element);
|
||||
}
|
||||
try {
|
||||
const handle = await locator.elementHandle();
|
||||
if (handle) {
|
||||
await handle.evaluate((el) => {
|
||||
el.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
el.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// Best-effort for sites that don't react to setInputFiles alone.
|
||||
}
|
||||
}
|
||||
|
||||
async function executeSingleAction(
|
||||
|
||||
@@ -26,7 +26,10 @@ installPwToolsCoreTestHooks();
|
||||
const { armFileUploadViaPlaywright } = await import("./pw-tools-core.downloads.js");
|
||||
|
||||
function createFileChooserPageMocks() {
|
||||
const fileChooser = { setFiles: vi.fn(async () => {}) };
|
||||
const element = vi.fn(async () => {
|
||||
throw new Error("manual upload event dispatch is forbidden");
|
||||
});
|
||||
const fileChooser = { setFiles: vi.fn(async () => {}), element };
|
||||
const press = vi.fn(async () => {});
|
||||
const waitForEvent = vi.fn(async () => fileChooser);
|
||||
setPwToolsCoreCurrentPage({
|
||||
@@ -44,7 +47,7 @@ describe("armFileUploadViaPlaywright upload path validation", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("sets files using resolved inbound media paths", async () => {
|
||||
it("sets resolved files once and leaves browser events to Playwright", async () => {
|
||||
const { fileChooser } = createFileChooserPageMocks();
|
||||
|
||||
await armFileUploadViaPlaywright({
|
||||
@@ -59,6 +62,8 @@ describe("armFileUploadViaPlaywright upload path validation", () => {
|
||||
"/home/user/.openclaw/media/inbound/report.pdf",
|
||||
]);
|
||||
});
|
||||
expect(fileChooser.setFiles).toHaveBeenCalledTimes(1);
|
||||
expect(fileChooser.element).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("escapes the chooser when paths are outside managed upload roots", async () => {
|
||||
|
||||
Reference in New Issue
Block a user