Loslegen
Playwright Test Passes But Nothing Happens? Triage

Playwright Test Passes But Nothing Happens? Triage

Paste your Playwright, Puppeteer or Selenium symptom; get ranked causes, probe code and a read-back check.
#Recherche
Rating
Weitere Bewertungen erforderlich
Sold
0
How to use
Herunterladen

How it works

Browser Automation Silent-Failure Triage is for the case where a Playwright, Puppeteer or Selenium script says it worked and nothing changed: the log prints "saved", but the file is not uploaded, the form is not saved, the click did nothing.

Phase 1 — Restate the symptom. What the script did, what it reported, what the page or server actually shows, which framework, and what you already tried. Your own log lines are not treated as proof.

Phase 2 — Match the catalog. 14 known silent-failure causes (page not hydrated, disabled button, hidden overlay, wrong element matched, no file input, preview-without-upload, setInputFiles ignored, silent redirect, form posted to a page URL, hard limit with no message, toggle instead of add, autocomplete swallowing text, selector mismatch, late consent banner). Each candidate is ranked by the evidence you gave and tagged LIKELY / POSSIBLE / ruled out.

Phase 3 — Ordered probes. Copy-paste snippets (log every non-GET request, count file inputs, check what element covers the click point, force a change event) each with a decision rule: "if you see X, it is cause Y".

Phase 4 — Fix and read-back. After a probe result is in, the smallest fix and a check that reloads the page or asks the server to prove the result, instead of trusting that the click returned ok.

Sample output

Real, unedited output from running this Skill on a sample problem (an avatar upload that logs "saved" but the page still says "Please upload an avatar photo"):

## Symptom

1. **Action**: upload a file (`setInputFiles('input[type=file]', 'avatar.png')`), then click Save.
2. **What the script reported**: both calls resolved, no error, `console.log('saved')` printed. (Inference: "saved" is just your own log line and proves nothing.)
3. **What the page/server actually shows**: the preview shows the image right after setInputFiles; after Save the page shows the red line "Please upload an avatar photo."; after reload the old default avatar is back. Nothing was saved.
4. **Framework and runner**: Playwright (Node), headless, version "1.4x" (exact version unknown); a headed run gives the same result. Proxy: unknown.
5. **Already tried**: `waitForTimeout(5000)` before Save (same result); headed mode (same result). Observation: the network watcher only matches URLs containing `/api/`, and it saw nothing after Save. Not tried: logging all non-GET requests, checking file-input count, dispatching `change`.

Note: the two tries were each a single change, so they are attributable. They rule out a plain timing race and a headless-only problem.

## Likely causes

1. **#7 `setInputFiles` ignored (the app never registered the file)** — LIKELY — evidence: "Right after setInputFiles the avatar preview shows my image. After Save, the page shows a red line 'Please upload an avatar photo.'" The preview and the app's form state disagree, so the app's own validator says there is no file.
2. **#6 Upload preview without upload (multi-step upload)** — LIKELY — evidence: "the avatar preview shows my image" followed by "Please upload an avatar photo." The preview may be a local client-side render, and a separate upload request may be needed before Save.
3. **#10 Hard limit or validation with no UI message / hidden validator stops the click handler** — POSSIBLE — evidence: "red line ... 'Please upload an avatar photo.'" and "none [requests] after Save". Here the validator does show a message, but the effect is the one in the catalog: the save request is never sent.
4. **#9 Save went to a page URL, not an API URL** — POSSIBLE — evidence: "I only watch network requests whose URL matches /api/ and I see none after Save." Your filter could be hiding a request to a page URL. The validation message argues against this, but it is not ruled out until you log every non-GET request.
5. **#5 No `input[type=file]` in the DOM / wrong input matched (#4 also applies)** — POSSIBLE — evidence: the selector is a bare `input[type=file]`. If the page has more than one such input (or a hidden duplicate), the file may have gone to a different one than the one the form reads. Unconfirmed: you did not say how many exist.

Not matched: #1 (not hydrated: the preview reacted, so some client JS runs), #2 (you say Save looks enabled; the validation message shows the click handler ran), #3 (you say nothing covers it; unverified by `elementFromPoint`, but the handler evidently fired), #8 (no redirect reported), #11 (not a toggle), #12 (no text field), #13 (not a selector/attribute problem on the Save button), #14 (no consent banner or page sequence mentioned).

Inference note: the ranking above is inference from your description. No cause is confirmed until a probe result is in this conversation.

