Playwright, fully offline, MIT

Tests that heal themselves.

When a selector changes but the element is still there, selfmend reconnects your test and keeps it green. And it never fakes a pass.

$ npm i -D selfmend How to add it View source

Why tests break for no real reason

Most failing end-to-end tests are not real bugs. A developer renames a CSS class or moves a button, and every test pinned to the old selector goes red, even though the app works perfectly. Teams burn hours fixing tests that never caught a real failure, and slowly stop trusting the suite. selfmend absorbs that churn so the suite stays useful.

Add it in one step

No test rewrites. Pick the path that matches how you run Playwright.

Using @playwright/test

Change one import. Your existing tests do not change.

- import { test, expect } from "@playwright/test";
+ import { test, expect } from "selfmend";

Any other framework

Cucumber, Mocha, Jest, or a plain script. Wrap the page once.

import { wrapPage } from "selfmend";

// once, where you create the page
this.page = wrapPage(rawPage, {
  store,
  scope: () => ({ suite: feature, test: scenario }),
});

What to expect

selfmend does three things, in order. Nothing talks to a network at any point.

1

It learns on green

When a test passes, selfmend records a fingerprint of each element it touched: visible text, role, test id, position. It saves them to a plain local JSON file.

2

It heals on break

Later a selector breaks. After Playwright's normal timeout, selfmend scores the page. Only if one element clearly matches above a confidence floor does it reconnect your locator and replay the action. The test stays green.

3

It reports, honestly

Every run prints what healed and what did not. If nothing matches confidently, selfmend does nothing and the test fails normally, exactly as it would today.

selfmend report, end of run
┌───────────────────────────────────────────────────────────────────┐
 selfmend: 1 locator healed                                        
 checkout                                                          
   page.locator(.btn-primary) -> [data-testid="place-order"]  (0.97) 
└───────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
 selfmend: 1 locator could NOT heal                       
 checkout                                                  
   page.locator(.promo-link) x no-candidates  (best n/a)  
└─────────────────────────────────────────────────────────┘

The first box: a renamed button was reconnected with 0.97 confidence, green. The second: an element that was genuinely removed, which selfmend refused to fake. That refusal is the point.

The one promise: it never fakes a green

selfmend only heals when it is highly confident the element is the same one, and clearly not a look-alike. Otherwise the test fails exactly as it would today. The worst case is a missed heal you handle by hand, never a real bug hidden behind a false pass.

Offline. No network calls Private. No telemetry, no API key Yours. The baseline is a local file you own Free. MIT licensed

What it does not do

So expectations stay honest.

  • It does not write your tests. You still decide what to check.
  • It does not fix real bugs. If the product is broken, the test fails.
  • It does not silently rewrite your code. It reconnects at run time and reports it.
  • It is a safety net for selector churn, not a reason to skip stable selectors. Treat a heal as a heads-up to update a selector later.