Fix iOS 26 UI test failures in Picker, DatePicker, and TimePicker tests - #36270
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36270Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36270" |
|
Hey there @@SubhikshaSf4851! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
|
/azp run maui-pr-uitests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run maui-pr-uitests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Updates MAUI Appium UI tests to handle iOS 26’s picker/action-button accessibility label change (from “Done” to “selected”), preventing iOS 26-specific UI test failures across Picker/DatePicker/TimePicker and some Editor keyboard-dismiss flows.
Changes:
- Adjusted
HelperExtensions.ClosePickerto tap"selected"on iOS 26+ instead of hard-coding"Done". - Updated multiple UI tests to resolve the correct iOS picker action button label dynamically via
HelperExtensions.IsIOS26OrHigher. - Updated Editor keyboard-dismiss helper (
KeyboardScrolling.CloseiOSEditorKeyboard) to use"selected"vs"Done"based on iOS version.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/TestUtils/src/UITest.Appium/HelperExtensions.cs | Updates shared picker-closing helper for iOS 26+ (“selected” vs “Done”). |
| src/Controls/tests/TestCases.Shared.Tests/Tests/KeyboardScrolling.cs | Updates Editor keyboard-dismiss logic to handle iOS 26+ button label. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/XFIssue/Issue5159.cs | Makes picker-dialog dismissal waits iOS-version-aware (“selected” vs “Done”). |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/XFIssue/Issue1614.cs | Makes Done/Cancel action identifier iOS-version-aware for the test flow. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34848.cs | Uses iOS-version-aware action button for closing DatePicker. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32984.cs | Uses iOS-version-aware action button for closing Picker. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31889.cs | Uses iOS-version-aware action button to dismiss iOS keyboard in theme-binding test. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31167.cs | Uses iOS-version-aware action button for repeated DatePicker open/close cycles. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Bugzilla/Bugzilla42074.cs | Uses iOS-version-aware action button for TimePicker cancel/unfocus flow. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Bugzilla/Bugzilla41424.cs | Uses iOS-version-aware action button for DatePicker cancel/unfocus flow. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/PickerFeatureTests.cs | Uses iOS-version-aware action button when closing the picker during screenshot test. |
|
/azp run maui-pr-uitests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
This comment has been minimized.
This comment has been minimized.
MauiBot
left a comment
There was a problem hiding this comment.
AI Review Summary
@SubhikshaSf4851 — new AI review results are available based on this last commit:
85f2588. To request a fresh review after new comments or commits, comment/review rerun.
🗂️ Review Sessions — click to expand
🚦 Gate — Test Before & After Fix
Gate Result: ⚠️ INCONCLUSIVE
Platform: ANDROID
⚠️ verify-tests-fail.ps1exited before writing a verification report. Diagnostics below.
Exit code: 3
Artifacts written before exit:
test-failure-Bugzilla41424.log(7.9 KB)test-failure-Bugzilla42074.log(7.9 KB)test-failure-Issue1614.log(7.7 KB)test-failure-Issue31167.log(7.7 KB)test-failure-Issue31889.log(8.3 KB)test-failure-Issue32984.log(7.9 KB)test-failure-Issue34848.log(7.9 KB)test-failure-Issue5159.log(7.7 KB)test-failure-KeyboardScrolling.log(7.8 KB)test-failure-PickerFeatureTests.log(177.5 KB)verification-log.txt(0.2 KB)
Gate output log (last 60 lines)
07-02 08:56:40.634 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/CultureEGButton'
07-02 08:56:41.157 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/TimeEntry'
07-02 08:56:41.259 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/TimeEntry'
07-02 08:56:41.712 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/TimeEntry'
07-02 08:56:42.370 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/SetTimeButton'
07-02 08:56:42.732 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/SetTimeButton'
07-02 08:56:42.811 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/Apply'
07-02 08:56:43.351 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/Apply'
07-02 08:56:44.358 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/TimePickerControl'
07-02 08:56:44.369 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/CultureFormatLabel'
07-02 08:56:47.637 31105 31136 I appium : AppiumResponse: {"sessionId":"9ad05d5f-0fce-455f-a112-264fb710fcc1","value":"<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>\r\n<hierarchy index=\"0\" class=\"hierarchy\" rotation=\"0\" width=\"1080\" height=\"1794\">\r\n <android.widget.FrameLayout index=\"0\" package=\"com.microsoft.maui.uitests\" class…
07-02 08:56:47.652 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/Options'
07-02 08:56:47.694 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/Options'
07-02 08:56:47.880 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/CultureJPButton'
07-02 08:56:48.746 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/CultureJPButton'
07-02 08:56:49.323 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/TimeEntry'
07-02 08:56:49.348 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/TimeEntry'
07-02 08:56:49.869 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/TimeEntry'
07-02 08:56:50.532 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/SetTimeButton'
07-02 08:56:50.886 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/SetTimeButton'
07-02 08:56:50.988 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/Apply'
07-02 08:56:51.526 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/Apply'
07-02 08:56:51.755 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/TimePickerControl'
07-02 08:56:52.729 31105 31136 I appium : method: 'id', selector: 'com.microsoft.maui.uitests:id/CultureFormatLabel'
07-02 08:56:56.098 31105 31136 I appium : AppiumResponse: {"sessionId":"9ad05d5f-0fce-455f-a112-264fb710fcc1","value":"<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>\r\n<hierarchy index=\"0\" class=\"hierarchy\" rotation=\"0\" width=\"1080\" height=\"1794\">\r\n <android.widget.FrameLayout index=\"0\" package=\"com.microsoft.maui.uitests\" class…
07-02 08:56:56.250 11067 11944 I ActivityManager: Force stopping com.microsoft.maui.uitests appid=10154 user=0: from pid 1162
07-02 08:56:56.251 11067 11944 I ActivityManager: Killing 32463:com.microsoft.maui.uitests/u0a154 (adj 0): stop com.microsoft.maui.uitests due to from pid 1162
07-02 08:56:56.258 11067 11944 W ActivityTaskManager: Force removing ActivityRecord{98aa11c u0 com.microsoft.maui.uitests/.MainActivity t147 f}}: app died, no saved state
07-02 08:56:57.195 11067 12161 D AutofillSession: handling death of Token{749ea8f ActivityRecord{98aa11c u0 com.microsoft.maui.uitests/.MainActivity t-1 f}}} when saving=false
07-02 08:56:57.308 11067 11227 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.microsoft.maui.uitests/.MainActivity} from uid 2000
07-02 08:56:57.576 11067 11096 I ActivityManager: Start proc 1188:com.microsoft.maui.uitests/u0a154 for pre-top-activity {com.microsoft.maui.uitests/com.microsoft.maui.uitests.MainActivity}
07-02 08:56:59.022 1188 1188 D DOTNET : AndroidCryptoNative_InitLibraryOnLoad: jint AndroidCryptoNative_InitLibraryOnLoad(JavaVM *, void *) in /__w/1/s/src/runtime/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c
07-02 08:56:58.900 1188 1188 W ft.maui.uitests: type=1400 audit(0.0:31064): avc: denied { read } for name="memory.use_hierarchy" dev="cgroup" ino=15 scontext=u:r:untrusted_app:s0:c154,c256,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=com.microsoft.maui.uitests
07-02 08:56:58.900 1188 1188 W ft.maui.uitests: type=1400 audit(0.0:31065): avc: denied { read } for name="memory.limit_in_bytes" dev="cgroup" ino=10 scontext=u:r:untrusted_app:s0:c154,c256,c512,c768 tcontext=u:object_r:cgroup:s0 tclass=file permissive=0 app=com.microsoft.maui.uitests
07-02 08:57:00.465 1188 1188 W ft.maui.uitest: ClassLoaderContext classpath size mismatch. expected=15, found=2 (DLC[];PCL[base.apk*1604962157:base.apk!classes2.dex*892330443:base.apk!classes3.dex*4132208247:base.apk!classes4.dex*1189418256:base.apk!classes5.dex*603145810:base.apk!classes6.dex*3249919879:base.apk!classes7.dex*4272712489:base.apk!classes8.dex*2286867051:base.apk!classes9.dex*1990284164:base.apk!classes10.dex*1304220855:base.apk!classes11.dex*2113592843:base.apk!classes12.dex*567841885:base.apk!classes13.dex*1284683107:base.apk!classes14.dex*287099224:base.apk!classes15.dex*3381648213]{PCL[/system/framework/org.apache.http.legacy.jar*1452144318]#PCL[/system/framework/com.android.location.provider.jar*4177849200]#PCL[/system/framework/com.android.media.remotedisplay.jar*1128910120]#PCL[/system_ext/framework/androidx.window.sidecar.jar*709954415]} | DLC[];PCL[/data/app/~~9PGTaOIFFg6qiK4xqD8Eyw==/com.microsoft.maui.uitests-BLCSrJBOi5trWnNZZiZORw==/base.apk*1230500770:/data/app/~~9PGTaOIFFg6qiK4xqD8Eyw==/com.microsoft.maui.uitests-BLCSrJBOi5trWnNZZiZORw==/base.apk!classes2.dex*2427112916]{PCL[/system/framework/org.apache.http.legacy.jar*1452144318]#PCL[/system_ext/framework/androidx.window.sidecar.jar*709954415]})
07-02 08:57:00.466 1188 1188 W ft.maui.uitest: Found duplicated class when checking oat files: 'Landroid/support/v4/graphics/drawable/IconCompatParcelizer;' in /data/app/~~rURNipLUuIJYzVWaZG090g==/com.google.android.gms-uKar-YQqfcjn4lnI9AmlAg==/split_MapsDynamite_installtime.apk!classes2.dex and /data/app/~~9PGTaOIFFg6qiK4xqD8Eyw==/com.microsoft.maui.uitests-BLCSrJBOi5trWnNZZiZORw==/base.apk
07-02 08:57:01.723 11694 16675 I PhenotypeResourceReader: unable to find any Phenotype resource metadata for com.microsoft.maui.uitests
07-02 08:57:03.175 11067 11094 D ArtManagerInternalImpl: /data/misc/iorapd/com.microsoft.maui.uitests/1/com.microsoft.maui.uitests.MainActivity/compiled_traces/compiled_trace.pb doesn't exist
07-02 08:57:03.222 1188 1269 W ft.maui.uitest: ClassLoaderContext classpath size mismatch. expected=15, found=2 (DLC[];PCL[base.apk*1604962157:base.apk!classes2.dex*892330443:base.apk!classes3.dex*4132208247:base.apk!classes4.dex*1189418256:base.apk!classes5.dex*603145810:base.apk!classes6.dex*3249919879:base.apk!classes7.dex*4272712489:base.apk!classes8.dex*2286867051:base.apk!classes9.dex*1990284164:base.apk!classes10.dex*1304220855:base.apk!classes11.dex*2113592843:base.apk!classes12.dex*567841885:base.apk!classes13.dex*1284683107:base.apk!classes14.dex*287099224:base.apk!classes15.dex*3381648213]{PCL[/system/framework/org.apache.http.legacy.jar*1452144318]#PCL[/system/framework/com.android.location.provider.jar*4177849200]#PCL[/system/framework/com.android.media.remotedisplay.jar*1128910120]#PCL[/system_ext/framework/androidx.window.sidecar.jar*709954415]} | DLC[];PCL[/data/app/~~9PGTaOIFFg6qiK4xqD8Eyw==/com.microsoft.maui.uitests-BLCSrJBOi5trWnNZZiZORw==/base.apk*1230500770:/data/app/~~9PGTaOIFFg6qiK4xqD8Eyw==/com.microsoft.maui.uitests-BLCSrJBOi5trWnNZZiZORw==/base.apk!classes2.dex*2427112916]{PCL[/system/framework/org.apache.http.legacy.jar*1452144318]#PCL[/system_ext/framework/androidx.window.sidecar.jar*709954415]})
07-02 08:57:03.222 1188 1269 W ft.maui.uitest: Found duplicated class when checking oat files: 'Landroid/support/v4/graphics/drawable/IconCompatParcelizer;' in /data/app/~~rURNipLUuIJYzVWaZG090g==/com.google.android.gms-uKar-YQqfcjn4lnI9AmlAg==/split_GoogleCertificates_installtime.apk!classes2.dex and /data/app/~~9PGTaOIFFg6qiK4xqD8Eyw==/com.microsoft.maui.uitests-BLCSrJBOi5trWnNZZiZORw==/base.apk
07-02 08:57:03.230 11067 11094 I ActivityTaskManager: Displayed com.microsoft.maui.uitests/.MainActivity: +5s317ms
07-02 08:57:03.299 1188 1260 I PhClient: Shared storage file not found for com.google.android.gms.clearcut_client#com.microsoft.maui.uitests
07-02 08:57:03.301 1188 1260 I PhClient: Unable to retrieve flag snapshot for com.google.android.gms.clearcut_client#com.microsoft.maui.uitests, using defaults.
07-02 08:57:03.367 1188 1260 I PhClient: Shared storage file not found for com.google.android.libraries.consentverifier#com.microsoft.maui.uitests
07-02 08:57:03.370 1188 1260 I PhClient: Unable to retrieve flag snapshot for com.google.android.libraries.consentverifier#com.microsoft.maui.uitests, using defaults.
ℹ️ Full device log: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests/android-device.log
═══════════════════════════════════════════════════════
❌ Tests failed with exit code 1
ℹ️ Review logs at: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests
📊 Parsed test results: Passed=79 Failed=43 Total=122 (from 1 result blocks)
==========================================
VERIFICATION RESULTS
==========================================
╔═══════════════════════════════════════════════════════════╗
║ ERROR PARSING TEST RESULTS ║
╚═══════════════════════════════════════════════════════════╝
[UITest] Issue1614: Test filter 'Issue1614' matched 0 tests
[UITest] Issue31167: Test filter 'Issue31167' matched 0 tests
[UITest] Issue5159: Test filter 'Issue5159' matched 0 tests
[UITest] KeyboardScrolling: Test filter 'KeyboardScrolling' matched 0 tests
📱 UI Tests — DatePicker,Editor,Entry,Picker,TimePicker
Detected UI test categories: DatePicker,Editor,Entry,Picker,TimePicker
drop-deep-uitests artifact before concluding.
🧪 UI Test Execution Results (deep, platform pool)
| Category | Tests | Snapshot diffs |
|---|---|---|
DatePicker |
44/44 ✓ | — |
Editor |
66/66 ✓ | — |
Entry |
0/113 (app crashed; 113 couldn't complete) | — |
Picker |
0/50 (setup failed; 50 marked failed) | — |
TimePicker |
0/32 (setup failed; 32 marked failed) | — |
⚠️ Entry — app crashed mid-run; 113 tests could not complete
The HostApp crashed during this category (a test failed in TearDown with investigate as possible crash); every following OneTimeSetUp then timed out waiting for the test gallery to reappear. This can be an emulator/infrastructure flake OR a regression introduced by this PR — review the screenshots and logcat in the ui-diagnostics folder of the artifact before concluding.
Multiple setup failure signatures were present; showing the first one. See the TRX artifact for all details.
The app was expected to be running still, investigate as possible crash
TearDown : The app was expected to be running still, investigate as possible crash
at UITest.Appium.NUnit.UITestBase.UITestBaseTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 159
at UITest.Appium.NUnit.UITestBase.TestTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 45
at InvokeStub_UITestBase.TestTearDown(Object, Object, IntPtr*)
--TearDown
at UITest.Appium.NUnit.UITestBase.UITestBaseTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 159
at UITest.Appium.NUnit.UITestBase.TestTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 45
at InvokeStub_UITestBase.TestTearDown(Object, Object, IntPtr*)
1) at UITest.Appium.NUnit.UITestBase.UITestBaseTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 159
at UITest.Appium.NUnit.UITestBase.TestTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 45
at InvokeStub_UITestBase.TestTearDown(Object, Object, IntPtr*)
⚠️ Picker — fixture setup failed for 50 tests
NUnit reported a OneTimeSetUp/fixture setup failure before test bodies ran; the TRX marked each affected test failed.
Multiple setup failure signatures were present; showing the first one. See the TRX artifact for all details.
OneTimeSetUp: System.TimeoutException : Timed out waiting for Go To Test button to appear
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
at Microsoft.Maui.TestCases.Tests.UtilExtensions.NavigateToGallery(IApp app, String page) in /_/src/Controls/tests/TestCases.Shared.Tests/UtilExtensions.cs:line 37
at Microsoft.Maui.TestCases.Tests._GalleryUITest.FixtureSetup() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/_GalleryUITest.cs:line 57
at UITest.Appium.NUnit.UITestBase.OneTimeSetup() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 221
at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStac
...
⚠️ TimePicker — fixture setup failed for 32 tests
NUnit reported a OneTimeSetUp/fixture setup failure before test bodies ran; the TRX marked each affected test failed.
Multiple setup failure signatures were present; showing the first one. See the TRX artifact for all details.
OneTimeSetUp: System.TimeoutException : Timed out waiting for Go To Test button to appear
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
at Microsoft.Maui.TestCases.Tests.UtilExtensions.NavigateToGallery(IApp app, String page) in /_/src/Controls/tests/TestCases.Shared.Tests/UtilExtensions.cs:line 37
at Microsoft.Maui.TestCases.Tests._GalleryUITest.FixtureSetup() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/_GalleryUITest.cs:line 57
at UITest.Appium.NUnit.UITestBase.OneTimeSetup() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 221
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
📎 Download drop-deep-uitests artifact (TRX + snapshot diffs)
📋 Pre-Flight — Context & Validation
Issue: N/A - No linked issue found in PR body
PR: #36270 - Fix iOS 26 UI test failures in Picker, DatePicker, and TimePicker tests
Platforms Affected: iOS UI tests (iOS 26+); Android requested for candidate testing but behavior is iOS-specific
Files Changed: 2 test infrastructure/helper, 9 UI test files
Key Findings
- PR #36270 updates UI-test code for iOS 26, where Appium exposes picker/editor dismissal as
"selected"instead of"Done". - The PR's current fix repeats
App is AppiumIOSApp iosApp && HelperExtensions.IsIOS26OrHigher(iosApp) ? "selected" : "Done"across multiple tests and updatesHelperExtensions.ClosePickerplusKeyboardScrolling.CloseiOSEditorKeyboard. - Public GitHub API access was available, but
ghCLI was unauthenticated. PR comments/reviews were fetched via public API; all prior Copilot inline comments were addressed by later commits. - Gate was provided as inconclusive by the caller and was not re-run.
Code Review Summary
Verdict: NEEDS_DISCUSSION
Confidence: low
Errors: 0 | Warnings: 2 | Suggestions: 1
Key code review findings:
- ⚠ Remaining hard-coded
"Done"locators exist in related UI tests such asDatePickerFeatureTests.cs,TimePickerFeatureTests.cs, andSafeArea_ContentPageFeatureTests.cs; some are under disabled/conditional test blocks, but they are the same failure mode if enabled in the iOS 26 lane. - ⚠
"selected"is a generic global locator and could match an unrelated selected element before the accessory dismiss button. - ℹ Repeating the iOS 26 ternary in many tests increases future drift; a centralized helper/fallback query would be easier to maintain.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #36270 | Per-test iOS 26 conditional locators plus helper updates for ClosePicker and editor keyboard dismissal |
HelperExtensions.cs, KeyboardScrolling.cs, 9 UI test files |
Original PR; plausible but duplicated and iOS-only |
🔬 Code Review — Deep Analysis
Code Review — PR #36270
Independent Assessment
What this changes: Test-only updates that switch iOS picker/editor keyboard dismissal from "Done" to "selected" on iOS 26+, using HelperExtensions.IsIOS26OrHigher(AppiumIOSApp). Android/Windows/MacCatalyst behavior is intended to remain unchanged.
Inferred motivation: WebDriver/Appium sees the iOS 26 picker/editor accessory dismiss control with accessibility name "selected" instead of "Done".
Reconciliation with PR Narrative
Author claims: The PR fixes iOS 26 UI test failures where Picker, DatePicker, TimePicker, and Editor keyboard dismiss flows hard-coded "Done" but the iOS 26 accessibility name is "selected".
Agreement/disagreement: The code matches the stated root cause and updates the listed failing tests. The main disagreement is maintainability/coverage: the PR fixes affected call sites directly rather than centralizing the behavior, and related hard-coded "Done" locators remain elsewhere under conditional test blocks.
Prior Review Reconciliation
| Prior ❌ Error Finding | Source | Status | Evidence |
|---|---|---|---|
| No prior ❌ Error findings found. | Public PR review/comment API | N/A | Prior Copilot comments were documentation/formatting/comment issues and were addressed in patch 3. |
Blast Radius Assessment
- Runs for all instances: No product runtime impact; UI test infrastructure/test code only.
- Startup impact: No.
- Static/shared state: No.
CI Status
- Required-check result: undetermined
- Classification: undetermined
- Action taken:
ghCLI was unavailable due missing auth; caller-provided gate result was inconclusive and was not re-run.
Findings
⚠️ Warning — likely incomplete replacement coverage
A repo scan still finds hard-coded iOS "Done" dismissal in related UI tests:
src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/DatePickerFeatureTests.cs:29,50,78src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/TimePickerFeatureTests.cs:30src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/SafeArea_ContentPageFeatureTests.cs:52
Some are inside disabled/conditional test regions, but if any run in the same net11/iOS 26 lane they can still fail with the same “Done not found” symptom.
⚠️ Warning — "selected" is a brittle global locator
The PR uses App.Tap("selected") / MobileBy.Name("selected") globally. "selected" is generic and could match another selected control/state if Appium exposes multiple elements with that name. A picker wheel item, page element, or accessibility state named "selected" could be returned before the accessory dismiss button.
💡 Suggestion — duplication increases drift
Several test files define local doneButton/DatePickerActionButton/TimePickerActionButton ternaries. That solves immediate failures but makes future iOS accessibility-name changes require another broad hunt. Prefer one helper/query abstraction for “dismiss iOS picker/editor accessory.”
Failure-Mode Probing
- iOS 25 or lower: should continue using
"Done". - iOS 26 editor keyboard: likely improved by
CloseiOSEditorKeyboard(IApp app, ...), but still brittle due global"selected"lookup. - MacCatalyst: should remain
"Done"becauseAppiumCatalystAppdoes not satisfyAppiumIOSApp. - Android-only validation: not meaningful for this fix beyond compile/no-op confidence.
- Remaining hard-coded
"Done"tests: potential continued net11/iOS 26 failures if those test blocks become active.
Verdict: NEEDS_DISCUSSION
Confidence: low
Summary: The PR is test-only and directionally correct, but the chosen approach duplicates iOS 26 locator logic and uses a generic global "selected" locator. With CI/gate inconclusive and iOS behavior not testable on the requested Android platform, this is best treated as a discussion/alternative-fix exploration rather than a verified LGTM.
🛠️ Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix | Centralize "Done" vs "selected" in UITest.Appium helper and use App.ClosePicker()/GetIOSDismissButtonName() from tests |
1 helper + affected UI tests | Better maintainability than PR, same label/version premise | |
| 2 | try-fix | Use structural iOS accessory-toolbar button lookup with bounded "Done"/"selected" fallback |
helper + affected UI tests | Avoids OS-version branching, but requires iOS XCUITest validation | |
| 3 | try-fix | Add iOS query alias so "Done" retries "selected" on miss |
iOS Appium query infrastructure | Lowest churn, broadest masking risk | |
| 4 | try-fix | Set stable AccessibilityIdentifier = "Done" on MAUI iOS accessory button |
iOS platform accessory view | Fixes source surface if MAUI owns the affected button and Appium honors identifier | |
| PR | PR #36270 | Per-test iOS 26 ternaries plus ClosePicker/editor keyboard helper updates |
11 files | Original PR; targeted and already merged, but duplicated locator logic |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 1 | Yes | Centralized helper/version-resolution approach |
| claude-opus-4.7 | 1 | Yes | Structural XCUITest accessory locator with label fallback |
| gpt-5.3-codex | 1 | Yes | iOS query-alias normalization |
| gpt-5.5 | 1 | Yes | Stable automation identifier on MauiDoneAccessoryView |
| gpt-5.5 | 2 | No | Remaining approaches reduce to the same four classes: per-call-site branching, centralized helper branching, structural/semantic locator, query aliasing, or source accessibility identifier |
Test/Validation Notes
- The caller supplied the gate as inconclusive and explicitly instructed not to re-run gate verification.
- The requested platform is Android, but PR #36270 and all meaningful candidates target iOS 26 Appium behavior. Android can only exercise unchanged Android picker dismissal behavior and cannot prove the
"Done"/"selected"issue. - The local worktree is dirty with unrelated CI-script changes and does not contain PR #36270’s public patch as the active local diff. To avoid corrupting unrelated work, candidates were generated as isolated proposed diffs in artifacts rather than applied to the worktree.
Exhausted: Yes
Selected Fix: None — no candidate passed tests. On code merits only, Candidate #1 is the safest improvement over the PR because it reduces duplication while preserving the PR’s narrow test-infrastructure scope. Candidate #2 is potentially more robust long-term but needs iOS 26 validation before it can be considered better. Candidate #4 is high leverage but too risky without confirming MAUI owns every affected accessory path.
🏁 Report — Final Recommendation
Comparative Fix Report — PR #36270
Candidate Ranking
| Rank | Candidate | Regression result | Assessment |
|---|---|---|---|
| 1 | pr |
Best available candidate. It is already implemented, localized to UI test/test-helper code, preserves non-iOS behavior, and directly addresses the reported iOS 26 "Done" -> "selected" Appium locator change. |
|
| 2 | pr-plus-reviewer |
Equivalent to pr; the expert reviewer found no actionable feedback to apply, so this candidate has no material improvement over the raw PR. |
|
| 3 | try-fix-1 |
Centralizing the dismiss label in a helper is more maintainable than per-test ternaries, but it remains unvalidated and depends on the same generic "selected" locator/version premise. Good future cleanup, not a safer winner now. |
|
| 4 | try-fix-2 |
Structurally locating the iOS accessory toolbar could be more robust long-term, but the proposed SingleOrDefault() approach is risky if multiple toolbar buttons exist and requires iOS XCUITest validation before replacing the PR. |
|
| 5 | try-fix-4 |
Setting a stable AccessibilityIdentifier on MauiDoneAccessoryView is high leverage if MAUI owns every affected button path, but it changes platform accessibility metadata and may not cover native picker accessory surfaces. |
|
| 6 | try-fix-3 |
A global iOS query alias for "Done" -> "selected" has the broadest blast radius and could silently bind unrelated lookups to unrelated selected elements. |
Comparative Analysis
No candidate has a passing regression result, and none is known to have failed regression tests. The caller-provided gate is inconclusive, so it is not treated as a failure for pr or pr-plus-reviewer. All try-fix-* candidates are blocked/unvalidated and therefore cannot outrank the already-implemented PR fix on evidence.
try-fix-1 is the strongest alternative on maintainability because it centralizes the locator decision in UITest.Appium, but it is still only a refactor of the PR's premise and adds no validation. try-fix-2 may eventually be more robust by avoiding OS-version branching, but it depends on unproven iOS hierarchy assumptions. try-fix-4 is attractive as a source-level automation-id fix, but its production platform-code blast radius is larger than this test-infrastructure PR. try-fix-3 is the least desirable because global query aliasing can mask unrelated automation failures.
Winner
Winner: pr
The raw PR fix wins because it is targeted, already present in the PR, matches the documented root cause, preserves existing platform behavior, and the expert reviewer found no actionable changes. pr-plus-reviewer is equivalent, so choosing pr avoids implying there is an additional patch to apply.
🧭 Next Steps — review latest findings
No alternative fix was selected for this run. Review the session findings and CI results before merging.
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment whether this change resolves your issue. Thank you!
Description of Change
On iOS 26, the picker dialog's action button label changed from "Done" to "selected", which broke several UI tests that hard-coded the
"Done"accessibility id when dismissingPicker,DatePicker, andTimePickerdialogs. This PR updates the affected tests to dynamically resolve the correct button label based on the iOS version under test, using the existingHelperExtensions.IsIOS26OrHigherhelper.Changes:
doneButton/DatePickerActionButton/TimePickerActionButtoncomputed property in each affected test class that returns"selected"on iOS 26+ and"Done"otherwise (viaApp is AppiumIOSApp iosApp && HelperExtensions.IsIOS26OrHigher(iosApp)).App.WaitForElement/App.Tapcalls to use this computed value instead of the hard-coded"Done"string.HelperExtensions.csto tap"selected"instead of"Done"when running on iOS 26+.KeyboardScrolling.CloseiOSEditorKeyboard(used byHideKeyboard) to accept theIAppinstance and resolve"selected"vs"Done"for the Editor's keyboard "Done" button on iOS 26+, instead of always searching for"Done".This resolves the CI failures in the following tests:
Picker_TapPicker_TakeScreenshotInvisiblePickerShowsDialogOnFocusInvisibleTimepickerShowsDialogOnFocusIssue1614TestIssue32984PickerShouldResizeInvisibleDatepickerShowsDialogOnFocusPickerCanBeOpenedProgrammaticallyDatePickerYearFormat_iOS_ConsistentAfterMultipleInteractionsDatePickerCancelShouldUnfocusDatePickerYearFormat_UserInteraction_MaintainsFourDigitYearDatePickerOpenedAndClosedEventsAreRaisedEntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnThemeChangeTimePickerCancelShouldUnfocusKeepEditorCursorAboveKeyboardInScrollViewKeepEditorCursorAboveKeyboardInGridEditorsScrollingPageTestEditorRuntimeTextAlignmentChanged