Blog # 15: How to Upload and Remove Files with Playwright

Published on April 10, 2025

Have you ever found yourself dragging and dropping files into a browser during testing and thinking, "There’s got to be a better way…”?

Yeah, me too.

Lately, while learning Playwright and exploring UI automation, I ran into the classic file upload challenge. You know the one — that sneaky element that just doesn’t play nice with regular click actions.

That’s when Playwright swooped in like a superhero. 🦸‍♂️ Let me walk you through how I tamed file uploads (single and multiple!) with just a few lines of code. 


🚀 Mission 1: Upload a Single File Like a Pro

Here's what I started with:

onst { test, expect } = require('@playwright/test');
const path = require('path');

test('Test Upload File', async ({ page }) => {
    // Step 1: Go to the battlefield (a demo site)
    await page.goto('https://testautomationpractice.blogspot.com/');
    
    // Step 2: Wait for the upload field to load (patience)
    await page.waitForSelector('#singleFileInput');

    // Step 3: Find the file path (no "404 tears" here)
    const filePath = path.resolve('tests/FilesToUpload/invite1.pdf');
    
    // Step 4: Inject the file like a vaccine 💉
    await page.locator('#singleFileInput').setInputFiles(filePath);

    // Step 5: Click the upload button (mic drop)
    await page.getByText('Upload Single File').click();
});

🎯 What’s happening here?

  • We navigate to a demo site.

  • Use setInputFiles() to inject a file directly into the upload field (no need for a file picker!).

  • Then click the upload button like a boss.

✨ And boom! File uploaded without lifting a finger (literally).


🧠 But Wait, What About Multiple Files?

Challenge accepted. I wanted to go beyond just one file. So, I targeted another playground: David Walsh’s file upload demo.

Here’s the code:

test('Multiple files upload', async({ page }) => {
    // Step 1: Visit the multi-upload playground
    await page.goto('https://davidwalsh.name/demo/multiple-file-upload.php');

    // Step 2: Upload two files like a boss
    await page.locator('#filesToUpload').setInputFiles([
        'tests/FilesToUpload/invite1.pdf',
        'tests/FilesToUpload/invite2.pdf'
    ]);

    // Step 3: Verify the files exist (trust, but verify)
    await expect(page.locator('#fileList li:nth-child(1)')).toHaveText('invite1.pdf');
    await expect(page.locator('#fileList li:nth-child(2)')).toHaveText('invite2.pdf');

    // Step 4: Pause for dramatic effect 🎬
    await page.waitForTimeout(5000);

    // Step 5: Delete files & verify 
    await page.locator('#filesToUpload').setInputFiles([]);
    await expect(page.locator('#fileList li')).toHaveText('No Files Selected');
});


🔍 What I Love Here:

  • File selection is as simple as passing an array.

  • You can even clear the upload with setInputFiles([]).

  • Assertions confirm the right files were picked and later removed.


🧩 Final Thoughts: Why This Matters

Whether you're a beginner in test automation (like I was not too long ago!) or someone refining their Playwright skills, handling file uploads is a must-have trick in your toolkit.

It’s clean. It’s fast. It’s powerful.

File uploads: mastered. Time saved. Coffee earned. ☕