Answer
File Uploads in Playwright
Basic File Upload (Native Input)
TypeScript
// Upload a single file
await page.getByLabel('Upload File').setInputFiles('tests/fixtures/resume.pdf');
// Upload multiple files
await page.getByLabel('Upload Photos').setInputFiles([
'tests/fixtures/photo1.jpg',
'tests/fixtures/photo2.jpg',
]);
Upload with CSS Locator
TypeScript
await page.locator('input[type="file"]').setInputFiles('tests/fixtures/document.pdf');
Remove Files (Clear Upload)
TypeScript
await page.locator('input[type="file"]').setInputFiles([]);
Upload with File Buffer (Dynamic Files)
TypeScript
// Create file content in memory
await page.locator('input[type="file"]').setInputFiles({
name: 'test-file.txt',
mimeType: 'text/plain',
buffer: Buffer.from('Hello, World! This is test content.'),
});
// Upload a dynamically created JSON file
await page.locator('input[type="file"]').setInputFiles({
name: 'config.json',
mimeType: 'application/json',
buffer: Buffer.from(JSON.stringify({ env: 'test', version: '1.0' })),
});
Hidden File Input (Custom Upload Button)
When the <input type="file"> is hidden and triggered by a custom button:
TypeScript
// Method 1: Directly set files on the hidden input
await page.locator('input[type="file"]').setInputFiles('resume.pdf');
// Method 2: Wait for file chooser dialog
const [fileChooser] = await Promise.all([
page.waitForEvent('filechooser'),
page.getByRole('button', { name: 'Choose File' }).click(),
]);
await fileChooser.setFiles('tests/fixtures/resume.pdf');
Drag and Drop File Upload
TypeScript
// Simulate file being dragged onto a drop zone
const dropZone = page.locator('.drop-zone');
await dropZone.dispatchEvent('drop', {
dataTransfer: await page.evaluateHandle(() => {
const dt = new DataTransfer();
// Note: Full file drag-drop requires additional setup
return dt;
}),
});
Verify Upload Success
TypeScript
import { test, expect } from '@playwright/test';
import path from 'path';
test('upload profile picture', async ({ page }) => {
await page.goto('/profile/edit');
const filePath = path.join(__dirname, 'fixtures', 'profile.jpg');
await page.locator('input[type="file"]').setInputFiles(filePath);
// Verify preview appears
await expect(page.locator('.image-preview img')).toBeVisible();
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('.success-toast')).toContainText('Profile updated');
});
