diff --git a/browse/src/snapshot.ts b/browse/src/snapshot.ts index 3ff2ab56e..73a9d2533 100644 --- a/browse/src/snapshot.ts +++ b/browse/src/snapshot.ts @@ -146,6 +146,11 @@ export async function handleSnapshot( roleNameCounts.set(key, (roleNameCounts.get(key) || 0) + 1); } + function markRoleNameSeen(node: ParsedNode) { + const key = `${node.role}:${node.name || ''}`; + roleNameSeen.set(key, (roleNameSeen.get(key) || 0) + 1); + } + // Second pass: assign refs and build locators for (const line of lines) { const node = parseLine(line); @@ -155,18 +160,24 @@ export async function handleSnapshot( const isInteractive = INTERACTIVE_ROLES.has(node.role); // Depth filter - if (opts.depth !== undefined && depth > opts.depth) continue; + if (opts.depth !== undefined && depth > opts.depth) { + // Skipped nodes still occupy nth() slots for later same-name matches. + markRoleNameSeen(node); + continue; + } // Interactive filter: skip non-interactive but still count for locator indices if (opts.interactive && !isInteractive) { // Still track for nth() counts - const key = `${node.role}:${node.name || ''}`; - roleNameSeen.set(key, (roleNameSeen.get(key) || 0) + 1); + markRoleNameSeen(node); continue; } // Compact filter: skip elements with no name and no inline content that aren't interactive - if (opts.compact && !isInteractive && !node.name && !node.children) continue; + if (opts.compact && !isInteractive && !node.name && !node.children) { + markRoleNameSeen(node); + continue; + } const indent = ' '.repeat(depth); diff --git a/browse/test/snapshot.test.ts b/browse/test/snapshot.test.ts index 72afe6564..c7b14c464 100644 --- a/browse/test/snapshot.test.ts +++ b/browse/test/snapshot.test.ts @@ -299,4 +299,33 @@ describe('Ref invalidation', () => { await handleWriteCommand('goto', [baseUrl + '/basic.html'], bm); expect(bm.getRefCount()).toBe(0); }); + + test('depth filter still freezes the correct nth same-name element', async () => { + const page = bm.getPage(); + await page.setContent(`
+Hello
+ `); + + const snap = await handleMetaCommand('snapshot', ['-c'], bm, shutdown); + const ref = extractRef(snap, (line) => line.includes('[paragraph]') && line.includes('Hello')); + + const html = await handleReadCommand('html', [ref], bm); + expect(html).toBe('Hello'); + }); });