Fix intermediate pages not receiving query parameters in multi-page Shell navigation#35432
Conversation
…hell navigation When Shell.GoToAsync pushes multiple pages (e.g. 'product/review'), only the last page received query parameters. Intermediate pages silently got nothing because their Parent is null (not yet in visual tree), causing baseShellItem to be null. Neither the ShellContent branch nor the isLastItem branch would run, so parameters were silently dropped. Added a third branch in ApplyQueryAttributes for the case where the element is a Page but baseShellItem is null. It sets the QueryAttributesProperty with prefix-filtered parameters, which triggers the existing property-changed handler to apply IQueryAttributable, BindingContext propagation, and QueryProperty attributes. Fixes #35107 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35432Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35432" |
Add UI tests (Order 148-149) in ShellNavigationFeatureTests to verify multi-page GoToAsync delivers prefixed params to intermediate pages and unprefixed params to the last page, including overlapping param name scoping. Enhance QueryIntermediatePage to implement IQueryAttributable and display received params. Add multi-page prefixed navigation button to QuerySenderPage. Add unit tests for overlapping param names and verifying intermediate pages do not receive unprefixed params meant for the last page. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes Shell multi-page navigation so intermediate pages can receive route-prefixed query parameters when GoToAsync pushes multiple pages in one call.
Changes:
- Applies query attributes directly to intermediate
Pageinstances that are not yet parented in the Shell visual tree. - Adds unit coverage for prefixed intermediate parameters, overlapping keys, and last-page parameter behavior.
- Adds HostApp/UI test support for multi-page prefixed query navigation scenarios.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/Controls/src/Core/Shell/ShellNavigationManager.cs |
Adds direct query application for intermediate pages and minor cleanup. |
src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs |
Adds Shell parameter passing regression tests for intermediate pages. |
src/Controls/tests/TestCases.HostApp/FeatureMatrix/Shell/ShellNavigation/ShellNavigationControlPage.xaml.cs |
Extends the Shell navigation feature page with a multi-page prefixed query test flow. |
src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/ShellNavigationFeatureTests.cs |
Adds Appium feature tests for intermediate/last-page scoped query parameters. |
| // which triggers OnQueryAttributesPropertyChanged to handle IQueryAttributable, | ||
| // BindingContext propagation, and [QueryProperty] attributes. | ||
| var mergedData = MergeData(element, filteredQuery, isPopping); | ||
| if (mergedData.Count > 0 || !isPopping) |
There was a problem hiding this comment.
Fixed in 95e0ab7. Added the ShellContent-style guard:
if (filteredQuery.Count == 0 && !element.IsSet(ShellContent.QueryAttributesProperty))
return;This skips empty queries on fresh intermediate pages. For pages that previously had params set (re-navigation), an empty query still propagates to allow clearing.
Added test IntermediatePageWithNoPrefixedParamsDoesNotReceiveEmptyQuery to verify.
| var mergedData = MergeData(element, filteredQuery, isPopping); | ||
| if (mergedData.Count > 0 || !isPopping) | ||
| { | ||
| element.SetValue(ShellContent.QueryAttributesProperty, mergedData); |
There was a problem hiding this comment.
Good catch — but this is a pre-existing issue in the ShellRouteParameters(query, prefix) constructor (line 55-56 of ShellRouteParameters.cs). It copies _shellNavigationQueryParameters verbatim for ALL prefix-filtered queries, including those used in the ShellContent branch at line 311. The intermediate page branch inherits the same behavior.
Fixing this would require changing the shared constructor, which would also affect the ShellContent path. I think that warrants a separate issue/PR rather than mixing it into this bug fix.
|
/review |
|
/review -b feature/regression-check |
PureWeen
left a comment
There was a problem hiding this comment.
Multi-Model Adversarial Code Review + MAUI Expert Review
Methodology: 3 independent reviewers (different models) with adversarial consensus, plus MAUI-specific expert dimension review. Disputed findings went through a follow-up round where the other reviewers weighed in.
✅ Verdict: LGTM (high confidence)
The fix is correct, minimal, and well-tested. The else if (element is Page) branch correctly delivers prefix-filtered query params to intermediate pages by reusing existing QueryAttributesProperty infrastructure. No correctness, security, or regression concerns survived cross-validation.
Confirmed safe:
- No double-application risk (branch ordering prevents it)
SetValueis safe before page joins visual tree- Correctly uses
filteredQuery(not fullquery) for intermediate pages - All shared code — no platform-specific concerns
- No security, threading, or resource leak issues
Additional observations (not inline)
💡 Last page receives ALL params including prefixed keys for other pages — This is pre-existing behavior in Branch 2 (isLastItem uses full query, not filteredQuery). None of the new tests document this asymmetry. Consider adding an explicit assertion if this is intentional contract. (2/3 reviewers)
💡 ShellNavigationQueryParameters bypasses prefix filtering — The prefix constructor in ShellRouteParameters.cs (line 55-56) correctly filters string keys by prefix but copies _shellNavigationQueryParameters wholesale. Pre-existing issue from PR #15585, not introduced here. Worth tracking as a separate issue. (3/3 reviewers, all confirmed pre-existing)
💡 Whitespace reformatting mixed with functional changes in ShellNavigationFeatureTests.cs — space-to-tab fixes on existing code mixed with new test additions. Harmless but adds diff noise.
- Add ShellContent-style guard: skip empty filteredQuery on intermediate pages if QueryAttributesProperty was never previously set. Prevents spurious empty ApplyQueryAttributes calls during multi-page navigation when no prefixed params target the intermediate page. - Fix misleading comment: remove 'Parent is null' claim since the branch also fires for in-stack pages from PrepareCurrentStackForBeingReplaced. - Add test: IntermediatePageWithNoPrefixedParamsDoesNotReceiveEmptyQuery verifies the empty-query guard works correctly. - Add test: IntermediatePageReceivesParamsOnReNavigation verifies params are delivered on subsequent navigations to the same route. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/review -b feature/regression-check |
|
/azp-run maui-pr-devicetests |
|
/review -b feature/regression-check |
|
/review -b feature/regression-check -p android |
2 similar comments
|
/review -b feature/regression-check -p android |
|
/review -b feature/regression-check -p android |
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Problem The `/review` slash command in `.github/workflows/review-trigger.yml` is silently skipped when the comment body has any **leading whitespace** before `/review`. Concrete example: - Comment posted on #35432: #35432 (comment) - Body (raw bytes): `' /review -b feature/regression-check'` — note the leading space (`0x20`). - Result: workflow run https://github.com/dotnet/maui/actions/runs/25824871590 → **skipped**. ### Root cause The job-level guard was: ```yaml if: >- github.event_name == 'workflow_dispatch' || (github.event.issue.pull_request && (github.event.comment.body == '/review' || startsWith(github.event.comment.body, '/review '))) ``` `startsWith(' /review ...', '/review ')` returns `false`, so the job is skipped. GitHub expression syntax has no `trim` or regex, so we can't fix this purely at the expression level. The `Parse parameters` step had the same blind spot — `sed -n 's|^/review[[:space:]]*||p'` produces empty `ARGS` if the body doesn't start with `/review`. ### Fix 1. **New tiny `match` pre-filter job** that uses a bash regex (`^[[:space:]]*/review([[:space:]]|$)`) to decide whether the comment is a `/review` command. It allows arbitrary leading whitespace (spaces, tabs, newlines) but still requires `/review` to be a standalone token (won't match `/reviewfoo` or comments that merely mention `/review` mid-sentence). 2. **`trigger-review` now `needs: match`** and gates on its output, keeping the rest of the job structure intact. 3. **Trim leading whitespace before `sed`** in `Parse parameters`, so flag/positional parsing works on prefixed comments like ` /review -b feature/foo`. ### Verification Local check of the regex against representative inputs: | Body | Should match | Matches | |-------------------------------------|--------------|---------| | `/review` | yes | yes | | `/review android` | yes | yes | | ` /review -b feature/regression-check` (the failing case) | yes | yes | | `\t/review` | yes | yes | | ` /review -p ios` | yes | yes | | `/reviewfoo` | no | no | | `please /review this` | no | no | | `not a command` | no | no | The full end-to-end behavior will be exercised by the next `/review` invocation on a PR that targets this branch.
|
/review -b feature/regression-check -p ios |
🤖 AI Summary
📊 Review Session —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ ShellNavigationFeatureTests ShellNavigationFeatureTests |
✅ FAIL — 579s | ❌ FAIL — 367s |
🧪 ShellParameterPassingTests ShellParameterPassingTests |
✅ FAIL — 12s | ✅ PASS — 9s |
🔴 Without fix — 🖥️ ShellNavigationFeatureTests: FAIL ✅ · 579s
(truncated to last 15,000 chars)
igationSucceeds Start
Passed RouteRegistration_UnregisterRoute_NavigationFails [1 s]
>>>>> 5/21/2026 4:35:11 AM RouteRegistration_ReRegisterRoute_NavigationSucceeds Stop
Passed RouteRegistration_ReRegisterRoute_NavigationSucceeds [4 s]
>>>>> 5/21/2026 4:35:11 AM CancelNavigation_NavigationIsBlocked_StaysOnMain Start
>>>>> 5/21/2026 4:35:18 AM CancelNavigation_NavigationIsBlocked_StaysOnMain Stop
Passed CancelNavigation_NavigationIsBlocked_StaysOnMain [7 s]
>>>>> 5/21/2026 4:35:18 AM DeferralNavigation_NavigationCompletes_AfterDelay Start
>>>>> 5/21/2026 4:35:28 AM DeferralNavigation_NavigationCompletes_AfterDelay Stop
Passed DeferralNavigation_NavigationCompletes_AfterDelay [10 s]
>>>>> 5/21/2026 4:35:28 AM TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo Start
>>>>> 5/21/2026 4:35:31 AM TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo Stop
Passed TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo [2 s]
>>>>> 5/21/2026 4:35:31 AM TabStack_OnPushAsync_SubPage1_TabStackCountIsThree Start
>>>>> 5/21/2026 4:35:33 AM TabStack_OnPushAsync_SubPage1_TabStackCountIsThree Stop
Passed TabStack_OnPushAsync_SubPage1_TabStackCountIsThree [1 s]
>>>>> 5/21/2026 4:35:33 AM TabStack_OnPushAsync_SubPage2_TabStackCountIsFour Start
>>>>> 5/21/2026 4:35:34 AM TabStack_OnPushAsync_SubPage2_TabStackCountIsFour Stop
Passed TabStack_OnPushAsync_SubPage2_TabStackCountIsFour [1 s]
>>>>> 5/21/2026 4:35:34 AM TabStack_OnPopAsync_SubPage2_TabStackCountIsThree Start
>>>>> 5/21/2026 4:35:36 AM TabStack_OnPopAsync_SubPage2_TabStackCountIsThree Stop
Passed TabStack_OnPopAsync_SubPage2_TabStackCountIsThree [1 s]
>>>>> 5/21/2026 4:35:36 AM TabStack_OnPopToRootAsync_ReturnsToMainPage Start
>>>>> 5/21/2026 4:35:38 AM TabStack_OnPopToRootAsync_ReturnsToMainPage Stop
Passed TabStack_OnPopToRootAsync_ReturnsToMainPage [1 s]
>>>>> 5/21/2026 4:35:38 AM TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage Start
>>>>> 5/21/2026 4:35:41 AM TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage Stop
Passed TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage [3 s]
>>>>> 5/21/2026 4:35:41 AM TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo Start
>>>>> 5/21/2026 4:35:42 AM TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo Stop
>>>>> 5/21/2026 4:35:42 AM TabStack_OnRemovePage_NoOp_WhenNothingToRemove Start
Passed TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo [1 s]
>>>>> 5/21/2026 4:35:43 AM TabStack_OnRemovePage_NoOp_WhenNothingToRemove Stop
>>>>> 5/21/2026 4:35:43 AM TabStack_GetNavigationStack_TabStackMatchesNavigationStack Start
Passed TabStack_OnRemovePage_NoOp_WhenNothingToRemove [1 s]
>>>>> 5/21/2026 4:35:49 AM TabStack_GetNavigationStack_TabStackMatchesNavigationStack Stop
Passed TabStack_GetNavigationStack_TabStackMatchesNavigationStack [6 s]
>>>>> 5/21/2026 4:35:49 AM NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage Start
>>>>> 5/21/2026 4:35:55 AM NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage Stop
Passed NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage [5 s]
>>>>> 5/21/2026 4:35:55 AM NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped Start
>>>>> 5/21/2026 4:35:55 AM NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped Stop
>>>>> 5/21/2026 4:35:55 AM NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage Start
Passed NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped [789 ms]
>>>>> 5/21/2026 4:35:57 AM NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage Stop
>>>>> 5/21/2026 4:35:57 AM NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage Start
Passed NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage [2 s]
>>>>> 5/21/2026 4:35:58 AM NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage Stop
>>>>> 5/21/2026 4:35:58 AM NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged Start
Passed NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage [717 ms]
>>>>> 5/21/2026 4:36:04 AM NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged Stop
Passed NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged [5 s]
>>>>> 5/21/2026 4:36:04 AM NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain Start
>>>>> 5/21/2026 4:36:05 AM NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain Stop
>>>>> 5/21/2026 4:36:05 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged Start
Passed NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain [715 ms]
>>>>> 5/21/2026 4:36:06 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged Stop
>>>>> 5/21/2026 4:36:06 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged Start
>>>>> 5/21/2026 4:36:06 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged Stop
>>>>> 5/21/2026 4:36:06 AM NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged Start
Passed NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged [1 s]
Passed NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged [444 ms]
>>>>> 5/21/2026 4:36:11 AM NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged Stop
Passed NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged [4 s]
>>>>> 5/21/2026 4:36:11 AM NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 Start
>>>>> 5/21/2026 4:36:12 AM NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 Stop
Passed NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 [1 s]
>>>>> 5/21/2026 4:36:12 AM NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged Start
>>>>> 5/21/2026 4:36:18 AM NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged Stop
Passed NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged [5 s]
>>>>> 5/21/2026 4:36:18 AM NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA Start
>>>>> 5/21/2026 4:36:19 AM NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA Stop
Passed NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA [1 s]
>>>>> 5/21/2026 4:36:19 AM NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot Start
>>>>> 5/21/2026 4:36:24 AM NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot Stop
Passed NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot [5 s]
>>>>> 5/21/2026 4:36:24 AM NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot Start
>>>>> 5/21/2026 4:36:25 AM NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot Stop
>>>>> 5/21/2026 4:36:25 AM PassData_StringQueryParam_ReceivedByIQueryAttributable Start
Passed NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot [464 ms]
>>>>> 5/21/2026 4:36:33 AM PassData_StringQueryParam_ReceivedByIQueryAttributable Stop
Passed PassData_StringQueryParam_ReceivedByIQueryAttributable [7 s]
>>>>> 5/21/2026 4:36:33 AM PassData_DictionaryParam_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:36:38 AM PassData_DictionaryParam_ReceivedByIQueryAttributable Stop
Passed PassData_DictionaryParam_ReceivedByIQueryAttributable [5 s]
>>>>> 5/21/2026 4:36:38 AM PassData_SingleUseParams_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:36:43 AM PassData_SingleUseParams_ReceivedByIQueryAttributable Stop
Passed PassData_SingleUseParams_ReceivedByIQueryAttributable [5 s]
>>>>> 5/21/2026 4:36:43 AM PassData_StringQueryParam_BothLabelsReceiveSameValue Start
>>>>> 5/21/2026 4:36:49 AM PassData_StringQueryParam_BothLabelsReceiveSameValue Stop
Passed PassData_StringQueryParam_BothLabelsReceiveSameValue [5 s]
>>>>> 5/21/2026 4:36:49 AM PassData_BackwardsNavigation_PassesDataToPreviousPage Start
>>>>> 5/21/2026 4:36:52 AM PassData_BackwardsNavigation_PassesDataToPreviousPage Stop
Passed PassData_BackwardsNavigation_PassesDataToPreviousPage [2 s]
>>>>> 5/21/2026 4:36:52 AM PassData_MultipleStringParams_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:37:01 AM PassData_MultipleStringParams_ReceivedByIQueryAttributable Stop
Passed PassData_MultipleStringParams_ReceivedByIQueryAttributable [9 s]
>>>>> 5/21/2026 4:37:01 AM PassData_IQueryAttributable_ReceivesDecodedValues Start
>>>>> 5/21/2026 4:37:07 AM PassData_IQueryAttributable_ReceivesDecodedValues Stop
Passed PassData_IQueryAttributable_ReceivesDecodedValues [5 s]
>>>>> 5/21/2026 4:37:07 AM PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack Start
>>>>> 5/21/2026 4:37:17 AM PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack Stop
Passed PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack [10 s]
>>>>> 5/21/2026 4:37:17 AM BackButtonBehavior_TextOverride_CustomTextShownOnBackButton Start
>>>>> 5/21/2026 4:37:26 AM BackButtonBehavior_TextOverride_CustomTextShownOnBackButton Stop
Passed BackButtonBehavior_TextOverride_CustomTextShownOnBackButton [8 s]
>>>>> 5/21/2026 4:37:26 AM BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter Start
>>>>> 5/21/2026 4:37:35 AM BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter Stop
Passed BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter [9 s]
>>>>> 5/21/2026 4:37:35 AM BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate Start
>>>>> 5/21/2026 4:37:35 AM BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate Stop
BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate: Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
>>>>> 5/21/2026 4:37:35 AM BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks Start
>>>>> 5/21/2026 4:37:35 AM BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks Stop
BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks: Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
>>>>> 5/21/2026 4:37:36 AM BackButtonBehavior_IconOverride_CustomIconShownOnBackButton Start
Skipped BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate [50 ms]
Error Message:
Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
Standard Output Messages:
Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
Skipped BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks [36 ms]
Error Message:
Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
Standard Output Messages:
Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
>>>>> 5/21/2026 4:37:45 AM BackButtonBehavior_IconOverride_CustomIconShownOnBackButton Stop
Passed BackButtonBehavior_IconOverride_CustomIconShownOnBackButton [9 s]
>>>>> 5/21/2026 4:37:45 AM PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams Start
>>>>> 5/21/2026 4:38:00 AM PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams Stop
>>>>> 5/21/2026 4:38:00 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
Failed PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams [18 s]
Error Message:
System.TimeoutException : Timed out waiting for element...
Stack Trace:
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 2757
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 2784
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 793
at Microsoft.Maui.TestCases.Tests.ShellNavigationFeatureTests.PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/ShellNavigationFeatureTests.cs:line 855
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, ObjectHandleOnStack result)
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
>>>>> 5/21/2026 4:38:03 AM PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly Start
>>>>> 5/21/2026 4:38:18 AM PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly Stop
>>>>> 5/21/2026 4:38:18 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
Failed PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly [18 s]
Error Message:
System.TimeoutException : Timed out waiting for element...
Stack Trace:
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 2757
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 2784
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 793
at Microsoft.Maui.TestCases.Tests.ShellNavigationFeatureTests.PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/ShellNavigationFeatureTests.cs:line 894
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, ObjectHandleOnStack result)
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Failed.
Total tests: 54
Passed: 50
Failed: 2
Skipped: 2
Total time: 5.6584 Minutes
🟢 With fix — 🖥️ ShellNavigationFeatureTests: FAIL ❌ · 367s
(truncated to last 15,000 chars)
igationSucceeds Start
Passed RouteRegistration_UnregisterRoute_NavigationFails [1 s]
>>>>> 5/21/2026 4:41:29 AM RouteRegistration_ReRegisterRoute_NavigationSucceeds Stop
Passed RouteRegistration_ReRegisterRoute_NavigationSucceeds [4 s]
>>>>> 5/21/2026 4:41:29 AM CancelNavigation_NavigationIsBlocked_StaysOnMain Start
>>>>> 5/21/2026 4:41:37 AM CancelNavigation_NavigationIsBlocked_StaysOnMain Stop
Passed CancelNavigation_NavigationIsBlocked_StaysOnMain [7 s]
>>>>> 5/21/2026 4:41:37 AM DeferralNavigation_NavigationCompletes_AfterDelay Start
>>>>> 5/21/2026 4:41:47 AM DeferralNavigation_NavigationCompletes_AfterDelay Stop
Passed DeferralNavigation_NavigationCompletes_AfterDelay [10 s]
>>>>> 5/21/2026 4:41:47 AM TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo Start
>>>>> 5/21/2026 4:41:49 AM TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo Stop
Passed TabStack_OnPushAsync_EnterOptionsPage_TabStackCountIsTwo [2 s]
>>>>> 5/21/2026 4:41:49 AM TabStack_OnPushAsync_SubPage1_TabStackCountIsThree Start
>>>>> 5/21/2026 4:41:51 AM TabStack_OnPushAsync_SubPage1_TabStackCountIsThree Stop
Passed TabStack_OnPushAsync_SubPage1_TabStackCountIsThree [1 s]
>>>>> 5/21/2026 4:41:51 AM TabStack_OnPushAsync_SubPage2_TabStackCountIsFour Start
>>>>> 5/21/2026 4:41:53 AM TabStack_OnPushAsync_SubPage2_TabStackCountIsFour Stop
Passed TabStack_OnPushAsync_SubPage2_TabStackCountIsFour [1 s]
>>>>> 5/21/2026 4:41:53 AM TabStack_OnPopAsync_SubPage2_TabStackCountIsThree Start
>>>>> 5/21/2026 4:41:54 AM TabStack_OnPopAsync_SubPage2_TabStackCountIsThree Stop
Passed TabStack_OnPopAsync_SubPage2_TabStackCountIsThree [1 s]
>>>>> 5/21/2026 4:41:54 AM TabStack_OnPopToRootAsync_ReturnsToMainPage Start
>>>>> 5/21/2026 4:41:56 AM TabStack_OnPopToRootAsync_ReturnsToMainPage Stop
Passed TabStack_OnPopToRootAsync_ReturnsToMainPage [1 s]
>>>>> 5/21/2026 4:41:56 AM TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage Start
>>>>> 5/21/2026 4:41:59 AM TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage Stop
Passed TabStack_OnInsertPageBefore_InsertsPageBelowCurrentPage [3 s]
>>>>> 5/21/2026 4:41:59 AM TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo Start
>>>>> 5/21/2026 4:42:01 AM TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo Stop
>>>>> 5/21/2026 4:42:01 AM TabStack_OnRemovePage_NoOp_WhenNothingToRemove Start
Passed TabStack_OnRemovePage_RemovesInsertedPage_CountBackToTwo [1 s]
>>>>> 5/21/2026 4:42:02 AM TabStack_OnRemovePage_NoOp_WhenNothingToRemove Stop
>>>>> 5/21/2026 4:42:02 AM TabStack_GetNavigationStack_TabStackMatchesNavigationStack Start
Passed TabStack_OnRemovePage_NoOp_WhenNothingToRemove [1 s]
>>>>> 5/21/2026 4:42:08 AM TabStack_GetNavigationStack_TabStackMatchesNavigationStack Stop
Passed TabStack_GetNavigationStack_TabStackMatchesNavigationStack [6 s]
>>>>> 5/21/2026 4:42:08 AM NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage Start
>>>>> 5/21/2026 4:42:13 AM NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage Stop
Passed NavEvents_Pop_NavigatingEvent_SourceIsPopAndCurrentIsPreviousPage [5 s]
>>>>> 5/21/2026 4:42:13 AM NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped Start
>>>>> 5/21/2026 4:42:14 AM NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped Stop
>>>>> 5/21/2026 4:42:14 AM NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage Start
Passed NavEvents_Pop_NavigatedEvent_CurrentIsLandedPagePreviousIsPopped [807 ms]
>>>>> 5/21/2026 4:42:16 AM NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage Stop
>>>>> 5/21/2026 4:42:16 AM NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage Start
Passed NavEvents_Push_NavigatingEvent_SourceIsPushAndCurrentIsPushedFromPage [2 s]
>>>>> 5/21/2026 4:42:17 AM NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage Stop
>>>>> 5/21/2026 4:42:17 AM NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged Start
Passed NavEvents_Push_NavigatedEvent_CurrentIsNewPagePreviousIsSourcePage [740 ms]
>>>>> 5/21/2026 4:42:23 AM NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged Stop
Passed NavEvents_ShellItemChanged_NavigatingEvent_SourceIsShellItemChanged [5 s]
>>>>> 5/21/2026 4:42:23 AM NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain Start
>>>>> 5/21/2026 4:42:23 AM NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain Stop
>>>>> 5/21/2026 4:42:23 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged Start
Passed NavEvents_ShellItemChanged_NavigatedEvent_CurrentIsPage2PreviousIsMain [735 ms]
>>>>> 5/21/2026 4:42:24 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged Stop
>>>>> 5/21/2026 4:42:24 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged Start
>>>>> 5/21/2026 4:42:25 AM NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged Stop
>>>>> 5/21/2026 4:42:25 AM NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged Start
Passed NavEvents_GoToAsyncAbsoluteRoute_NavigatingEvent_SourceIsShellItemChanged [1 s]
Passed NavEvents_GoToAsyncAbsoluteRoute_NavigatedEvent_SourceIsShellItemChanged [456 ms]
>>>>> 5/21/2026 4:42:30 AM NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged Stop
Passed NavEvents_ShellContentChanged_NavigatingEvent_SourceIsShellContentChanged [4 s]
>>>>> 5/21/2026 4:42:30 AM NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 Start
>>>>> 5/21/2026 4:42:31 AM NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 Stop
Passed NavEvents_ShellContentChanged_NavigatedEvent_CurrentIsContent2PreviousIsContent1 [1 s]
>>>>> 5/21/2026 4:42:31 AM NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged Start
>>>>> 5/21/2026 4:42:37 AM NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged Stop
Passed NavEvents_ShellSectionChanged_NavigatingEvent_SourceIsShellSectionChanged [5 s]
>>>>> 5/21/2026 4:42:37 AM NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA Start
>>>>> 5/21/2026 4:42:38 AM NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA Stop
Passed NavEvents_ShellSectionChanged_NavigatedEvent_CurrentIsTabBPreviousIsTabA [1 s]
>>>>> 5/21/2026 4:42:38 AM NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot Start
>>>>> 5/21/2026 4:42:43 AM NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot Stop
Passed NavEvents_PopToRoot_NavigatingEvent_SourceIsPopToRoot [5 s]
>>>>> 5/21/2026 4:42:43 AM NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot Start
>>>>> 5/21/2026 4:42:44 AM NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot Stop
>>>>> 5/21/2026 4:42:44 AM PassData_StringQueryParam_ReceivedByIQueryAttributable Start
Passed NavEvents_PopToRoot_NavigatedEvent_CurrentIsMainSourceIsPopToRoot [476 ms]
>>>>> 5/21/2026 4:42:52 AM PassData_StringQueryParam_ReceivedByIQueryAttributable Stop
Passed PassData_StringQueryParam_ReceivedByIQueryAttributable [7 s]
>>>>> 5/21/2026 4:42:52 AM PassData_DictionaryParam_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:42:57 AM PassData_DictionaryParam_ReceivedByIQueryAttributable Stop
Passed PassData_DictionaryParam_ReceivedByIQueryAttributable [5 s]
>>>>> 5/21/2026 4:42:57 AM PassData_SingleUseParams_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:43:03 AM PassData_SingleUseParams_ReceivedByIQueryAttributable Stop
Passed PassData_SingleUseParams_ReceivedByIQueryAttributable [5 s]
>>>>> 5/21/2026 4:43:03 AM PassData_StringQueryParam_BothLabelsReceiveSameValue Start
>>>>> 5/21/2026 4:43:08 AM PassData_StringQueryParam_BothLabelsReceiveSameValue Stop
Passed PassData_StringQueryParam_BothLabelsReceiveSameValue [5 s]
>>>>> 5/21/2026 4:43:08 AM PassData_BackwardsNavigation_PassesDataToPreviousPage Start
>>>>> 5/21/2026 4:43:11 AM PassData_BackwardsNavigation_PassesDataToPreviousPage Stop
Passed PassData_BackwardsNavigation_PassesDataToPreviousPage [2 s]
>>>>> 5/21/2026 4:43:11 AM PassData_MultipleStringParams_ReceivedByIQueryAttributable Start
>>>>> 5/21/2026 4:43:21 AM PassData_MultipleStringParams_ReceivedByIQueryAttributable Stop
Passed PassData_MultipleStringParams_ReceivedByIQueryAttributable [9 s]
>>>>> 5/21/2026 4:43:21 AM PassData_IQueryAttributable_ReceivesDecodedValues Start
>>>>> 5/21/2026 4:43:27 AM PassData_IQueryAttributable_ReceivesDecodedValues Stop
Passed PassData_IQueryAttributable_ReceivesDecodedValues [5 s]
>>>>> 5/21/2026 4:43:27 AM PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack Start
>>>>> 5/21/2026 4:43:37 AM PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack Stop
Passed PassData_Dictionary_PersistsWhenNavigatingToIntermediatePageAndBack [10 s]
>>>>> 5/21/2026 4:43:37 AM BackButtonBehavior_TextOverride_CustomTextShownOnBackButton Start
>>>>> 5/21/2026 4:43:46 AM BackButtonBehavior_TextOverride_CustomTextShownOnBackButton Stop
Passed BackButtonBehavior_TextOverride_CustomTextShownOnBackButton [9 s]
>>>>> 5/21/2026 4:43:46 AM BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter Start
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter Stop
Passed BackButtonBehavior_CommandParameter_CommandFiresWithCorrectParameter [9 s]
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate Start
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate Stop
BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate: Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks Start
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks Stop
BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks: Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
>>>>> 5/21/2026 4:43:56 AM BackButtonBehavior_IconOverride_CustomIconShownOnBackButton Start
Skipped BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate [45 ms]
Error Message:
Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
Standard Output Messages:
Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
Skipped BackButtonBehavior_IsVisible_False_ProgrammaticNavStillWorks [36 ms]
Error Message:
Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
Standard Output Messages:
Fails on iOS 26 due to bug issue: https://github.com/dotnet/maui/issues/34771
>>>>> 5/21/2026 4:44:04 AM BackButtonBehavior_IconOverride_CustomIconShownOnBackButton Stop
Passed BackButtonBehavior_IconOverride_CustomIconShownOnBackButton [8 s]
>>>>> 5/21/2026 4:44:04 AM PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams Start
>>>>> 5/21/2026 4:44:20 AM PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams Stop
>>>>> 5/21/2026 4:44:20 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
Failed PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams [18 s]
Error Message:
System.TimeoutException : Timed out waiting for element...
Stack Trace:
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 2757
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 2784
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 793
at Microsoft.Maui.TestCases.Tests.ShellNavigationFeatureTests.PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/ShellNavigationFeatureTests.cs:line 855
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, ObjectHandleOnStack result)
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
>>>>> 5/21/2026 4:44:23 AM PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly Start
>>>>> 5/21/2026 4:44:38 AM PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly Stop
>>>>> 5/21/2026 4:44:38 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
Failed PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly [18 s]
Error Message:
System.TimeoutException : Timed out waiting for element...
Stack Trace:
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 2757
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 2784
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 793
at Microsoft.Maui.TestCases.Tests.ShellNavigationFeatureTests.PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/ShellNavigationFeatureTests.cs:line 894
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, ObjectHandleOnStack result)
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Failed.
Total tests: 54
Passed: 50
Failed: 2
Skipped: 2
Total time: 4.4491 Minutes
🔴 Without fix — 🧪 ShellParameterPassingTests: FAIL ✅ · 12s
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/TestUtils/TestUtils.csproj (in 526 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 527 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 578 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 602 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj (in 1.3 sec).
5 of 10 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0/Microsoft.Maui.Maps.dll
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0/Microsoft.Maui.Controls.Maps.dll
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0/Microsoft.Maui.Controls.Xaml.dll
TestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/TestUtils/Debug/netstandard2.0/Microsoft.Maui.TestUtils.dll
Controls.Core.UnitTests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.14] Discovering: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.80] Discovered: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.80] Starting: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.92] MultipleIntermediatePagesEachReceiveOwnPrefixedParams [FAIL]
[xUnit.net 00:00:00.92] Assert.Single() Failure: The collection was empty
[xUnit.net 00:00:00.92] Stack Trace:
[xUnit.net 00:00:00.92] /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(861,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.MultipleIntermediatePagesEachReceiveOwnPrefixedParams()
[xUnit.net 00:00:00.92] --- End of stack trace from previous location ---
Passed UrlParameter [51 ms]
Passed InitialNavigationDoesntSetQueryAttributesProperty [23 ms]
Passed ReNavigatingToCurrentLocationPassesParameters(useDataTemplates: True) [3 ms]
Passed ReNavigatingToCurrentLocationPassesParameters(useDataTemplates: False) [< 1 ms]
Passed NavigationWithQueryStringThenWithoutQueryString [2 ms]
Passed NavigatingBackToShellContentRetainsQueryParameter [3 ms]
Failed MultipleIntermediatePagesEachReceiveOwnPrefixedParams [3 ms]
Error Message:
Assert.Single() Failure: The collection was empty
Stack Trace:
at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.MultipleIntermediatePagesEachReceiveOwnPrefixedParams() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 861
--- End of stack trace from previous location ---
Passed BasicShellParameterTest [4 ms]
Passed PopNavigationTriggersApplyQueryAttributes [2 ms]
[xUnit.net 00:00:00.94] Assert.Equal() Failure: Strings differ
[xUnit.net 00:00:00.94] Expected: "hello"
[xUnit.net 00:00:00.94] Actual: null
[xUnit.net 00:00:00.94] Stack Trace:
[xUnit.net 00:00:00.94] /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(822,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesQueryPropertyAttributes()
[xUnit.net 00:00:00.94] --- End of stack trace from previous location ---
Passed ExtraParametersArentReAppliedWhenNavigatingBackToShellContent [2 ms]
Passed DotDotNavigationPassesShellParameters [1 ms]
Passed ExtraParametersDontGetRetained [3 ms]
[xUnit.net 00:00:00.94] IntermediatePageReceivesQueryPropertyAttributes [FAIL]
Passed DotDotNavigationPassesParameters [< 1 ms]
Passed PassesUrlInShellParameter [< 1 ms]
Passed ShellNavigationQueryParametersPassedInAsReadOnly [< 1 ms]
Failed IntermediatePageReceivesQueryPropertyAttributes [1 ms]
Error Message:
Assert.Equal() Failure: Strings differ
Expected: "hello"
Actual: null
Stack Trace:
at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesQueryPropertyAttributes() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 822
--- End of stack trace from previous location ---
[xUnit.net 00:00:00.95] IntermediatePageDoesNotReceiveUnprefixedParams [FAIL]
Passed NavigatingBackToTabSetsQueryAttributesProperty [1 ms]
Passed UriEncodedStringDecodesCorrectly [< 1 ms]
[xUnit.net 00:00:00.95] Assert.Single() Failure: The collection was empty
[xUnit.net 00:00:00.95] Stack Trace:
[xUnit.net 00:00:00.95] /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(920,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageDoesNotReceiveUnprefixedParams()
[xUnit.net 00:00:00.95] --- End of stack trace from previous location ---
[xUnit.net 00:00:00.95] Assert.Single() Failure: The collection was empty
[xUnit.net 00:00:00.95] IntermediatePageReceivesPrefixedQueryParamsViaIQueryAttributable [FAIL]
[xUnit.net 00:00:00.95] Stack Trace:
[xUnit.net 00:00:00.95] /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(796,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesPrefixedQueryParamsViaIQueryAttributable()
[xUnit.net 00:00:00.95] --- End of stack trace from previous location ---
Passed BasicQueryStringTest [< 1 ms]
Passed FlyoutItemNavigationSetsQueryAttributesProperty [< 1 ms]
Passed NavigationBetweenShellContentsPassesQueryString [< 1 ms]
Passed NavigationBetweenFlyoutItemWithPushedPageRetainsQueryString [< 1 ms]
Failed IntermediatePageDoesNotReceiveUnprefixedParams [< 1 ms]
Error Message:
Assert.Single() Failure: The collection was empty
Stack Trace:
at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageDoesNotReceiveUnprefixedParams() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 920
--- End of stack trace from previous location ---
Passed NavigationWithQueryStringAndNoDataTemplate [< 1 ms]
Passed SingleUseQueryParametersReplaceQueryStringParams [< 1 ms]
Failed IntermediatePageReceivesPrefixedQueryParamsViaIQueryAttributable [< 1 ms]
Error Message:
Assert.Single() Failure: The collection was empty
Stack Trace:
at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesPrefixedQueryParamsViaIQueryAttributable() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 796
--- End of stack trace from previous location ---
Passed UriDecodesQueryString [< 1 ms]
[xUnit.net 00:00:00.96] OverlappingParamNamesDeliverCorrectValueToEachPage [FAIL]
[xUnit.net 00:00:00.96] Assert.Single() Failure: The collection was empty
[xUnit.net 00:00:00.96] Stack Trace:
[xUnit.net 00:00:00.96] /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(892,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.OverlappingParamNamesDeliverCorrectValueToEachPage()
[xUnit.net 00:00:00.96] --- End of stack trace from previous location ---
[xUnit.net 00:00:00.96] IntermediatePageReceivesParamsOnReNavigation [FAIL]
[xUnit.net 00:00:00.96] Assert.Single() Failure: The collection was empty
[xUnit.net 00:00:00.96] Stack Trace:
[xUnit.net 00:00:00.96] /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs(972,0): at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesParamsOnReNavigation()
[xUnit.net 00:00:00.96] --- End of stack trace from previous location ---
Passed ShellSectionChangedSetsQueryAttributesProperty [< 1 ms]
Passed LastPageStillReceivesUnprefixedParamsWithIntermediatePages [< 1 ms]
Passed NavigationWithQueryStringWhenPageMatchesBindingContext [< 1 ms]
Passed SetParameterOfTypeThatsNotAString [4 ms]
Failed OverlappingParamNamesDeliverCorrectValueToEachPage [< 1 ms]
Error Message:
Assert.Single() Failure: The collection was empty
Stack Trace:
at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.OverlappingParamNamesDeliverCorrectValueToEachPage() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 892
--- End of stack trace from previous location ---
Failed IntermediatePageReceivesParamsOnReNavigation [< 1 ms]
Error Message:
Assert.Single() Failure: The collection was empty
Stack Trace:
at Microsoft.Maui.Controls.Core.UnitTests.ShellParameterPassingTests.IntermediatePageReceivesParamsOnReNavigation() in /_/src/Controls/tests/Core.UnitTests/ShellParameterPassingTests.cs:line 972
--- End of stack trace from previous location ---
Passed TabBarNavigationSetsQueryAttributesProperty [1 ms]
Passed NavigatingBackDoesntClearParametersFromPreviousPage [5 ms]
Passed NavigatingBackAbsolutelyClearsParametersFromPreviousPage [< 1 ms]
[xUnit.net 00:00:00.98] Finished: Microsoft.Maui.Controls.Core.UnitTests
Passed NavigationBetweenFlyoutItemsRetainsQueryString [1 ms]
Passed ValidateReadOnlyDictionary [1 ms]
Passed NavigatingBackToShellContentAbsolutelyClearsQueryParameter [< 1 ms]
Passed IntermediatePageWithNoPrefixedParamsDoesNotReceiveEmptyQuery [1 ms]
Passed TabBarNavigationWithGoToAsyncSetsQueryAttributesProperty [< 1 ms]
Test Run Failed.
Total tests: 41
Passed: 35
Failed: 6
Total time: 1.3326 Seconds
🟢 With fix — 🧪 ShellParameterPassingTests: PASS ✅ · 9s
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 476 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 477 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 485 ms).
7 of 10 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158784
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0/Microsoft.Maui.Controls.Xaml.dll
Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0/Microsoft.Maui.Controls.Maps.dll
TestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/TestUtils/Debug/netstandard2.0/Microsoft.Maui.TestUtils.dll
Controls.Core.UnitTests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.11] Discovering: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.74] Discovered: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.75] Starting: Microsoft.Maui.Controls.Core.UnitTests
Passed UrlParameter [51 ms]
Passed InitialNavigationDoesntSetQueryAttributesProperty [19 ms]
Passed ReNavigatingToCurrentLocationPassesParameters(useDataTemplates: True) [3 ms]
Passed ReNavigatingToCurrentLocationPassesParameters(useDataTemplates: False) [< 1 ms]
Passed NavigationWithQueryStringThenWithoutQueryString [2 ms]
Passed NavigatingBackToShellContentRetainsQueryParameter [3 ms]
Passed MultipleIntermediatePagesEachReceiveOwnPrefixedParams [3 ms]
Passed BasicShellParameterTest [2 ms]
Passed PopNavigationTriggersApplyQueryAttributes [2 ms]
Passed ExtraParametersArentReAppliedWhenNavigatingBackToShellContent [2 ms]
Passed DotDotNavigationPassesShellParameters [1 ms]
Passed ExtraParametersDontGetRetained [3 ms]
Passed DotDotNavigationPassesParameters [< 1 ms]
Passed PassesUrlInShellParameter [< 1 ms]
Passed ShellNavigationQueryParametersPassedInAsReadOnly [< 1 ms]
Passed IntermediatePageReceivesQueryPropertyAttributes [< 1 ms]
Passed NavigatingBackToTabSetsQueryAttributesProperty [1 ms]
Passed UriEncodedStringDecodesCorrectly [< 1 ms]
Passed BasicQueryStringTest [< 1 ms]
Passed FlyoutItemNavigationSetsQueryAttributesProperty [1 ms]
Passed NavigationBetweenShellContentsPassesQueryString [1 ms]
Passed NavigationBetweenFlyoutItemWithPushedPageRetainsQueryString [1 ms]
Passed IntermediatePageDoesNotReceiveUnprefixedParams [< 1 ms]
Passed NavigationWithQueryStringAndNoDataTemplate [< 1 ms]
Passed SingleUseQueryParametersReplaceQueryStringParams [< 1 ms]
Passed IntermediatePageReceivesPrefixedQueryParamsViaIQueryAttributable [1 ms]
Passed UriDecodesQueryString [< 1 ms]
Passed ShellSectionChangedSetsQueryAttributesProperty [1 ms]
Passed LastPageStillReceivesUnprefixedParamsWithIntermediatePages [< 1 ms]
Passed NavigationWithQueryStringWhenPageMatchesBindingContext [< 1 ms]
Passed SetParameterOfTypeThatsNotAString [3 ms]
Passed OverlappingParamNamesDeliverCorrectValueToEachPage [< 1 ms]
Passed IntermediatePageReceivesParamsOnReNavigation [1 ms]
Passed TabBarNavigationSetsQueryAttributesProperty [< 1 ms]
Passed NavigatingBackDoesntClearParametersFromPreviousPage [1 ms]
Passed NavigatingBackAbsolutelyClearsParametersFromPreviousPage [< 1 ms]
[xUnit.net 00:00:00.91] Finished: Microsoft.Maui.Controls.Core.UnitTests
Passed NavigationBetweenFlyoutItemsRetainsQueryString [6 ms]
Passed ValidateReadOnlyDictionary [1 ms]
Passed NavigatingBackToShellContentAbsolutelyClearsQueryParameter [< 1 ms]
Passed IntermediatePageWithNoPrefixedParamsDoesNotReceiveEmptyQuery [< 1 ms]
Passed TabBarNavigationWithGoToAsyncSetsQueryAttributesProperty [< 1 ms]
Test Run Successful.
Total tests: 41
Passed: 41
Total time: 1.2384 Seconds
⚠️ Failure Details
- ❌ ShellNavigationFeatureTests FAILED with fix (should pass)
Device tests: 2 of 52 failed
📁 Fix files reverted (1 files)
src/Controls/src/Core/Shell/ShellNavigationManager.cs
🧪 UI Tests — Shell
Detected UI test categories: Shell
🧪 UI Test Execution Results
⏭️ SKIPPED — 0 passed, 0 failed, 1 skipped (platform: ios)
| Category | Result | Tests | Duration | Notes |
|---|---|---|---|---|
Shell |
⏭️ SKIPPED | — | 0s | Runner threw an exception |
Failures here are informational only — they do not block the gate or affect try-fix candidate scoring.
🔍 Pre-Flight — Context & Validation
Pre-Flight Summary — PR #35432
Issue (#35107)
Shell.GoToAsync with multi-segment routes (e.g. "product/review?product.sku=X&stars=5") silently drops query parameters intended for intermediate pages. Only the last page receives params. Existing prefix-based scoping (product.sku → sku for the product page) is in place in ShellRouteParameters but never reaches the page.
PR Fix (Author: mattleibow)
File: src/Controls/src/Core/Shell/ShellNavigationManager.cs
Approach: In ApplyQueryAttributes, after the existing baseShellItem is ShellContent and isLastItem branches, add a third branch:
else if (element is Page)
{
if (filteredQuery.Count == 0 && !element.IsSet(ShellContent.QueryAttributesProperty))
return;
var mergedData = MergeData(element, filteredQuery, isPopping);
if (mergedData.Count > 0 || !isPopping)
element.SetValue(ShellContent.QueryAttributesProperty, mergedData);
}Root cause cited: intermediate Page objects are freshly created by ShellSection.GetOrCreateFromRoute and have Parent == null at the time ApplyQueryAttributes runs, so neither the baseShellItem is ShellContent nor isLastItem branch fires; the parameters are silently dropped. The fix piggybacks on the already-existing ShellContent.QueryAttributesProperty propertyChanged handler (OnQueryAttributesPropertyChanged) which already dispatches to IQueryAttributable, propagates BindingContext, and reflects [QueryProperty] attributes.
Tests added by PR
- Unit tests (
ShellParameterPassingTests.cs, +202 lines, 8 new tests): intermediate page viaIQueryAttributable, via[QueryProperty], multi-intermediate, overlapping names, no-leak of unprefixed params, no-empty-apply, re-navigation. - UI tests (
ShellNavigationFeatureTests.cs, 2 tests, order 148/149):PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams,PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly. - HostApp rewrite of
ShellNavigationControlPage.xaml.cs(large reformat, +856/-799).
Gate Result (already run, do not re-run)
| Test | Without Fix | With Fix |
|---|---|---|
| ShellNavigationFeatureTests (UI) | FAIL (expected) | FAIL ❌ — TimeoutException waiting for elements; output also references unrelated iOS 26 bug #34771 |
| ShellParameterPassingTests (Unit) | FAIL (expected) | PASS ✅ |
Interpretation: The unit tests prove the fix is logically correct. The UI tests fail in both states with the same error signature (Appium TimeoutException + iOS 26 issue #34771 — known pre-existing). The gate flags this as "regression in another test" but the UI failures are likely environment/iOS-26-related, NOT caused by the fix.
Call sites of ApplyQueryAttributes(navPage, …)
ShellSection.cs:418— iteratesnavStack, calls per page, withisLast = i == globalRoutes.Count - 1. This is where intermediate pages get the call withisLast=false.ShellSection.cs:517— different path, with the actual ShellContent.
Key infrastructure used by the fix
ShellContent.cs:376 OnQueryAttributesPropertyChanged → ApplyQueryAttributes(content, query, oldQuery):
- Dispatches to
IQueryAttributable.ApplyQueryAttributes - Walks
BindingContextif it differs from the page - Reflects
[QueryProperty]attributes (gated byRuntimeFeature.IsQueryPropertyAttributeSupported)
Areas where an alternative fix could differ
- Fix at call site (
ShellSection.cs:418/375) — apply attributes when the page is created, before insertion, so the call path doesn't depend on whether the page is wrapped. - Reuse
BaseShellItem.ApplyQueryAttributes-style dispatch — extract theShellContent.ApplyQueryAttributes(content, query, oldQuery)static into a reusable helper and call it directly on the page rather than routing through the attached property's propertyChanged handler. - Move the page-handling into the existing
baseShellItem is ShellContentbranch by liftingbaseShellItemdiscovery — detect the page case earlier and merge into one path. - Set
Parent(or attach to ShellContent) beforeApplyQueryAttributes— fix the underlying ordering issue rather than adding a side-channel.
🔧 Fix — Analysis & Comparison
Try-Fix Aggregate Summary — PR #35432
Context
- Issue: Shell GoToAsync: no way to pass query parameters to intermediate pages in multi-segment navigation #35107 —
Shell.GoToAsync("product/review?product.sku=X&stars=5")silently drops thesku=Xparameter intended for the intermediateproductpage. Only the last page receives query parameters. - PR's fix: add an
else if (element is Page)branch toShellNavigationManager.ApplyQueryAttributesthat setsShellContent.QueryAttributesProperty(attached) directly on intermediate pages, leveraging the existingOnQueryAttributesPropertyChangeddispatch. - Gate result (already run, did not re-execute): unit tests pass with the fix; UI tests fail both with and without the fix due to unrelated iOS 26 issues (Appium TimeoutException + reference to [iOS 26] BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate test fails with TimeoutException #34771). The unit-test result confirms the fix is logically correct.
- Validation method: for each candidate, I built
Controls.Core.UnitTestsand ran every test matchingFullyQualifiedName~Shell(309 tests, including the PR's 8 new ones).
Candidates
| # | Approach | Build | Shell tests (309) | Verdict |
|---|---|---|---|---|
| 1 | Fix at the call site (ShellSection.GetOrCreateFromRoute) instead of inside ApplyQueryAttributes. Leaves the shared dispatch method untouched. |
✅ | ✅ 309/309 | Works. Smaller blast radius; PR's centralized approach probably more maintainable. |
| 2 | Collapse isLastItem + is Page branches into one unified element is Page branch. Pure refactor of PR's fix. |
✅ | ✅ 309/309 | Works. Stylistic improvement only; matter of taste. |
| 3a | Expose ShellContent.ApplyQueryAttributesInternal and call it directly + still SetValue on attached property. |
✅ | ❌ 5 failures (double-dispatch — Assert.Single() Failure: collection contained 2 items) |
Found a foot-gun. |
| 3b | Same as 3a but only call the internal dispatcher (no SetValue). | ✅ | ✅ 309/309 | Works. More invasive (ShellContent.cs API expanded); subtle semantic loss (attached property no longer holds the value after dispatch). |
Comparison vs PR's fix
All three working candidates (1, 2, 3b) deliver identical behavior on all 309 unit tests, including the 8 new ones the PR introduced (Intermediate*, OverlappingParamNames*, LastPageStillReceivesUnprefixedParams*, MultipleIntermediatePagesEachReceiveOwnPrefixedParams, IntermediatePageReceivesParamsOnReNavigation, IntermediatePageWithNoPrefixedParamsDoesNotReceiveEmptyQuery).
None of the candidates is demonstrably better than the PR's fix. Findings:
- PR's design is the most conservative, smallest, and least-error-prone choice. It piggybacks on existing machinery (the
QueryAttributesPropertypropertyChanged handler) and keeps API surface unchanged. - Candidate 1 is a viable alternative if a reviewer specifically wants
ApplyQueryAttributesuntouched. It's not better, just differently scoped. - Candidate 2 is a clean-up; might be applied on top of the PR's fix as a follow-up refactor. Not blocking.
- Candidate 3 revealed a real risk: calling both the SetValue and the direct dispatcher causes double-fire of
IQueryAttributable.ApplyQueryAttributes. This is a useful safety lesson but the candidate itself is less attractive than the PR.
UI Test Failures (separate from fix correctness)
The gate reported PassData_MultiPageNavigation_IntermediateAndLastPageReceiveCorrectParams and PassData_MultiPageNavigation_OverlappingParamNamesAreScopedCorrectly failing on iOS in both the fix-applied and fix-reverted runs, with the same Appium System.TimeoutException signature plus references to unrelated iOS 26 bug #34771. This points to environment/UI-test-infrastructure issues, not a regression caused by the fix. Unit-test coverage validates the underlying logic.
Recommendation
Keep the PR's fix as-is. The exploration confirms:
- The bug analysis is correct.
- The chosen fix location (
ApplyQueryAttributesthird branch) is reasonable and unifies handling for the only call sites that produce orphanPageinstances. - No alternative dramatically simplifies or improves the fix.
- UI test failures appear unrelated and should be investigated separately (iOS 26 environment, not Shell logic).
Optional follow-up: candidate 2 (collapsing the isLastItem/is Page branches) is a small readability improvement worth considering as a separate housekeeping PR.
Detailed candidate write-ups
try-fix-1/content.md— call-site fix inShellSection.GetOrCreateFromRoutetry-fix-2/content.md— branch-collapse refactortry-fix-3/content.md— direct dispatcher invocation (including the double-dispatch bug discovered)
📋 Report — Final Recommendation
PR #35432 — Comparative Report
Issue
#35107 — Shell.GoToAsync with multi-segment routes (e.g., "product/review?product.sku=X&stars=5") silently drops query parameters intended for intermediate pages. Only the last page receives params. Prefix-based scoping already exists in ShellRouteParameters but never reaches intermediate pages whose Parent is null when ApplyQueryAttributes runs.
Candidates Evaluated
| # | Candidate | Approach | Build | Shell unit tests (309) | UI tests (iOS) | Notes |
|---|---|---|---|---|---|---|
| 1 | pr | Add else if (element is Page) branch in ShellNavigationManager.ApplyQueryAttributes that sets ShellContent.QueryAttributesProperty attached property, leveraging existing OnQueryAttributesPropertyChanged dispatch. |
✅ | ✅ 309/309 (incl. 8 new tests) | ❌ env-only (iOS-26 #34771, fails identically without fix) | The submitted PR fix. |
| 2 | pr-plus-reviewer | Identical to pr — expert review found no actionable findings above info severity. |
✅ | ✅ 309/309 | ❌ env-only | No sandbox patch applied; inline-findings.json is empty. |
| 3 | try-fix-1 | Fix at the page-creation call site (ShellSection.GetOrCreateFromRoute) instead of inside ApplyQueryAttributes. |
✅ | ✅ 309/309 | not re-run (env-only) | Smaller blast radius but needs duplication if a second call site ever creates orphan pages. |
| 4 | try-fix-2 | Pure refactor: collapse the existing isLastItem branch and the new is Page branch into a single unified branch that selects query vs filteredQuery based on isLastItem. |
✅ | ✅ 309/309 | not re-run (env-only) | Stylistic improvement only; matter of taste. Tightens an asymmetric early-exit guard. |
| 5 | try-fix-3 | Expose ShellContent.ApplyQueryAttributesInternal and call it directly from ShellNavigationManager, bypassing the attached-property roundtrip. |
✅ | ✅ 309/309 (after fix to attempt 1) | not re-run (env-only) | Initial attempt caused double-dispatch (IQueryAttributable.ApplyQueryAttributes fired twice) — fixed by removing the SetValue. Expands API surface and loses the persisted attached-property state. Uncovered a real foot-gun that the PR's design inherently avoids. |
Gate Result Reminder
| Test type | Without fix | With fix |
|---|---|---|
| ShellParameterPassingTests (unit) | FAIL (expected) | PASS ✅ |
| ShellNavigationFeatureTests (UI, iOS) | FAIL | FAIL (identical Appium TimeoutException + iOS-26 #34771 reference) |
The UI test failures reproduce both with and without the PR fix and match a known unrelated iOS 26 Appium issue. Unit tests are the authoritative correctness signal. No candidate failed regression tests — all candidates that produced a working build passed 309/309 Shell unit tests.
Per-dimension Highlights from Expert Review (pr)
- Handler/Navigation lifecycle: The new branch correctly routes through
ShellContent.OnQueryAttributesPropertyChanged, which already handlesIQueryAttributable,BindingContextpropagation, and[QueryProperty]reflection. No duplication, no new dispatch path. - Edge-case asymmetry (
isLastItemhas no early-exit guard; the newPagebranch does): Intentional.isLastItemuses unfilteredquery(typically non-empty); the newPagebranch uses prefix-filteredfilteredQuery(typically empty for most intermediates on most navigations). The guard prevents spuriousSetValue(empty)on every intermediate. The!IsSet(...)half preserves clear-on-re-nav semantics. - Silent fallthrough (
ShellSection/ShellItemthat isn't aPagestill skipped): Pre-existing behavior. No regression introduced. - Style scope creep (
shellContent?.ChildAdded +=): Unrelated to the bug fix but consistent with the symmetric-=form used in the disposable. Acceptable. - Threading / performance / public API / accessibility: No concerns.
- Test coverage: 8 new unit tests cover all canonical scenarios (IQueryAttributable, [QueryProperty], multi-intermediate, prefix overlap, no-unprefixed-leak, no-empty-application, re-navigation).
Comparative Reasoning
All five candidates are functionally equivalent on every unit test. The differentiators are non-functional:
- try-fix-1 moves the fix to the call site. It does not solve the second potentially-orphan call site (
ShellSection.cs:418re-navigation path) — that path happened to pass because of pre-existing logic, but a future caller that creates an orphan Page would not be covered. The PR's central location handles all current and future callers ofApplyQueryAttributesuniformly. - try-fix-2 is a cosmetic refactor — neither better nor worse, and slightly mutates the last-page branch's behavior in an edge case (skip vs write-empty) that is consumer-equivalent but a subtle change in side-effect on the attached property.
- try-fix-3 is strictly worse: it expands
ShellContent's internal surface, loses persisted attached-property state, and ships with a double-dispatch hazard that the PR's design structurally prevents. - pr-plus-reviewer added nothing — the expert reviewer found no findings above
infoseverity. The candidate collapses topr.
Winner
pr — the PR as submitted.
Rationale:
- Smallest correct diff to production code (one new
else ifbranch inShellNavigationManager.cs). - Reuses existing dispatch infrastructure (
OnQueryAttributesPropertyChanged) with zero duplication. - Structurally avoids the double-dispatch hazard that try-fix-3 uncovered.
- Covers all current and future callers of
ApplyQueryAttributesuniformly (unlike try-fix-1 which is bound to one call site). - Passes all 309 Shell unit tests, including the 8 new tests that fail without the fix.
- Expert reviewer produced zero actionable findings above
infoseverity →pr-plus-reviewer ≡ pr.
Optional non-blocking follow-up: candidate try-fix-2's branch-collapse is a small readability improvement that could land as a separate housekeeping PR if a maintainer values the symmetry. Not blocking.
Outputs
CustomAgentLogsTmp/PRState/35432/PRAgent/expert-pr-eval/content.md— full expert review write-upCustomAgentLogsTmp/PRState/35432/PRAgent/inline-findings.json— empty findings array (no inline comments to post)CustomAgentLogsTmp/PRState/35432/PRAgent/winner.json— winner manifest
Keep both PR's intermediate page param tests and upstream's ApplyQueryAttributesNotCalledOnInactivePageDuringBackNavigation test. Accept upstream removal of iOS 26 skip guards in ShellNavigationFeatureTests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…hell navigation (#35432) <!-- Please let the below note in for people that find this PR --> > [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Fixes #35107 When `Shell.GoToAsync` pushes multiple pages in a single call (e.g., `"product/review"`), only the **last page** receives query parameters. All intermediate pages silently receive nothing — no `IQueryAttributable.ApplyQueryAttributes` call, no `[QueryProperty]` values set, no `BindingContext` propagation. ## Root Cause `ShellNavigationManager.ApplyQueryAttributes` has two branches for delivering parameters: 1. **`baseShellItem is ShellContent`** — applies params via the ShellContent instance method 2. **`isLastItem`** — applies params by setting the `QueryAttributesProperty` attached property For intermediate pages (not last in the stack), the method tries to find a `BaseShellItem` parent: ```csharp if (!(element is BaseShellItem baseShellItem)) baseShellItem = element?.Parent as BaseShellItem; ``` But intermediate pages were **just created** by `ShellSection.GetOrCreateFromRoute` and have not been added to the visual tree yet. Their `Parent` is `null`, so `baseShellItem` is `null`. Since the page is not a `ShellContent` and is not the last item, **neither branch runs** and the parameters are silently dropped. ## The Fix Added a third branch after the existing two: ```csharp else if (element is Page) { var mergedData = MergeData(element, filteredQuery, isPopping); if (mergedData.Count > 0 || !isPopping) { element.SetValue(ShellContent.QueryAttributesProperty, mergedData); } } ``` This sets the `QueryAttributesProperty` attached property directly on the page. The existing property-changed handler (`ShellContent.OnQueryAttributesPropertyChanged`) already handles: - `IQueryAttributable` interface dispatch - `BindingContext` propagation (if BindingContext differs from the page) - `[QueryProperty]` attribute reflection - `ShellNavigationQueryParameters` read-only wrapping No logic was duplicated — the fix reuses the same infrastructure that already works for the last page and ShellContent cases. ## How Parameter Scoping Works Shell already has a prefix-based scoping mechanism for targeting specific pages in a multi-page navigation. For a route like `"product/review"`: - **`?product.sku=seed-tomato`** → delivered to the page with route `"product"` as `sku=seed-tomato` - **`?stars=5`** → delivered to the last page (`"review"`) as `stars=5` - **`?product.name=Widget&name=Alice`** → `"product"` gets `name=Widget`, `"review"` gets `name=Alice` (no cross-contamination) This prefix mechanism (`ShellRouteParameters` constructor with prefix filtering) was already implemented and correct — it just could not deliver because of the null-parent bug. ## Testing **Unit tests** (`ShellParameterPassingTests.cs` — 6 new tests): - Intermediate page receives prefixed params via `IQueryAttributable` - Intermediate page receives prefixed params via `[QueryProperty]` - Last page still receives unprefixed params (regression) - Multiple intermediate pages each receive their own prefixed params (3-page deep) - Overlapping param names deliver correct distinct values to each page - Intermediate page does NOT receive unprefixed params meant for the last page **UI tests** (`ShellNavigationFeatureTests.cs` — 2 new tests): - Multi-page navigation delivers prefixed params to intermediate and unprefixed to last; verifies intermediate does not leak unprefixed params - Overlapping `name` key scoped correctly — intermediate and detail each see only their own value --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
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 if this change resolves your issue. Thank you!
Description
Fixes #35107
When
Shell.GoToAsyncpushes multiple pages in a single call (e.g.,"product/review"), only the last page receives query parameters. All intermediate pages silently receive nothing — noIQueryAttributable.ApplyQueryAttributescall, no[QueryProperty]values set, noBindingContextpropagation.Root Cause
ShellNavigationManager.ApplyQueryAttributeshas two branches for delivering parameters:baseShellItem is ShellContent— applies params via the ShellContent instance methodisLastItem— applies params by setting theQueryAttributesPropertyattached propertyFor intermediate pages (not last in the stack), the method tries to find a
BaseShellItemparent:But intermediate pages were just created by
ShellSection.GetOrCreateFromRouteand have not been added to the visual tree yet. TheirParentisnull, sobaseShellItemisnull. Since the page is not aShellContentand is not the last item, neither branch runs and the parameters are silently dropped.The Fix
Added a third branch after the existing two:
This sets the
QueryAttributesPropertyattached property directly on the page. The existing property-changed handler (ShellContent.OnQueryAttributesPropertyChanged) already handles:IQueryAttributableinterface dispatchBindingContextpropagation (if BindingContext differs from the page)[QueryProperty]attribute reflectionShellNavigationQueryParametersread-only wrappingNo logic was duplicated — the fix reuses the same infrastructure that already works for the last page and ShellContent cases.
How Parameter Scoping Works
Shell already has a prefix-based scoping mechanism for targeting specific pages in a multi-page navigation. For a route like
"product/review":?product.sku=seed-tomato→ delivered to the page with route"product"assku=seed-tomato?stars=5→ delivered to the last page ("review") asstars=5?product.name=Widget&name=Alice→"product"getsname=Widget,"review"getsname=Alice(no cross-contamination)This prefix mechanism (
ShellRouteParametersconstructor with prefix filtering) was already implemented and correct — it just could not deliver because of the null-parent bug.Testing
Unit tests (
ShellParameterPassingTests.cs— 6 new tests):IQueryAttributable[QueryProperty]UI tests (
ShellNavigationFeatureTests.cs— 2 new tests):namekey scoped correctly — intermediate and detail each see only their own value