'Playwright: Upload files from non-input element that cannot be used page.setInputFiles?

I'm working on uploading files through non-input HTML tag on Playwright.

For example, you can use setInputFiles like this, and this works:

await page.setInputFiles('input[type="file"]', './headphone.png')

But apparently setInputFiles only works for input element, something like this will be error:

await page.setInputFiles('label.ImageUpload__label ', './headphone.png');

The HTML I'm working on is like this:

<div id="ImageUpload" class="ImageUpload u-marginB10">
        <label class="ImageUpload__label js-dragdrop-area" for="selectFileMultiple">
            <span class="ImageUpload__hide">drag and drop or select files</span>
            <span class="ImageUpload__text"><span class="js-dragdrop-num">10</span>up to</span>
        </label>
</div>

So, is it possible to upload files to such HTML elements with Playwright?



Solution 1:[1]

NodeJs: https://playwright.dev/python/docs/api/class-filechooser

        page.on("filechooser", (fileChooser: FileChooser) => {
             fileChooser.setFiles(["/path/to/a/file"]);
        })

Python: https://playwright.dev/python/docs/api/class-filechooser/

with page.expect_file_chooser() as fc_info:
    page.click("upload")
file_chooser = fc_info.value
file_chooser.set_files("/path/to/a/file")

Java: https://playwright.dev/java/docs/api/class-filechooser

FileChooser fileChooser = page.waitForFileChooser(() -> 
page.click("upload"));
fileChooser.setFiles(Paths.get("myfile.pdf"));

Solution 2:[2]

I had the same issue so I decided to use AutoIt to upload files with Playwright.

AutoIt v3 is a freeware BASIC-like scripting language designed for automating Windows GUI and general scripting.

I used AutoIT to handle the Windows File Upload dialog, which cannot be handled using Playwright.


Creating Script

  1. Download AutoIt: https://www.autoitscript.com/site/autoit/downloads/
  2. Open SciTE Script Editor and type the followng:
WinWaitActive("Choose files")
Send("C:\ChromeDriver\text.txt") 
Send("{ENTER}")

If it does not work, change Choose files to whatever title is on the top left of the upload dialog.

  1. Click save and name it something like upload.au3 and save it in the root directory of your test.

Example of Save Location

  1. Right click your newly created file and click Compile Script

Executing the script in your test

Create execFile function of child process modules in node.js. Reference: https://nodejs.org/api/child_process.html#child_process_child_process_execfile_file_args_options_callback

Add this to the top of your .spec.ts test file:

var exec = require('child_process').execFile;
var upload_script = function(){
   exec('upload.exe', function(err, data) {  
        console.log(err)                  
    });  
}

Open the upload dialog, then call the function in your test

// Click Browse
await page.locator('#browse').click();

// Execute Upload Script
upload_script();
  

You have to run your test headed or it will not work:

npx playwright test --headed

Solution 3:[3]

Found another alternative to upload that worked in my case. We create a buffer from memory and drag and drop the file to the upload button.

// Read your file into a buffer.
const buffer = readFileSync('file.pdf');

// Create the DataTransfer and File
const dataTransfer = await scope.page.evaluateHandle((data) => {
    const dt = new DataTransfer();
    // Convert the buffer to a hex array
    const file = new File([data.toString('hex')], 'file.pdf', { type: 'application/pdf' });
    dt.items.add(file);
    return dt;
}, buffer);

// Now dispatch
await page.dispatchEvent('YOUR_TARGET_SELECTOR', 'drop', { dataTransfer });

if using typescript, add this to the top of the file:

import {readFileSync} from 'fs';

Github issue: https://github.com/microsoft/playwright/issues/10667#issuecomment-998397241

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Rodrigo Akio
Solution 3 Rodrigo Akio