fix: resolve unnamed element refs matching multiple elements (#573)

* fix: resolve unnamed element refs matching multiple elements (#500)

When a page has one unnamed button among several named buttons,
clicking its ref fails with "matched N elements" because the
locator `getByRole('button')` matches all buttons on the page.

Normalize unnamed interactive elements to `name: ""` so the
selector becomes `getByRole('button', { name: "", exact: true })`
which matches only buttons with empty accessible names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: remove dead code branch in buildSelector

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: make RefMap.name required string, remove dead code branches

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: hyunjinee <leehj0110@kakao.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jin.2
2026-03-01 09:42:05 -06:00
committed by GitHub
co-authored by Claude Opus 4.6 hyunjinee
parent 79d8dfe34c
commit 7238b7da4c
4 changed files with 45 additions and 23 deletions
+24
View File
@@ -154,6 +154,30 @@ describe('BrowserManager', () => {
});
});
describe('unnamed-button ref uniqueness', () => {
it('should click the correct unnamed button among named buttons', async () => {
const page = browser.getPage();
// 1 unnamed button among 2 named buttons
await page.setContent(`
<html><body>
<button>OK</button>
<button onclick="document.title='unnamed'"></button>
<button>Cancel</button>
</body></html>
`);
const snapshot = await browser.getSnapshot();
const refs = snapshot.refs;
const unnamedRefs = Object.entries(refs).filter(([, v]) => v.role === 'button' && !v.name);
expect(unnamedRefs.length).toBe(1);
const [refId] = unnamedRefs[0];
await executeCommand({ id: 'test', action: 'click', selector: `@${refId}` }, browser);
const title = await page.title();
expect(title).toBe('unnamed');
});
});
describe('cursor-ref selector uniqueness', () => {
it('should produce unique selectors for repeated DOM structures', async () => {
const page = browser.getPage();