Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
“Load local resources” in Playwright can mean several different operations. Use page.setContent() for an HTML string, page.addScriptTag({ path }) or page.addStyleTag({ path }) for one local asset, route.fulfill({ path }) when a browser request must be answered from disk, a local web server with baseURL for a complete application, and locator.setInputFiles() when the test is selecting an upload. Choosing the API that matches the job avoids misleading tests and path errors.
Choose the operation first
| What you need | Use | What it actually does |
|---|---|---|
| Render an HTML string | page.setContent(html) |
Replaces the document with markup supplied in memory. |
| Inject one local JavaScript file | page.addScriptTag({ path }) |
Adds a script element whose source is read from the filesystem. |
| Run code before page scripts | page.addInitScript({ path }) |
Installs an initialization script before navigated page scripts execute. |
| Inject one local stylesheet | page.addStyleTag({ path }) |
Adds a stylesheet from a filesystem path. |
| Serve a fixture such as JSON through a URL | page.route() or context.route() plus route.fulfill({ path }) |
Intercepts matching browser traffic and returns a local file as the response. |
| Test a complete local app | Local server, webServer, and baseURL |
Exercises ordinary URL navigation and the app’s normal asset pipeline. |
| Test a file chooser | locator.setInputFiles() |
Selects a file for an input[type=file]; it does not load a page asset. |
For all documented filesystem path options, a relative path is resolved from the process current working directory, not automatically from the test file’s directory. Use an absolute path or construct one deliberately when that distinction matters.
Render local HTML with page.setContent()
Use this for a small, isolated document or markup held in a string. It is useful for component fixtures, email-like layouts, and fast unit-style browser checks where URL navigation is not part of the behavior under test.
import { test, expect } from '@playwright/test';
test('renders an HTML fixture', async ({ page }) => {
const html = `
<!doctype html>
<html>
<head><title>Fixture</title></head>
<body><main data-testid="content">Hello</main></body>
</html>`;
await page.setContent(html);
await expect(page.getByTestId('content')).toHaveText('Hello');
});
setContent internally calls document.write(), so it has the characteristics of that browser operation. It is not a substitute for starting your application’s server: server routing, bundling, origin behavior, and production-like asset loading are absent unless you recreate them.
#1 Best Overall
- Easily store and access 2TB to content on the go with the Seagate Portable Drive, a USB external hard drive
- Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop
- To get set up, connect the portable hard drive to a computer for automatic recognition no software required
- This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
- The available storage capacity may vary.
Referencing assets from injected markup
An <img src="..."> or stylesheet URL in the string still needs a browser-resolvable URL. If the test is about the asset itself, inject it with the APIs below or serve the fixture over HTTP. Avoid assuming that a direct file:// navigation behaves consistently across browser engines; the documented guidance here does not establish a cross-engine recommendation for that approach.
Inject a local JavaScript file
page.addScriptTag reads a file and adds it to the current page. The path may be relative to the process working directory or absolute.
import path from 'node:path';
import { test, expect } from '@playwright/test';
test('loads a local script', async ({ page }) => {
const scriptPath = path.resolve('fixtures/widget.js');
await page.goto('about:blank');
await page.addScriptTag({ path: scriptPath });
await expect.poll(() => page.evaluate(() => window.widgetReady)).toBe(true);
});
If the script must run before the application’s own scripts, use an initialization script:
await page.addInitScript({ path: path.resolve('fixtures/test-hooks.js') });
await page.goto('http://127.0.0.1:3000/');
Initialization scripts are appropriate for deterministic shims, feature flags, or browser API setup. They do not turn a local file into a network response; they execute JavaScript in the page context.
Rank #2
- Easily store and access 5TB of content on the go with the Seagate portable drive, a USB external hard Drive
- Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop
- To get set up, connect the portable hard drive to a computer for automatic recognition software required
- This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
- The available storage capacity may vary.
Inject a local CSS file
import path from 'node:path';
import { test, expect } from '@playwright/test';
test('loads fixture CSS', async ({ page }) => {
await page.setContent('<button class="notice">Save</button>');
await page.addStyleTag({ path: path.resolve('fixtures/notice.css') });
await expect(page.locator('.notice')).toHaveCSS('display', 'block');
});
addStyleTag is best for a targeted stylesheet. If you need to verify how the application discovers CSS through its bundler, links, preload hints, or server headers, run the application normally instead.
Serve a local file as a browser response
When page code requests a URL such as /fixtures/data.json, intercept it and fulfill the request from disk. This preserves the browser-facing request shape while keeping the fixture local.
import path from 'node:path';
import { test, expect } from '@playwright/test';
test('fulfills an API request from a fixture', async ({ page }) => {
await page.route('**/fixtures/data.json', route =>
route.fulfill({ path: path.resolve('fixtures/data.json') })
);
await page.goto('http://127.0.0.1:3000/dashboard');
await expect(page.getByTestId('account-name')).toHaveText('Ada');
});
Playwright infers the response content type from the file extension. Use a page route when only one page needs the behavior; use context.route when every page in a browser context should receive the fixture.
const context = await browser.newContext();
await context.route('**/images/logo.png', route =>
route.fulfill({ path: path.resolve('fixtures/logo.png') })
);
const page = await context.newPage();
Routing caveats
- Routing disables HTTP cache. A cache-focused test can therefore produce different results while the route is installed.
- Match the actual request URL, including query strings where relevant; a pattern that is too narrow will never run.
- Keep fixture paths explicit. A typo generally appears as a route failure or missing response rather than a useful application error.
Use a local server for a whole application
For end-to-end tests, the closest representation of deployment is usually your app’s local development or preview server. Playwright Test can start it and resolve relative navigation through baseURL.
Rank #3
- Easily store and access 1TB to content on the go with the Seagate Portable Drive, a USB external hard drive.Specific uses: Personal
- Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop. Reformatting may be required for Mac
- To get set up, connect the portable hard drive to a computer for automatic recognition no software required
- This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
- The available storage capacity may vary.
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
baseURL: 'http://127.0.0.1:3000'
},
webServer: {
command: 'npm run dev -- --host 127.0.0.1',
url: 'http://127.0.0.1:3000',
reuseExistingServer: true
}
});
import { test, expect } from '@playwright/test';
test('opens a local route', async ({ page }) => {
await page.goto('/settings');
await expect(page).toHaveURL(//settings$/);
await expect(page.getByRole('heading', { name: 'Settings' })).toBeVisible();
});
This approach exercises URL resolution, server middleware, bundled assets, cookies, redirects, and cross-origin behavior in a way that direct markup injection cannot. page.goto waits for the load event, including dependent stylesheets, scripts, frames, and images. Modern applications can continue fetching lazy content afterward, so wait for the specific state your assertion needs.
await page.goto('/reports');
await page.getByRole('heading', { name: 'Reports' }).waitFor();
await expect(page.getByTestId('report-row')).toHaveCount(10);
Upload a local file instead of loading an asset
If the user action is choosing a file, target the file input. This is separate from loading HTML, CSS, JavaScript, or images into the page.
import path from 'node:path';
import { test, expect } from '@playwright/test';
test('uploads a fixture', async ({ page }) => {
await page.goto('/import');
await page.locator('input[type=file]').setInputFiles(
path.resolve('fixtures/orders.csv')
);
await expect(page.getByText('orders.csv')).toBeVisible();
});
The same method accepts in-memory file data, which is useful when a test should not depend on a checked-in fixture:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
await page.locator('input[type=file]').setInputFiles({
name: 'hello.txt',
mimeType: 'text/plain',
buffer: Buffer.from('hello')
});
Path resolution and readiness checklist
- Print or inspect
process.cwd()when a relative path unexpectedly fails. - Resolve paths from a known project root or from the test file’s location; do not assume the runner changes the working directory.
- Use
setContentonly when an in-memory document is the subject of the test. - Use route fulfillment when application code must make a normal request and receive a deterministic local response.
- Use
webServerandbaseURLwhen navigation and the real asset pipeline matter. - After navigation, wait for an observable application condition rather than treating the
loadevent as proof that lazy data is ready.
Common failures and fixes
“File not found” despite a correct-looking path
The relative path is based on the process current working directory. Log process.cwd(), then use an absolute path or build one from a deliberate root.
Rank #4
- Easily store and access 4TB of content on the go with the Seagate Portable Drive, a USB external hard drive.Specific uses: Personal
- Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop
- To get set up, connect the portable hard drive to a computer for automatic recognition no software required
- This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
- The available storage capacity may vary.
The route handler never runs
The URL pattern does not match the request, the route was installed after navigation, or another handler handled it first. Register routing before goto, inspect the requested URL, and broaden the pattern temporarily to diagnose.
The page is blank after setContent
The supplied string may be empty, malformed, or dependent on scripts and styles that were never injected. Start with minimal markup, then add addScriptTag, addStyleTag, or a server-backed page as appropriate.
Assertions run before lazy content appears
goto reaching load does not guarantee that post-load fetches or lazy images have completed. Wait for a locator, a response, or a domain-specific ready marker.
Cache behavior changed under a route
Playwright routing disables HTTP cache. Remove the route for cache tests, or design the test to account for interception.
Best Value
- [Upgraded Version] - This external hard drive features a mirrored logo stripe combined with a striped anti-slip design, and the rounded corners of the casing make it easier to grip. The stripes also have a heat dissipation function, ensuring stable and fast data transfer.
- 【Ultra-thin and quiet】 - The motherboard adopts JMicron 578 noise-free solution, giving you a quiet working environment. Lightweight and portable size designed to fit in your pocket for easy portability.
- 【Ultra-Fast Data Transfers】 - Pairing this external hard drive with JMicron 578 solution USB 3.0 and USB 2.0 interfaces enables blazing-fast data transfer. It boasts theoretical read speeds of up to 125MB/s and write speeds of up to 103MB/s.
- 【Plug and Play】 - With no software to install, just plug it in and the drive is ready to use.The hard disk chip is wrapped with an aluminum anti-interference layer to increase heat dissipation and protect data.
- 【What You Get】 - 1 x Portable Hard Drive, 1 x USB 3.0 Cable, 1 x User Manual, Gift-type shell packaging ,Three-year manufacturer's warranty and free technical support services.
The upload test changes the wrong element
setInputFiles requires the file input (or a locator associated with it), not a visible filename label or arbitrary button. Locate input[type=file] or use the page’s accessible upload control.
Or skip the browser setup
If your goal is simply to create a clean screenshot of a local or public page rather than test browser behavior, ScreenshotNeo provides a single HTTP request. Its API accepts cookie banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. It also offers an MCP server for AI clients such as Claude and Cursor.
See the ScreenshotNeo API documentation for the complete option list, including full-page captures, CSS selectors, device presets, custom CSS and JavaScript, waits, request blocking, cookies, headers, PDFs, caching, signed links, asynchronous jobs, and bulk capture.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutecurl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
There is a free allowance of 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.
Which method should you choose?
Use the smallest tool that still models the behavior you care about: setContent for markup, script/style injection for individual assets, routing for request-level fixtures, a configured server for the application, and setInputFiles for uploads. This keeps tests explicit about whether they are checking rendering, network behavior, deployment-like navigation, or user file selection.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

