Skip to content

← All use cases

A sidebar navigation entry that a product rename moved out from under the suite

Ten scenarios, one stale label: "Fleet" became "AGENTS"

What makes it hard

Ten of ten scenarios in a module failed, all on the same navigation step. The heal log makes the cause unambiguous:

json
{
  "action": "click",
  "originalSelector": "getByRole('link', { name: 'Fleet' })",
  "candidates": [
    { "strategy": "role",         "count": 0 },
    { "strategy": "text-exact",   "count": 0 },
    { "strategy": "text-partial", "count": 0 }
  ],
  "succeeded": false
}

Every strategy returned zero. The string was not on the page in any form — the section had been renamed. Self-healing cannot invent a name that does not exist; it recovers from a moved element, not from a deleted one.

Two details made it worse than a rename:

  • the project YAML still carried title: "Fleet" for the module, so the report labelled the failure with a name nobody in the product would recognise
  • the destination was no longer a link at all. It had become a collapsible section header showing a count. Even the correct name would not have satisfied a click.

Ten heal attempts, zero heals, across the whole run. Which is the one piece of good news: no pass in that run was carried by a healed selector.

How to cover it

This is the locator-priority rule presenting its bill. Visible copy is the most volatile thing on a page — it changes for a product decision, a marketing decision or a translation, none of which anyone tells the test team about. A test id survives all three; getByRole('link', { name: 'Fleet' }) survives none of them.

Concretely:

  • Move navigation onto a test id and ask for data-testid="nav-<key>" per row. Navigation is the single highest-fan-in locator in any suite; it is worth an attribute.
  • Give the heal context every handle you have, and one you do not yet have:
ts
readonly agentsNav = this.heal.locator(
  this.page.getByTestId('nav-agents'),
  { role: 'link', name: 'Agents', testId: 'nav-agents', description: 'agents nav entry' },
);
  • Read the heal report before you re-run anything. sdods heal report --last summarises the original selector, the strategy that won, the score and the suggested locator. Zero heals over ten attempts told the whole story in one command; --write-history persists heal-history.json so future runs bias toward strategies that have actually worked on this application.
  • Keep sdods.project.yaml in step. A module title: that no longer matches the product turns every report into a translation exercise.
  • Re-check the scenario's intent, not only its selector. An expandable section header is not a link, so the fix here was not a new name — it was a different interaction.
Before assuming a straight rename, check whether the old name survives behind a feature flag or on another plan tier. Renaming a locator back is a second outage.

analyze_locators over the MCP server, or the reviewer agent, will find the CSS-only and copy-bound locators in a project before the next rename does.

Scenario sketch

gherkin
@ui @smoke
Scenario: The agents section is reachable from the workspace shell
  Given I use a leased user with role "member"
  When I navigate to the "workspace" page
  And I click the element with test id "nav-agents"
  Then the page URL should contain "/agents"
  And the element with test id "fleet-list" should be visible
bash
sdods heal report --last

More on the scoring and the probe order in self-healing.

Other use cases