Skip to content

Test a PWA

Published

At the end of this guide you can answer, from Chrome DevTools, why a page is or is not installable, step a service worker through install, waiting, and activation on demand, simulate offline without unplugging the machine, and confirm the install flow on a real Android device. The Application panel does all of it; Lighthouse’s PWA category is deprecated and is not part of the procedure.

You need the app served over HTTPS or localhost, Chrome with DevTools, and for the last step an Android phone with USB debugging enabled. The names below are the English DevTools labels.

1. Read the manifest and its Installability section

Section titled “1. Read the manifest and its Installability section”

Open DevTools, select Application, then Manifest. The Identity and Presentation sections show the manifest fields in readable form, Icons lists each declared icon (the Show only the minimum safe area for maskable icons checkbox previews the cropped safe area), and Shortcut #N and Screenshot #N sections follow. When an icon fails to load or a required field is missing, an Installability section appears with the reason. Keep the Console drawer open while you click the address bar’s Install button: it logs manifest problems and the install lifecycle.

A manifest that passes has at least this:

{
"name": "Example PWA",
"short_name": "Example",
"start_url": "/",
"scope": "/",
"display": "standalone",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
]
}

The full list of conditions is in Installability criteria: what makes a PWA installable.

2. Drive the worker from the Service workers pane

Section titled “2. Drive the worker from the Service workers pane”

Application > Service workers lists the registration for the open page with its Source, Status, and Clients lines. The controls, and when to use each:

  • Offline puts DevTools into offline mode, the same as the Network panel’s Offline throttling preset. Reload with it checked to see what the worker serves without a network.
  • Update on reload refetches the worker script on every navigation, installs it even when it is byte-identical so install runs again, skips the waiting phase, and then navigates. It removes the “close every tab” step while you edit sw.js; turn it off before you test the real update path.
  • Bypass for network sends requests straight to the network, which tells you whether a bug lives in the worker or in the page.
  • Push and Sync fire a push event with the typed payload and a sync event without a server.
  • stop halts the running worker; the next event starts it with fresh global state, which surfaces code that assumed in-memory variables survive.
  • Unregister removes the registration; Update performs a one-time update check.

The Update Cycle table shows the worker’s activities and elapsed times, such as install, wait, and activate; the Expand buttons reveal exact timestamps.

3. Detect a registration before asserting on it

Section titled “3. Detect a registration before asserting on it”

A test harness that assumes navigator.serviceWorker exists throws in browsers without the API, and getRegistration() resolves with undefined when nothing is registered for the scope. Check both so the harness reports a reason instead of a stack trace.

export async function serviceWorkerState() {
if (!('serviceWorker' in navigator)) {
return { ok: false, reason: 'Service workers are not supported in this browser.' };
}
const registration = await navigator.serviceWorker.getRegistration();
if (!registration) {
return { ok: false, reason: 'No service worker is registered for this page yet.' };
}
const worker = registration.active || registration.waiting || registration.installing;
return { ok: true, state: worker ? worker.state : 'unknown', scope: registration.scope };
}

Run it from the Console: (await serviceWorkerState()).state prints activated once the first install has finished.

4. Install on a real phone over remote debugging

Section titled “4. Install on a real phone over remote debugging”

Desktop Chrome’s Install button cannot reproduce the Android flow (WebAPK minting, the home screen icon, the splash screen), and the Lighthouse PWA audits that once covered this are deprecated in favour of the installability criteria and this panel. Connect the phone over USB, open chrome://inspect/#devices on the desktop, select the page, and in Chrome on the phone open the three-dot menu and choose Install app (or Add to Home screen on some devices). The desktop DevTools instance attached to the phone shows the same Manifest and Service workers panes, so the Installability section from step 1 applies to the device you are holding. When the icon appears on the home screen and the app launches full-screen with the manifest’s theme_color, the install path is verified.

← Back to the Guides overview.