From 477306ea50bc83f59d3f8411374839f55662cff0 Mon Sep 17 00:00:00 2001 From: lhfmartin <44720140+lhfmartin@users.noreply.github.com> Date: Sat, 14 Feb 2026 15:00:39 +0000 Subject: [PATCH 1/5] fix: Replace path with parentPath --- packages/playwright-core/src/client/elementHandle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/playwright-core/src/client/elementHandle.ts b/packages/playwright-core/src/client/elementHandle.ts index fe206241aabde..4eb1d52f8938f 100644 --- a/packages/playwright-core/src/client/elementHandle.ts +++ b/packages/playwright-core/src/client/elementHandle.ts @@ -289,7 +289,7 @@ export async function convertInputFiles(platform: Platform, files: string | File context._checkFileAccess(localDirectory); if (context._connection.isRemote()) { - const files = localDirectory ? (await platform.fs().promises.readdir(localDirectory, { withFileTypes: true, recursive: true })).filter(f => f.isFile()).map(f => platform.path().join(f.path, f.name)) : localPaths!; + const files = localDirectory ? (await platform.fs().promises.readdir(localDirectory, { withFileTypes: true, recursive: true })).filter(f => f.isFile()).map(f => platform.path().join(f.parentPath, f.name)) : localPaths!; const { writableStreams, rootDir } = await context._wrapApiCall(async () => context._channel.createTempFiles({ rootDirName: localDirectory ? platform.path().basename(localDirectory) : undefined, items: await Promise.all(files.map(async file => { From 23a4e293d58d92f4bd0940f608663a68c58f8bf4 Mon Sep 17 00:00:00 2001 From: lhfmartin <44720140+lhfmartin@users.noreply.github.com> Date: Mon, 16 Feb 2026 14:30:59 +0000 Subject: [PATCH 2/5] Add test --- tests/library/browsertype-connect.spec.ts | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/library/browsertype-connect.spec.ts b/tests/library/browsertype-connect.spec.ts index 2b756d1a361ea..bdff953086f3b 100644 --- a/tests/library/browsertype-connect.spec.ts +++ b/tests/library/browsertype-connect.spec.ts @@ -733,6 +733,33 @@ for (const kind of ['launchServer', 'run-server'] as const) { await Promise.all([uploadFile, file1.filepath].map(fs.promises.unlink)); }); + test('should set input folder', async ({ connect, startRemoteServer, server }, testInfo) => { + test.slow(); + const remoteServer = await startRemoteServer(kind); + const browser = await connect(remoteServer.wsEndpoint()); + const context = await browser.newContext(); + const page = await context.newPage(); + + await page.goto(server.PREFIX + '/input/folderupload.html'); + const input = await page.$('input'); + const folderName = 'folder-upload-test' + const dir = testInfo.outputPath(folderName); + { + await fs.promises.mkdir(dir, { recursive: true }); + await fs.promises.writeFile(path.join(dir, 'file1.txt'), 'file1 content'); + await fs.promises.writeFile(path.join(dir, 'file2'), 'file2 content'); + await fs.promises.mkdir(path.join(dir, 'sub-dir')); + await fs.promises.writeFile(path.join(dir, 'sub-dir', 'really.txt'), 'sub-dir file content'); + } + await input.setInputFiles(dir); + + expect(new Set(await page.evaluate(e => [...e.files].map(f => f.webkitRelativePath), input))).toEqual(new Set([ + `${folderName}/file1.txt`, + `${folderName}/file2`, + `${folderName}/sub-dir/really.txt`, + ])); + }); + test('setInputFiles should preserve lastModified timestamp', async ({ connect, startRemoteServer, asset }) => { test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/27452' }); const remoteServer = await startRemoteServer(kind); From eecc243152a06feadd7c46756990062491126cc9 Mon Sep 17 00:00:00 2001 From: lhfmartin <44720140+lhfmartin@users.noreply.github.com> Date: Mon, 16 Feb 2026 15:42:06 +0000 Subject: [PATCH 3/5] Check files received by server --- tests/library/browsertype-connect.spec.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/library/browsertype-connect.spec.ts b/tests/library/browsertype-connect.spec.ts index bdff953086f3b..55be045006247 100644 --- a/tests/library/browsertype-connect.spec.ts +++ b/tests/library/browsertype-connect.spec.ts @@ -733,7 +733,7 @@ for (const kind of ['launchServer', 'run-server'] as const) { await Promise.all([uploadFile, file1.filepath].map(fs.promises.unlink)); }); - test('should set input folder', async ({ connect, startRemoteServer, server }, testInfo) => { + test('should upload a folder', async ({ connect, startRemoteServer, server }, testInfo) => { test.slow(); const remoteServer = await startRemoteServer(kind); const browser = await connect(remoteServer.wsEndpoint()); @@ -753,7 +753,19 @@ for (const kind of ['launchServer', 'run-server'] as const) { } await input.setInputFiles(dir); - expect(new Set(await page.evaluate(e => [...e.files].map(f => f.webkitRelativePath), input))).toEqual(new Set([ + const serverFilesPromise = new Promise(fulfill => { + server.setRoute('/upload', async (req, res) => { + const form = new formidable.IncomingForm({ multiples: true, uploadDir: dir }); + form.parse(req, function(err, fields, f) { + res.end(); + fulfill(f.file1 as formidable.File[]); + }); + }); + }); + + await page.click('input[type=submit]') + + expect(new Set((await serverFilesPromise).map(f => f.originalFilename))).toEqual(new Set([ `${folderName}/file1.txt`, `${folderName}/file2`, `${folderName}/sub-dir/really.txt`, From 363074d6c2f16648d44f9a0a2802a1d7f0885b7c Mon Sep 17 00:00:00 2001 From: lhfmartin <44720140+lhfmartin@users.noreply.github.com> Date: Mon, 16 Feb 2026 17:45:42 +0000 Subject: [PATCH 4/5] Check content in input instead of what is uploaded to the server --- tests/library/browsertype-connect.spec.ts | 25 +++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/tests/library/browsertype-connect.spec.ts b/tests/library/browsertype-connect.spec.ts index 55be045006247..b8750a23c3bca 100644 --- a/tests/library/browsertype-connect.spec.ts +++ b/tests/library/browsertype-connect.spec.ts @@ -753,23 +753,22 @@ for (const kind of ['launchServer', 'run-server'] as const) { } await input.setInputFiles(dir); - const serverFilesPromise = new Promise(fulfill => { - server.setRoute('/upload', async (req, res) => { - const form = new formidable.IncomingForm({ multiples: true, uploadDir: dir }); - form.parse(req, function(err, fields, f) { - res.end(); - fulfill(f.file1 as formidable.File[]); - }); - }); - }); - - await page.click('input[type=submit]') - - expect(new Set((await serverFilesPromise).map(f => f.originalFilename))).toEqual(new Set([ + const webkitRelativePaths = await page.evaluate(e => [...e.files].map(f => f.webkitRelativePath), input) + expect(new Set(webkitRelativePaths)).toEqual(new Set([ `${folderName}/file1.txt`, `${folderName}/file2`, `${folderName}/sub-dir/really.txt`, ])); + + for (let i = 0; i < webkitRelativePaths.length; i++) { + const content = await input.evaluate((e, i) => { + const reader = new FileReader(); + const promise = new Promise(fulfill => reader.onload = fulfill); + reader.readAsText(e.files[i]); + return promise.then(() => reader.result); + }, i); + expect(content).toEqual(fs.readFileSync(path.join(dir, '..', webkitRelativePaths[i])).toString()); + } }); test('setInputFiles should preserve lastModified timestamp', async ({ connect, startRemoteServer, asset }) => { From 34eb769854a9913157e7a99ed1672c8b166634e3 Mon Sep 17 00:00:00 2001 From: lhfmartin <44720140+lhfmartin@users.noreply.github.com> Date: Mon, 16 Feb 2026 17:50:41 +0000 Subject: [PATCH 5/5] Format with eslint --- tests/library/browsertype-connect.spec.ts | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/library/browsertype-connect.spec.ts b/tests/library/browsertype-connect.spec.ts index b8750a23c3bca..42c34120de995 100644 --- a/tests/library/browsertype-connect.spec.ts +++ b/tests/library/browsertype-connect.spec.ts @@ -742,7 +742,7 @@ for (const kind of ['launchServer', 'run-server'] as const) { await page.goto(server.PREFIX + '/input/folderupload.html'); const input = await page.$('input'); - const folderName = 'folder-upload-test' + const folderName = 'folder-upload-test'; const dir = testInfo.outputPath(folderName); { await fs.promises.mkdir(dir, { recursive: true }); @@ -753,22 +753,22 @@ for (const kind of ['launchServer', 'run-server'] as const) { } await input.setInputFiles(dir); - const webkitRelativePaths = await page.evaluate(e => [...e.files].map(f => f.webkitRelativePath), input) + const webkitRelativePaths = await page.evaluate(e => [...e.files].map(f => f.webkitRelativePath), input); expect(new Set(webkitRelativePaths)).toEqual(new Set([ - `${folderName}/file1.txt`, - `${folderName}/file2`, - `${folderName}/sub-dir/really.txt`, - ])); - - for (let i = 0; i < webkitRelativePaths.length; i++) { - const content = await input.evaluate((e, i) => { - const reader = new FileReader(); - const promise = new Promise(fulfill => reader.onload = fulfill); - reader.readAsText(e.files[i]); - return promise.then(() => reader.result); - }, i); - expect(content).toEqual(fs.readFileSync(path.join(dir, '..', webkitRelativePaths[i])).toString()); - } + `${folderName}/file1.txt`, + `${folderName}/file2`, + `${folderName}/sub-dir/really.txt`, + ])); + + for (let i = 0; i < webkitRelativePaths.length; i++) { + const content = await input.evaluate((e, i) => { + const reader = new FileReader(); + const promise = new Promise(fulfill => reader.onload = fulfill); + reader.readAsText(e.files[i]); + return promise.then(() => reader.result); + }, i); + expect(content).toEqual(fs.readFileSync(path.join(dir, '..', webkitRelativePaths[i])).toString()); + } }); test('setInputFiles should preserve lastModified timestamp', async ({ connect, startRemoteServer, asset }) => {