## Probes

Default framework: Playwright for Node (as you use). Replace placeholders with values from your page; I have not invented any selectors.

**Probe 1 — Did anything leave the browser, and where did I land? (separates #9 from #6/#7/#10)**

Attach before the actions, with no `/api/` filter.

```js
page.on('request', r => {
  if (r.method() !== 'GET') console.log('REQ', r.method(), r.url());
});
page.on('requestfailed', r => console.log('FAILED', r.method(), r.url(), r.failure()?.errorText));
page.on('response', r => {
  if (r.request().method() !== 'GET') console.log('RES', r.status(), r.url());
});

await page.setInputFiles('input[type=file]', 'avatar.png');
console.log('after setInputFiles: non-GET requests above (if any) = upload step');
await page.getByRole('button', { name: 'Save' }).click();
await page.waitForTimeout(1500);
console.log('url:', page.url(), 'title:', await page.title());

Decision rule:

  • A POST/PUT/PATCH to a non-/api/ URL appears after Save: cause #9. Your filter hid it; look at the response status and body next.
  • A request appears after setInputFiles but none after Save: the upload step exists. Go to cause #6 and check the response (did it return a file id the form needs?).
  • No non-GET request at all, ever: the client-side validator stopped the handler (#10) or the app never saw the file (#7). Go to Probe 2.
  • The URL or title changed unexpectedly: cause #8 (silent redirect). Not expected here, but this costs nothing to read.

Probe 2 — Is there exactly one file input, and does it hold the file? (separates #7 and #5)

const info = await page.evaluate(() =>
  [...document.querySelectorAll('input[type=file]')].map((el, i) => ({
    i,
    files: el.files.length,
    name: el.files[0]?.name,
    visible: !!(el.offsetWidth || el.offsetHeight),
    disabled: el.disabled,
    name_attr: el.getAttribute('name'),
    inForm: !!el.form,
  }))
);
console.log(JSON.stringify(info, null, 2));

Run it after setInputFiles and before clicking Save.

Decision rule:

  • More than one input, and the one holding files: 1 is not the one inside your profile form: cause #5/#4. Target the right input with a more specific locator (look up its name or the form it belongs to).
  • Exactly one input and files: 1, but the Save still says no photo: the app ignored the set files (#7). Go to Probe 3.
  • Zero inputs, or files: 0: the input was replaced or re-rendered after you set it. Set the files again after the preview appears, and re-run this probe.

Probe 3 — Force the event (only if Probe 2 shows one input with the file; tests #7)

await page.evaluate(() => {
  const el = document.querySelector('input[type=file]');
  el.dispatchEvent(new Event('input',  { bubbles: true }));
  el.dispatchEvent(new Event('change', { bubbles: true }));
});
await page.getByRole('button', { name: 'Save' }).click();

Decision rule:

  • Save now sends a request and the red line is gone: cause #7. The app only reacts to a manual change.
  • Same red line, still no request: the app keeps the file somewhere other than the input (for example a separate upload step, cause #6). Go back to Probe 1 and look for a request right after the file is chosen, or send me the page's relevant form markup.

I did not give a probe for #3 or #2: you reported nothing covers the button and it looks enabled, and the validation text proves the click handler ran, so those probes would not change what you do next.

Paste back: the console output of Probe 1, the JSON of Probe 2, and the result of Probe 3.

Fix + read-back check

Not yet. You have not reported a probe result and have not asked me to proceed, so naming a fix now would be guessing. Once a probe result is in the conversation, I will give the smallest fix for the confirmed cause, a read-back check that reloads the profile page in a fresh page load (or does a GET on the profile) and compares the avatar URL/size to what you uploaded, an idempotence note, and one line of residual doubt.


## Use cases

- A Playwright upload or save step "passes" but the data never reaches the server
- A click or fill works on your machine and does nothing in headless or CI
- Test automation that reports green while the page state is unchanged
- Works inside Claude Code, Codex, or OpenClaw — paste the symptom and your script lines and go

## FAQ

**Does it run my script?** No — it reads your description and gives you probes to run; you paste the results back.

**Will it fix everything?** It covers 14 known causes. If none match, it says so instead of inventing one.

**Can it get past bot protection, CAPTCHAs or login walls?** No, and it will not try.

**What about sensitive info?** Remove passwords, tokens and customer data before pasting. The Skill does not fetch or store your text anywhere on its own.