Skip to content

fix(webdriveragent): allow excluding customActions from the JSON page source - #114

Open
Sangkwun wants to merge 1 commit into
appium:mainfrom
Sangkwun:fix/json-source-custom-actions
Open

Sangkwun wants to merge 1 commit into
appium:mainfrom
Sangkwun:fix/json-source-custom-actions

Conversation

@Sangkwun

Copy link
Copy Markdown

Summary

excluded_attributes cannot drop customActions from the JSON page source (/source?format=json). dictionaryForElement: sets customActions next to name, value, label and rect, outside the attribute block map that the exclusion loop reads, so wdCustomActions is read for every element regardless of excluded_attributes.

This PR moves customActions into that block map as a non-prefixed key, like nativeFrame, minValue and maxValue. With excluded_attributes=customActions, wdCustomActions is not called and the key is absent. Requests that do not exclude it get the same output as before: every node has customActions, with null when the getter returns nil. The accessibility audit calls dictionaryForElement: with only visible and accessible excluded, so its elementAttributes still include customActions.

Why

  • For each element whose snapshot has no cached value, fb_customActions asks accessibility for XC_kAXXCAttributeCustomActions. For an element without custom actions it logs [FBCustomActions] Cannot determine string value for XC_kAXXCAttributeCustomActions: (null). A failed request logs the same line with the accessibility error (for example kAXErrorInvalidUIElement), and an array of actions logs one [FBCustomActions] Custom action title: … line per action. On our iPhone 15 runner (WDA 16.15.3, which has the same custom actions code as main, polled with /source?format=json), [FBCustomActions] lines were 1,116,971 of 1,403,311 log lines (80%) between Oct 18 and Oct 26.
  • JSON clients that do not need the attribute have no way to skip it today. Every attribute except type, rawIdentifier, name, value, label, rect and customActions can already be excluded (frame, nativeFrame, enabled, visible, accessible, nativeAccessibilityElement, focused, traits, placeholderValue, minValue, maxValue).
  • The xcuitest driver passes pageSourceExcludedAttributes as excluded_attributes with useJSONSource too (lib/commands/source.ts), so its users can set pageSourceExcludedAttributes=customActions after this change. With useJSONSource the driver's getTreeForXML keeps only type, enabled, visible, accessible, focused, rect, name, label and value, so today customActions is fetched for every node but never reaches the driver's XML.

I did not make the JSON tree follow includeCustomActionsInPageSource, which the XML source uses, because that would drop the key from the default JSON output. nativeFrame, nativeAccessibilityElement, minValue and maxValue already work this way: they are in the default JSON output and can be excluded there, while XML includes them only with includeNativeFrameInPageSource, includeNativeAccessibilityElementInPageSource and includeMinMaxValueInPageSource (for example nativeAccessibilityElement in appium/WebDriverAgent#1146). If you prefer to gate the JSON output with the setting instead, I can change the PR.

Tests

New integration test FBElementAttributeTests/testCustomActionsInJSONTree. In the default tree every node has a customActions key and the button has Custom Action 1,Custom Action 2. With customActions excluded, no node has the key. On main the last check fails: 41 nodes still have the key.

On an iPhone 17 simulator (iOS 27.0, Xcode 27.1):

  • UnitTests: 186 tests, 0 failures.
  • IntegrationTests_1/FBElementAttributeTests: 19 tests, 0 failures, 1 skipped. The skipped test is testIgnoredAccessibilityAttributes ("No image element available to test"), which does not read the JSON tree.
  • IntegrationTests_2/XCUIApplicationHelperTests testApplicationTree, testApplicationTreeAttributesFiltering and testAccessbilityAudit: 3 tests, 0 failures.

Timing

Settings app root screen (167 nodes) on the same simulator. With this PR, excluded_attributes=customActions cut the median request time from 1.338 s to 0.964 s in round 1 and from 1.150 s to 0.972 s in round 2, and the [FBCustomActions] lines per request from 167 to 0. On main the parameter has no effect: all 167 nodes keep the key and each request logs 167 lines.

Method and all numbers

Each build ran in one runner process: one warm-up request, then two rounds. Each round sent 20 plain GET /session/:id/source?format=json requests, then 20 with excluded_attributes=customActions.

build round plain: median (min–max) excluded: median (min–max) nodes with customActions (plain / excluded) [FBCustomActions] lines per request (plain / excluded)
main 1 1.070 s (1.036–1.274) 1.075 s (1.030–1.477) 167 / 167 167 / 167
main 2 1.199 s (1.053–1.957) 1.109 s (1.053–1.335) 167 / 167 167 / 167
this PR 1 1.338 s (1.188–1.501) 0.964 s (0.931–1.957) 167 / 0 167 / 0
this PR 2 1.150 s (1.079–1.631) 0.972 s (0.900–1.486) 167 / 0 167 / 0

The runs were noisy. Medians moved by up to 0.19 s between rounds of the same build and request, and the two builds ran at different times, so compare the two cells within a row rather than across builds. A plain request calls the same getters in both builds. The minimums show the same as the medians: 1.188 → 0.931 s and 1.079 → 0.900 s with this PR, 1.036 → 1.030 s and 1.053 → 1.053 s on main.

Docs

After this is merged I will open a PR in appium-xcuitest-driver to update the pageSourceExcludedAttributes docs. They say that with useJSONSource only frame, enabled, visible, accessible and focused are supported, so I will add customActions and the other attributes the JSON source can exclude.

🤖 Generated with Claude Code

… source

dictionaryForElement: set customActions outside the attribute block map, so
excluded_attributes could not drop it and wdCustomActions was read for every
element. Move it into the block map as a non-prefixed key, like nativeFrame
and minValue/maxValue. The default JSON output is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added bug Something isn't working package:webdriveragent labels Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working package:webdriveragent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant