diff --git a/src/formatters/snapshotFormatter.ts b/src/formatters/snapshotFormatter.ts index 4b0365f5..68885edb 100644 --- a/src/formatters/snapshotFormatter.ts +++ b/src/formatters/snapshotFormatter.ts @@ -28,69 +28,32 @@ function getAttributes(serializedAXNodeRoot: TextSnapshotNode): string[] { `"${serializedAXNodeRoot.name || ''}"`, // Corrected: Added quotes around name ]; - // Value properties - const valueProperties = [ - 'value', - 'valuetext', - 'valuemin', - 'valuemax', - 'level', - 'autocomplete', - 'haspopup', - 'invalid', - 'orientation', - 'description', - 'keyshortcuts', - 'roledescription', - ] as const; - for (const property of valueProperties) { - if ( - property in serializedAXNodeRoot && - serializedAXNodeRoot[property] !== undefined - ) { - attributes.push(`${property}="${serializedAXNodeRoot[property]}"`); - } - } + const excluded = new Set(['id', 'role', 'name', 'elementHandle', 'children']); - // Boolean properties that also have an 'able' attribute - const booleanPropertyMap = { + const booleanPropertyMap: Record = { disabled: 'disableable', expanded: 'expandable', focused: 'focusable', selected: 'selectable', }; - for (const [property, ableAttribute] of Object.entries(booleanPropertyMap)) { - if (property in serializedAXNodeRoot) { - attributes.push(ableAttribute); - if (serializedAXNodeRoot[property as keyof typeof booleanPropertyMap]) { - attributes.push(property); - } - } - } - const booleanProperties = [ - 'modal', - 'multiline', - 'readonly', - 'required', - 'multiselectable', - ] as const; - - for (const property of booleanProperties) { - if (property in serializedAXNodeRoot && serializedAXNodeRoot[property]) { - attributes.push(property); + for (const attr of Object.keys(serializedAXNodeRoot).sort()) { + if (excluded.has(attr)) { + continue; } - } - - // Mixed boolean/string attributes - for (const property of ['pressed', 'checked'] as const) { - if (property in serializedAXNodeRoot) { - attributes.push(property); - if (serializedAXNodeRoot[property]) { - attributes.push(`${property}="${serializedAXNodeRoot[property]}"`); + const value = (serializedAXNodeRoot as unknown as Record)[ + attr + ]; + if (typeof value === 'boolean') { + if (booleanPropertyMap[attr]) { + attributes.push(booleanPropertyMap[attr]); } + if (value) { + attributes.push(attr); + } + } else if (typeof value === 'string' || typeof value === 'number') { + attributes.push(`${attr}="${value}"`); } } - return attributes; } diff --git a/tests/McpResponse.test.ts b/tests/McpResponse.test.ts index d34abe8c..11416447 100644 --- a/tests/McpResponse.test.ts +++ b/tests/McpResponse.test.ts @@ -89,7 +89,7 @@ uid=1_0 RootWebArea "" ## Page content uid=1_0 RootWebArea "My test page" uid=1_1 StaticText "username" - uid=1_2 textbox "username" value="mcp" focusable focused + uid=1_2 textbox "username" focusable focused value="mcp" `, ); }); diff --git a/tests/formatters/snapshotFormatter.test.ts b/tests/formatters/snapshotFormatter.test.ts index 0e17a512..47b7d288 100644 --- a/tests/formatters/snapshotFormatter.test.ts +++ b/tests/formatters/snapshotFormatter.test.ts @@ -100,7 +100,7 @@ describe('snapshotFormatter', () => { const formatted = formatA11ySnapshot(snapshot); assert.strictEqual( formatted, - `uid=1_1 checkbox "checkbox" checked checked="true" + `uid=1_1 checkbox "checkbox" checked uid=1_2 statictext "text" `, );