mirror of https://github.com/garrytan/gstack.git
fix: keep nth indices stable across snapshot filters
This commit is contained in:
parent
5152aca65e
commit
24c3e20aa0
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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(`<!doctype html><body>
|
||||
<ul><li><button id="nested" onclick="window.clicked='nested'">Save</button></li></ul>
|
||||
<button id="outer" onclick="window.clicked='outer'">Save</button>
|
||||
</body>`);
|
||||
|
||||
const snap = await handleMetaCommand('snapshot', ['-i', '-d', '1'], bm, shutdown);
|
||||
const ref = extractRef(snap, (line) => line.includes('[button]') && line.includes('"Save"'));
|
||||
|
||||
await handleWriteCommand('click', [ref], bm);
|
||||
const clicked = await handleReadCommand('js', ['window.clicked'], bm);
|
||||
expect(clicked).toBe('outer');
|
||||
});
|
||||
|
||||
test('compact filter still freezes the correct nth unnamed element', async () => {
|
||||
const page = bm.getPage();
|
||||
await page.setContent(`<!doctype html><body>
|
||||
<p id="empty"></p>
|
||||
<p id="filled">Hello</p>
|
||||
</body>`);
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue