TESTEROPS

A pragmatic approach to QA and OPS

Working with File Uploads in Playwright

In this article, we will explore how to work with file uploads in Playwright, a Node.js library that allows you to automate browser interactions for end-to-end testing and web scraping.

First, let’s start by installing Playwright:

npm install playwright

Next, we can use the following code to launch a browser and navigate to a website that has a file upload form:

const playwright = require('playwright');

(async () => {
  const browser = await playwright.chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();

  await page.goto('https://example.com/upload');
})();

Now let’s consider an actual webpage that has a upload form and see if we can upload a file. I’ve selected this url so that I can give a simple demo of how to upload a file.

For file uploads we will follow two approaches – using a default approach provided by Playwright docs and another approach using the dispatchEvent method.

Approach 1

As per playwright documentation, we can use the locator.setInputFiles() method to set an file location to an input element for a form upload.

Directly copying from documentation, we can see the different ways of file upload

// Select one file
await page.getByLabel('Upload file').setInputFiles('myfile.pdf');

// Select multiple files
await page.getByLabel('Upload files').setInputFiles(['file1.txt', 'file2.txt']);

// Remove all the selected files
await page.getByLabel('Upload file').setInputFiles([]);

// Upload buffer from memory
await page.getByLabel('Upload file').setInputFiles({
  name: 'file.txt',
  mimeType: 'text/plain',
  buffer: Buffer.from('this is test')
});

Let’s use this in our sample url. I’ve copied a simple file and given the absolute path of the file

/// <reference lib="dom"/>
import { createDataTransfer } from "playwright-utilities";
import { resolve } from "node:path";
import { chromium,test } from "@playwright/test";
test.use({ viewport: { width: 1400, height: 1000 } });
test('Launch the Selectors hub test page',async()=>{
const browser = await chromium.launch({
headless: false
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto("https://cgi-lib.berkeley.edu/ex/fup.html&quot;);
await page.waitForTimeout(5000);
const element1 = page.locator("input[name='upfile']");
await element1.setInputFiles("/Users/Rahul_Yadav/Downloads/shub.png");
await page.locator("input[value='Press']").click();
await page.waitForTimeout(5000);
});
view raw upload1.js hosted with ❤ by GitHub

Now from the screenshot we can see that the file is uploaded

Approach 2

In this second approach, we will use the dispatchEvent method to send a file element to a locator. I’ve got this sample code from this link, which was actually given in a github ticket from Playwright.

Later I found that there is a npm utitlity already created for this – which is named playwright-utilities that can be used to call this method directly.

So first we’ll install this

npm i playwright-utilities

Next we will call this in our code and then set the file element like this

import { createDataTransfer } from "playwright-utilities";
import { resolve } from "node:path";

await createDataTransfer({
  filePath: resolve(__dirname, "foo.png"),
  fileName: "foo.png",
  fileType: "image/png",
});

Now we’ll run this code-piece

/// <reference lib="dom"/>
import { createDataTransfer } from "playwright-utilities";
import { resolve } from "node:path";
import { chromium,test } from "@playwright/test";
test.use({ viewport: { width: 1400, height: 1000 } });
test('Launch the Selectors hub test page',async()=>{
const browser = await chromium.launch({
headless: false
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto("https://cgi-lib.berkeley.edu/ex/fup.html&quot;);
await page.waitForTimeout(5000);
const dataTransfer = await createDataTransfer({
page,
filePath: "/Users/Rahul_Yadav/Downloads/shub.png",
fileName: "shub.png",
fileType: "image/png",
});
await page.dispatchEvent("input[name='upfile']", "drop", { dataTransfer });
await page.waitForTimeout(3000);
await page.locator("input[value='Press']").click();
await page.waitForTimeout(3000);
});
view raw upload2.js hosted with ❤ by GitHub

Once you run this, the file will be uploaded also, but there is one difference – for some reason, it doesn’t show on the UI that file has been attached. However the page says that the file has been uploaded.

Now it’s upon you to decide which one to follow. I think the first one is pretty simple and will work in case you have an input element present for the upload file. If there is no input element present for upload file, then may be use the second one.

Now there is one thing that I’ll try and post in future – how can we use this to upload file inside an iframe – that is a future item for me.

%d bloggers like this: