[Testing] Feature Matrix UITest Cases for TabbedPage#31572
[Testing] Feature Matrix UITest Cases for TabbedPage#31572kubaflo merged 8 commits intodotnet:inflight/currentfrom
Conversation
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
@jsuarezruiz I have updated the test case in the latest commit. Could you please rerun the CI? |
There was a problem hiding this comment.
Pull Request Overview
This PR adds comprehensive UI test cases for the TabbedPage feature matrix, providing systematic testing of TabbedPage styling, behavior, and dynamic configuration. The tests validate various properties including BarBackground (gradient/solid), BarTextColor, Selected/Unselected tab colors, item template swapping, data source changes, programmatic selection, flow direction (RTL), overflow handling, and enabled state.
Key Changes
- Implements a comprehensive TabbedPageFeatureTests class with 24 test methods covering all major TabbedPage functionality
- Creates supporting infrastructure including TabbedPageViewModel, options page, and control page for runtime configuration testing
- Adds conditional compilation directives to handle platform-specific issues and known test failures
Reviewed Changes
Copilot reviewed 7 out of 63 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| TabbedPageFeatureTests.cs | Main test class with 24 comprehensive UI tests for TabbedPage features |
| TabbedPageViewModel.cs | ViewModel providing data binding and configuration options for TabbedPage testing |
| TabbedPageOptionsPage.xaml.cs | Code-behind for options configuration page with event handlers |
| TabbedPageOptionsPage.xaml | XAML layout for TabbedPage configuration options interface |
| TabbedPageControlPage.xaml.cs | Main TabbedPage control wrapper and navigation logic |
| TabbedPageControlPage.xaml | XAML definition of the TabbedPage with data bindings |
| CorePageView.cs | Registration of TabbedPage feature matrix in the gallery |
| App.Tap("ApplyButton"); | ||
| var rect = App.WaitForElement("ContentPageOne").GetRect(); | ||
| App.DragCoordinates(rect.X, rect.CenterY(), rect.Width - 10, rect.CenterY()); | ||
| Thread.Sleep(1000); |
There was a problem hiding this comment.
Using Thread.Sleep in UI tests is not recommended as it creates unreliable timing dependencies. Replace with App.WaitForElement or App.WaitForCondition to wait for specific UI states instead of arbitrary time delays.
| Thread.Sleep(1000); |
| [Test, Order(23)] | ||
| [Category(UITestCategories.TabbedPage)] | ||
| public void TabbedPage_IconImageSource_Change_Verify() |
There was a problem hiding this comment.
Test order conflict: Both TabbedPage_InsertTabAt_Verify (line 401) and TabbedPage_IconImageSource_Change_Verify (line 424) use Order(23). This will cause unpredictable test execution order.
|
|
||
| private async void NavigateToOptionsPage_Clicked(object sender, EventArgs e) | ||
| { | ||
| BindingContext = _viewModel = new TabbedPageViewModel(); |
There was a problem hiding this comment.
Creating a new TabbedPageViewModel instance discards the current state and configuration. This should reuse the existing _viewModel instance to maintain test state consistency.
| BindingContext = _viewModel = new TabbedPageViewModel(); | |
| BindingContext = _viewModel; |
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
@jsuarezruiz I have added the pending snapshots in the latest commit. |
|
/rebase |
0fdb060 to
fe261df
Compare
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
9dcd886 to
61bec2d
Compare
🤖 AI Summary📊 Expand Full Review —
|
| File:Line | Issue | Reviewer | Status |
|---|---|---|---|
TabbedPageFeatureTests.cs:239 |
Thread.Sleep(1000) used — anti-pattern, should use WaitForElement |
copilot-pull-request-reviewer | #if TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS) |
TabbedPageFeatureTests.cs:401,424 |
Duplicate Order(23) for TabbedPage_InsertTabAt_Verify AND TabbedPage_IconImageSource_Change_Verify — unpredictable execution order |
copilot-pull-request-reviewer | |
TabbedPageControlPage.xaml.cs:28 |
BindingContext = _viewModel = new TabbedPageViewModel() creates fresh ViewModel on every Options click, discarding state |
copilot-pull-request-reviewer |
Test Class Structure
- Class:
TabbedPageFeatureTestsextendsUITest(not_IssuesUITest) - Navigation:
App.NavigateToGallery("TabbedPage Feature Matrix")viaFixtureSetup - Tests with
#ifguards for platform-specific known issues:TEST_FAILS_ON_WINDOWS: Issues WinUI: TabbedPage pages provided by a DataTemplate crash when swapping to a different tab. #14572 (5 tests)TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS: FlowDirection testTEST_FAILS_ON_ANDROID && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_IOS && TEST_FAILS_ON_WINDOWS: MoreButton/AddTab tests (skipped everywhere)
- Tests running on Android: ~16 tests (most tests run)
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #31572 | Adds TabbedPage Feature Matrix test suite with snapshots | ⏳ PENDING (Gate) | 6 code files + 44 snapshots | Testing-only PR |
Issue: #31121 (open) - [iOS, Mac] TabbedPage FlowDirection Property Renders Opposite Layout Direction When Set via ViewModel Binding
Issue: #31377 (closed) - [iOS, Mac] TabbedPage overflow "More" button does not work
PR: #31572 - [Testing] Feature Matrix UITest Cases for TabbedPage
Author: TamilarasanSF4853 (Syncfusion partner / community contributor)
PR Type: Testing-only — adds feature matrix UI tests, no bug fix
Platforms Affected: All (Android, iOS, macOS, Windows)
Files Changed: 18 code/resource files + 82 snapshot images + 11 fruit icon images (total: ~122 files)
Prior Agent Review Found
A prior agent review was conducted on 2026-02-18. Key findings and outcomes:
- Gate PASSED: 23/23 Android tests passed
- Suggestions were implemented by contributor (2026-02-19 comment confirms)
- Duplicate
Order(23)issue was FIXED (now Order(24)/Order(25)) - Thread.Sleep anti-pattern remains (flagged but not fixed)
- Try-Fix was SKIPPED (incorrectly — this phase is mandatory)
Code Files Changed
| File | Purpose |
|---|---|
TestCases.HostApp/CoreViews/CorePageView.cs |
Registers "TabbedPage Feature Matrix" gallery entry |
TestCases.HostApp/FeatureMatrix/TabbedPage/TabbedPageControlPage.xaml[.cs] |
TabbedPage host UI |
TestCases.HostApp/FeatureMatrix/TabbedPage/TabbedPageOptionsPage.xaml[.cs] |
Options/config panel |
TestCases.HostApp/FeatureMatrix/TabbedPage/TabbedPageViewModel.cs |
ViewModel with bindings |
TestCases.Shared.Tests/Tests/FeatureMatrix/TabbedPageFeatureTests.cs |
NUnit test class (25 tests) |
| 11 fruit images | Tab icon resources |
| 82 snapshot images | Baseline screenshot images (Android, iOS, Mac, Windows) |
Test Class Structure (TabbedPageFeatureTests.cs)
- Class:
TabbedPageFeatureTestsextends_GalleryUITest - Navigation:
App.NavigateToGallery("TabbedPage Feature Matrix")via base class - 25 ordered test cases with
VerifyScreenshot()for visual regression - Platform-specific
#ifguards:TEST_FAILS_ON_WINDOWS(5 tests): BarBackground_Solid, BarBackground_And_BarTextColor, SelectedAndUnselectedTabColor, RemoveTab, InsertTabAtTEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS(1 test): FlowDirection (issues [iOS, Mac] TabbedPage FlowDirection Property Renders Opposite Layout Direction When Set via ViewModel Binding #31121, WinUI: TabbedPage pages provided by a DataTemplate crash when swapping to a different tab. #14572)TEST_FAILS_ON_ANDROID && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_IOS && TEST_FAILS_ON_WINDOWS(2 tests): MoreButton, AddTab (skipped everywhere)
Tests Running on Android (~21 tests)
Order 1 through 25, excluding Windows-only tests and the fully-disabled MoreButton/AddTab.
Key Findings (Current State After Contributor Updates)
| Finding | Status |
|---|---|
Duplicate Order(23) → Fixed to Order(24) and Order(25) |
✅ FIXED |
Thread.Sleep(1000) in TabbedPage_FlowDirection_Verify (line 221) |
|
| ViewModel re-creation on Options tap | |
| Missing NOTE block in PR description | ✅ ALREADY IN PR |
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #31572 | Adds TabbedPage Feature Matrix test suite (25 tests, 82 snapshots) | ⏳ PENDING (Gate) | 18 code files + 82 snapshots | Testing-only PR |
🚦 Gate — Test Verification
📝 Review Session — added snapshots · 61bec2d
Result: ✅ PASSED
Platform: Android
Mode: Tests Run and Verified
Test Results
- Tests run: 23
- Tests passed: 23 ✅
- Tests failed: 0
- Tests skipped: 0
Note: Testing-Only PR
This is a testing-only PR (no bug fix). The Gate phase verified that:
- Tests build and deploy successfully on Android
- All 23 Android-applicable tests pass with the committed snapshots
- Tests pass with the current codebase
The standard verify-tests-fail-without-fix approach does not apply here since there is no bug fix to revert. Instead, Gate verified the tests run correctly.
Tests That Passed (23)
- TabbedPage_InitialState_VerifyVisualState
- TabbedPage_InitialState_VerifyFunctionalState
- TabbedPage_BarBackground_Gradient_Verify
- TabbedPage_BarBackground_Solid_Verify
- TabbedPage_BarBackground_And_BarTextColor_Verify
- TabbedPage_BarBackground_With_SelectedTabColor_Verify
- TabbedPage_BarBackground_With_UnselectedTabColor_Verify
- TabbedPage_BarTextColor_Verify
- TabbedPage_BarTextColor_And_SelectedTabColor_Verify
- TabbedPage_BarTextColor_And_UnselectedTabColor_Verify
- TabbedPage_SelectedTabColor_Verify
- TabbedPage_UnselectedTabColor_Verify
- TabbedPage_SelectedAndUnselectedTabColor_Verify
- TabbedPage_FlowDirection_Verify
- TabbedPage_ItemTemplate_Verify
- TabbedPage_ItemTemplate_And_ItemSource_Verify
- TabbedPage_ItemSource_Verify
- TabbedPage_ItemSource_And_SelectedItems_Verify
- TabbedPage_SelectedItems_Verify
- TabbedPage_RemoveTab_Verify
- TabbedPage_InsertTabAt_Verify
- TabbedPage_IconImageSource_Change_Verify
- TabbedPage_IsEnabled_Verify
Gate Result: ⚠️ ENVIRONMENT BLOCKED
Platform: Android
Mode: Full Verification (attempted)
- Tests FAIL without fix: N/A (testing-only PR)
- Tests PASS with fix: ❌ (environment blocked — could not run)
Environment Blocker Details
Both test attempts failed with environment-level errors:
Attempt 1: System.TimeoutException: Timed out waiting for Go To Test button to appear
- App failed to show gallery navigation UI within 2-minute timeout
- Build succeeded (8m 9s), 39 tests all failed at OneTimeSetUp
Attempt 2 (retry): ADB command failed with exit code 20
cmd: Can't find service: settings- Android emulator infrastructure issue (missing ADB services)
- All 39 tests failed during initialization
Prior Gate Evidence (2026-02-18)
A prior agent review ran the gate successfully:
- Result: ✅ PASSED
- Tests: 23/23 Android tests passed
- Commit: 61bec2d (snapshot commit)
Code Changes Since Prior Gate
The contributor made one change after the prior review:
- Fixed duplicate
Order(23)→Order(24)andOrder(25)(per contributor's comment)
This change does not affect test logic, only execution ordering.
Assessment
The prior gate passed and the subsequent code change was a non-functional ordering fix. The current environment is blocking test execution (emulator infrastructure issue). Gate is considered
🔧 Fix — Analysis & Comparison
📝 Review Session — added snapshots · 61bec2d
Result: ✅ PASSED
Platform: Android
Mode: Tests Run and Verified
Test Results
- Tests run: 23
- Tests passed: 23 ✅
- Tests failed: 0
- Tests skipped: 0
Note: Testing-Only PR
This is a testing-only PR (no bug fix). The Gate phase verified that:
- Tests build and deploy successfully on Android
- All 23 Android-applicable tests pass with the committed snapshots
- Tests pass with the current codebase
The standard verify-tests-fail-without-fix approach does not apply here since there is no bug fix to revert. Instead, Gate verified the tests run correctly.
Tests That Passed (23)
- TabbedPage_InitialState_VerifyVisualState
- TabbedPage_InitialState_VerifyFunctionalState
- TabbedPage_BarBackground_Gradient_Verify
- TabbedPage_BarBackground_Solid_Verify
- TabbedPage_BarBackground_And_BarTextColor_Verify
- TabbedPage_BarBackground_With_SelectedTabColor_Verify
- TabbedPage_BarBackground_With_UnselectedTabColor_Verify
- TabbedPage_BarTextColor_Verify
- TabbedPage_BarTextColor_And_SelectedTabColor_Verify
- TabbedPage_BarTextColor_And_UnselectedTabColor_Verify
- TabbedPage_SelectedTabColor_Verify
- TabbedPage_UnselectedTabColor_Verify
- TabbedPage_SelectedAndUnselectedTabColor_Verify
- TabbedPage_FlowDirection_Verify
- TabbedPage_ItemTemplate_Verify
- TabbedPage_ItemTemplate_And_ItemSource_Verify
- TabbedPage_ItemSource_Verify
- TabbedPage_ItemSource_And_SelectedItems_Verify
- TabbedPage_SelectedItems_Verify
- TabbedPage_RemoveTab_Verify
- TabbedPage_InsertTabAt_Verify
- TabbedPage_IconImageSource_Change_Verify
- TabbedPage_IsEnabled_Verify
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #31572 | Adds TabbedPage Feature Matrix test suite (25 tests, 82 snapshots) | ✅ PASS (prior Gate - 23/23) | 18 code files + 82 snapshots | Testing-only PR |
| 1 | try-fix (claude-sonnet-4.6) | Remove Thread.Sleep(1000), add VerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2)) |
TabbedPageFeatureTests.cs (+1/-2) |
Correct fix, env issue | |
| 2 | try-fix (claude-opus-4.6) | Remove duplicate TAB 7 tap, add missing VerifyScreenshot() in AddTab_Verify |
✅ PASS (39/39 Android) | TabbedPageFeatureTests.cs (+1/-3) |
Code quality improvement |
Attempt 1 Details (claude-sonnet-4.6)
- Approach: Remove
Thread.Sleep(1000)anti-pattern fromTabbedPage_FlowDirection_Verify, replace withVerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2)) - Result:
⚠️ BLOCKED — Android emulator force-stopped mid-run;_GalleryUITest.FixtureSetup()timed out for all tests - Note:
EstablishBrokenBaseline.ps1reported "No fix files detected" (expected for testing-only PR) - Diff:
- App.DragCoordinates(rect.X, rect.CenterY(), rect.Width - 10, rect.CenterY());
- Thread.Sleep(1000);
- App.WaitForElement("Tab2Label");
- VerifyScreenshot();
+ App.DragCoordinates(rect.X, rect.CenterY(), rect.Width - 10, rect.CenterY());
+ App.WaitForElement("Tab2Label");
+ VerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2));Attempt 2 Details (claude-opus-4.6)
- Approach: Remove duplicate
App.WaitForElement("TAB 7"); App.Tap("TAB 7"); App.WaitForElement("Tab7Label")sequence inTabbedPage_AddTab_Verify; add missingVerifyScreenshot() - Result: ✅ PASS — 39/39 Android tests passed
- Diff:
- App.WaitForElement("TAB 7");
- App.Tap("TAB 7");
- App.WaitForElement("Tab7Label");
+ VerifyScreenshot();Attempt 3 Details (claude-opus-4.6, cross-pollination)
- Approach: Extract inline
#if ANDROIDinTabbedPage_RemoveTab_Verifyto a class-levelRemoveTabIterationCountconstant; extract#if IOS || MACCATALYST"More" button logic inMoreButton_Verify/AddTab_Verifyto aTapMoreButtonIfAvailable()helper method - Result: ✅ PASS — 39/39 Android tests passed
- Diff summary:
+#if ANDROID
+ const int RemoveTabIterationCount = 2;
+#else
+ const int RemoveTabIterationCount = 7;
+#endif
+
+ void TapMoreButtonIfAvailable()
+ {
+#if IOS || MACCATALYST
+ App.WaitForElement("More");
+ App.Tap("More");
+#endif
+ }
// RemoveTab: loop uses RemoveTabIterationCount instead of inline #if
// MoreButton/AddTab: TapMoreButtonIfAvailable() replaces inline #if IOS||MACCATALYSTCross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | YES → Attempt 3 | Inline #if refactor in RemoveTab/MoreButton/AddTab |
| claude-sonnet-4.6 | 2 | ENDORSE: Inline #if | Agreed with opus suggestion |
| claude-opus-4.6 | 3 | NO NEW IDEAS | After attempt 3 |
| claude-sonnet-4.6 | 3 | NO NEW IDEAS | After seeing all 3 attempts |
Exhausted: Yes — both models said NO NEW IDEAS after 3 rounds
Best Fix Comparison
| # | Source | Approach | Test Result | Simplicity | Notes |
|---|---|---|---|---|---|
| PR | PR #31572 | Test suite as submitted | ✅ PASS (prior Gate 23/23) | Baseline | Has Thread.Sleep, duplicate sequence, inline #if |
| 1 | try-fix sonnet | Remove Thread.Sleep → retryTimeout | +1/-2 lines | Correct fix, unverifiable due to env | |
| 2 | try-fix opus | Remove duplicate TAB 7 tap, add VerifyScreenshot | ✅ PASS 39/39 | +1/-3 lines | Genuine code quality improvement |
| 3 | try-fix opus | Extract inline #if to const + helper method | ✅ PASS 39/39 | +17/-17 lines | Guideline compliance fix |
Selected Fix: PR's fix (with suggested improvements from attempts 1–3) — The PR's tests are functionally correct and valuable. The try-fix alternatives found 3 code quality improvements that should be requested as changes before merge.
📋 Report — Final Recommendation
📝 Review Session — added snapshots · 61bec2d
✅ Final Recommendation: APPROVE (with suggestions)
Summary
This is a community-contributed testing PR from Syncfusion partner that adds a comprehensive feature matrix UI test suite for TabbedPage. It adds 24 NUnit tests covering bar background, bar text color, tab colors, item templates, data sources, programmatic selection, flow direction, and tab management. All 23 applicable Android tests passed in Gate verification.
The PR adds valuable test coverage for a control that was missing feature matrix tests. A few code quality issues should be fixed in a follow-up or requested as changes before merge.
Root Cause (of test gaps being addressed)
TabbedPage lacked comprehensive feature matrix tests, making it difficult to detect regressions in styling, dynamic configuration, and platform-specific behaviors. This PR addresses that gap.
Gate Results
23/23 Android tests passed ✅
All tests ran successfully on Android with committed snapshot images.
Title & Description Review
Title: [Testing] Feature Matrix UITest Cases for TabbedPage
- ✅ Clear and descriptive for a testing PR
- ✅
[Testing]prefix accurately categorizes the PR type
Description: Missing the required NOTE block at the top.
<!-- 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!Code Review Findings
🔴 Issues to Address
1. Duplicate Order(23) on two test methods
- File:
TabbedPageFeatureTests.cs:401and:424 - Problem: Both
TabbedPage_InsertTabAt_Verify(inside#if TEST_FAILS_ON_WINDOWS) andTabbedPage_IconImageSource_Change_Verify(outside any guard) have[Test, Order(23)]. On Android, both tests run with the same order number, causing unpredictable execution order. - Recommendation: Renumber
TabbedPage_IconImageSource_Change_VerifytoOrder(24)andTabbedPage_IsEnabled_VerifytoOrder(25).
2. Thread.Sleep(1000) in TabbedPage_FlowDirection_Verify
- File:
TabbedPageFeatureTests.cs:239 - Problem:
Thread.Sleep(1000)creates an unreliable timing dependency. While this test only runs on Android (guarded by#if TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS), it's still an anti-pattern. - Recommendation: Replace with
App.WaitForElement("Tab2Label")or useVerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2))for the screenshot call.
🟡 Suggestions
3. ViewModel re-creation on Options tap
- File:
TabbedPageControlPage.xaml.cs:28 - Problem:
BindingContext = _viewModel = new TabbedPageViewModel()creates a fresh ViewModel every time the Options button is tapped, discarding current test state. - Context: This may be intentional for test isolation (resetting to defaults between tests). However, the Copilot reviewer flagged it. If tests are designed to be cumulative/sequential, this reset could cause unexpected behavior.
- Recommendation: Clarify intent with a comment, or change to
BindingContext = _viewModelif the current_viewModelshould be preserved when navigating to options.
✅ What Looks Good
- ✅ Proper use of
#ifguards for platform-specific known issues (referencing issue numbers) - ✅ Tests use
App.WaitForElement()before interactions (good reliability) - ✅ AutomationIds are consistent between HostApp and test code
- ✅ Screenshot-based verification with committed baseline snapshots
- ✅ Platform-specific items source (Android uses 5 tabs, others use 10 for "More" tab testing)
- ✅ Tests that can't pass on ANY platform are clearly marked and excluded (
MoreButtonandAddTab)
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #31572 | Adds TabbedPage Feature Matrix test suite (24 tests, 44 snapshots) | ✅ PASS (Gate - 23/23) | 6 code files + 44 snapshots | Testing-only PR |
Selected Fix: PR's tests — all Android tests pass and the PR adds valuable coverage that was missing.
Before Merge
- Add NOTE block to PR description
- Fix duplicate
Order(23)(renumberTabbedPage_IconImageSource_Change_Verify→Order(24),TabbedPage_IsEnabled_Verify→Order(25)) - Replace
Thread.Sleep(1000)withApp.WaitForElement("Tab2Label")inTabbedPage_FlowDirection_Verify - Clarify or fix ViewModel re-creation in
NavigateToOptionsPage_Clicked
⚠️ Final Recommendation: REQUEST CHANGES
Result:
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | ✅ COMPLETE | Testing-only PR, prior agent review found and confirmed |
| Gate | Android emulator instability; prior Gate ✅ PASSED (23/23, 2026-02-18) | |
| Try-Fix | ✅ COMPLETE | 3 attempts; 2 passing with quality improvements found |
| Report | ✅ COMPLETE |
Summary
PR #31572 adds a comprehensive feature matrix UI test suite for TabbedPage — 25 ordered NUnit tests covering bar background, bar text color, tab colors, item templates, data sources, programmatic selection, flow direction, tab management, and icon changes. It is a testing-only PR with no framework bug fix.
The prior agent review (2026-02-18) verified 23/23 Android tests pass. The contributor addressed the prior duplicate-Order suggestion. However, try-fix exploration revealed 3 code quality issues that remain unaddressed and should be fixed before merge.
Root Cause (of issues found)
The PR adds valuable test coverage, but 3 guideline violations were found in the test code:
Thread.Sleep(1000)anti-pattern inTabbedPage_FlowDirection_Verify— should useretryTimeoutparameter- Redundant duplicate element-wait-tap sequence in
TabbedPage_AddTab_Verify— dead code repetition - Inline
#if ANDROID/#if IOS || MACCATALYSTdirectives inside test method bodies — violates "No Inline #if Directives in Test Methods" guideline
Gate Results
- Prior Gate (2026-02-18): ✅ PASSED — 23/23 Android tests
- Current Gate:
⚠️ ENVIRONMENT BLOCKED — Android emulator instability (ADB service errors) - Code changes since prior Gate: Only ordering fix (Order(24)/Order(25)) — non-functional change, does not affect pass/fail
Try-Fix Results
| # | Approach | Result | Impact |
|---|---|---|---|
| 1 | Remove Thread.Sleep(1000), use VerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2)) |
Anti-pattern fix | |
| 2 | Remove duplicate TAB 7 tap sequence; add missing VerifyScreenshot() to AddTab_Verify |
✅ PASS 39/39 | Code correctness |
| 3 | Extract #if ANDROID → RemoveTabIterationCount const; #if IOS||MACCATALYST → TapMoreButtonIfAvailable() |
✅ PASS 39/39 | Guideline compliance |
Selected Fix: PR's tests are the correct foundation. All 3 try-fix improvements should be incorporated as code quality changes before merge.
Code Review Findings
🔴 Required Changes
1. Thread.Sleep(1000) in TabbedPage_FlowDirection_Verify (line 221)
// Current (BAD):
App.DragCoordinates(rect.X, rect.CenterY(), rect.Width - 10, rect.CenterY());
Thread.Sleep(1000);
App.WaitForElement("Tab2Label");
VerifyScreenshot();
// Recommended:
App.DragCoordinates(rect.X, rect.CenterY(), rect.Width - 10, rect.CenterY());
App.WaitForElement("Tab2Label");
VerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2));2. Duplicate element sequence in TabbedPage_AddTab_Verify
// Current (BAD) — identical WaitForElement/Tap/WaitForElement repeated:
App.WaitForElement("TAB 7");
App.Tap("TAB 7");
App.WaitForElement("Tab7Label");
App.WaitForElement("TAB 7"); // ← duplicate
App.Tap("TAB 7"); // ← duplicate
App.WaitForElement("Tab7Label"); // ← duplicate
// Recommended — remove the duplicate, add VerifyScreenshot:
App.WaitForElement("TAB 7");
App.Tap("TAB 7");
App.WaitForElement("Tab7Label");
VerifyScreenshot();3. Inline #if directives in test methods (guideline violation)
Per UI test guidelines: "No Inline #if Directives in Test Methods — Move platform-specific logic to extension methods."
// Current (BAD) in TabbedPage_RemoveTab_Verify:
#if ANDROID
for (int i = 0; i < 2; i++) { ... }
#else
for (int i = 0; i < 7; i++) { ... }
#endif
// Recommended — class-level constant:
#if ANDROID
const int RemoveTabIterationCount = 2;
#else
const int RemoveTabIterationCount = 7;
#endif
// And in MoreButton/AddTab — extract to helper:
void TapMoreButtonIfAvailable()
{
#if IOS || MACCATALYST
App.WaitForElement("More");
App.Tap("More");
#endif
}✅ What Looks Good
- ✅ Test ordering now correct (Order 1–25, no duplicates after contributor fix)
- ✅ All tests properly gated with
#if TEST_FAILS_ON_*+ issue link comments - ✅
WaitForElementused before all interactions - ✅
VerifyScreenshot()used consistently for visual validation (except AddTab as noted) - ✅ AutomationIds consistent between HostApp and test code
- ✅ Platform-conditional ItemsSource (5 items Android, 10 for others) documented
- ✅ Tests disabled on ALL platforms (
MoreButton,AddTab) clearly marked with all 4 platform guards + issue numbers - ✅ Extends
_GalleryUITestcorrectly, usesGalleryPageNamepattern
Before Merge
- Remove
Thread.Sleep(1000), useVerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2))inTabbedPage_FlowDirection_Verify - Remove duplicate
WaitForElement("TAB 7") / Tap / WaitForElementsequence inTabbedPage_AddTab_Verify; addVerifyScreenshot() - Extract
#if ANDROIDloop count inTabbedPage_RemoveTab_Verifyto class-level constant - Extract
#if IOS || MACCATALYST"More" button taps to a helper method
📋 Expand PR Finalization Review
PR #31572 Finalization Review
PR Title: [Testing] Feature Matrix UITest Cases for TabbedPage
Author: TamilarasanSF4853 (Syncfusion partner/community)
Base Branch: main
Labels: area-controls-tabbedpage, community ✨, partner/syncfusion, s/agent-reviewed, s/agent-approved, s/agent-gate-passed, s/agent-suggestions-implemented, s/agent-fix-pr-picked
Phase 1: Title & Description Review
🟡 Title: Needs Minor Update
Current: [Testing] Feature Matrix UITest Cases for TabbedPage
Issue: The [Testing] prefix is non-standard in this repository. All other Feature Matrix PRs use the control name as the platform/component prefix. [Testing] is ambiguous and doesn't follow the established title formula.
Recommended: [TabbedPage] Add Feature Matrix UI tests for styling, data, and interaction behaviors
Rationale:
- Follows the
[Component] Verb + Whatformula used by similar PRs - Identifies TabbedPage as the affected area up front
- More searchable in git history than
[Testing]
✅ Description: Good Quality — Minor Enhancements Only
Quality Assessment:
| Indicator | Assessment |
|---|---|
| Structure | ✅ Clear sections with NOTE block, feature list, issues |
| Technical depth | ✅ Lists all scenarios covered |
| Accuracy | ✅ Matches actual diff |
| NOTE block present | ✅ At top of description |
| Issue links | ✅ Issues #31121 and #31377 referenced |
| Completeness |
Action: The existing description is good. Recommend adding a Platforms Tested section to clarify cross-platform coverage.
Suggested addition (append after Issues section):
### Platforms Tested
- [x] Android
- [x] iOS
- [x] MacCatalyst
- [x] Windows
> **Note:** Some tests are conditionally compiled out with `TEST_FAILS_ON_*` constants due to known platform issues (#31121 FlowDirection on iOS/Mac; #31377 overflow/More on all platforms except Android; #14572 Windows tab interaction).Phase 2: Code Review
🔴 Critical Issues
1. Thread.Sleep() in Test Code
- File:
src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/TabbedPageFeatureTests.cs(line ~185) - Problem:
TabbedPage_FlowDirection_VerifyusesThread.Sleep(1000)after a drag gesture. Per UI testing guidelines, arbitrary sleep is prohibited — useVerifyScreenshot(retryTimeout: ...)orApp.WaitForElement()instead. - Code:
App.DragCoordinates(rect.X, rect.CenterY(), rect.Width - 10, rect.CenterY()); Thread.Sleep(1000); // ❌ PROHIBITED App.WaitForElement("Tab2Label");
- Recommended fix:
App.DragCoordinates(rect.X, rect.CenterY(), rect.Width - 10, rect.CenterY()); App.WaitForElement("Tab2Label"); // Let WaitForElement handle timing VerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2));
Note:
TabbedPage_FlowDirection_Verifyis already gated byTEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWSso it only runs on Android, where theThread.Sleepis the issue.
🟡 Suggestions
2. Missing Newline at End of Files
- Files affected:
TabbedPageControlPage.xaml(\ No newline at end of file)TabbedPageControlPage.xaml.cs(\ No newline at end of file)TabbedPageFeatureTests.cs(\ No newline at end of file)TabbedPageViewModel.cs(\ No newline at end of file)
- Fix: Add a trailing newline to each file. Run
dotnet formatto catch these automatically.
3. Unused Image Asset: fruitsicon.png
- File:
src/Controls/tests/TestCases.HostApp/Resources/Images/fruitsicon.png - Problem: This image is added but does not appear to be referenced anywhere in the XAML or ViewModel code. Template One uses
bank.pngfor tab icons; Template Two sets icons viaTabbedPageItemSource.ImageUrlproperties (which are all individual fruit images).fruitsicon.pngis orphaned. - Recommendation: Either use it (e.g., as the TabbedPage toolbar icon) or remove it to avoid unnecessary resource bloat.
4. ViewModel Reset on Every "Options" Tap
- File:
TabbedPageControlPage.xaml.cs - Problem:
Every time a user taps "Options", a new
private async void NavigateToOptionsPage_Clicked(object sender, EventArgs e) { BindingContext = _viewModel = new TabbedPageViewModel(); // Resets ALL settings! await Navigation.PushModalAsync(new TabbedPageOptionsPage(_viewModel)); }
TabbedPageViewModelis created and the existing configuration is lost. This is functionally correct for the tests (which are[Order]ed and independent), but can confuse manual testers who expect their previously applied settings to be preserved. - Recommendation: Consider only creating a new ViewModel on initial construction, and passing the existing
_viewModelto the options page on subsequent taps, so applied settings are visible when re-entering the options page. However, this is a lower-priority UX concern since tests pass.
5. [Order] Attributes on Potentially-Independent Tests
- File:
TabbedPageFeatureTests.cs - Context: Tests use
[Order(N)]attributes. Since each test navigates to Options and creates a fresh ViewModel (see issue Aloha System.Maui! #4 above), tests are effectively independent. The[Order]attribute suggests sequential dependency but there is none. - Recommendation: Either remove
[Order](preferred for independent tests) or document that ordering is for organizational clarity only.
6. TabbedPage_IsEnabled_Verify Test Logic Ambiguity
- File:
TabbedPageFeatureTests.cs(Test Remove the Use2017 build property #25) - Problem:
The test sets
// Sets IsEnabled=false, applies, then tries to navigate to Options App.Tap("Options"); App.WaitForNoElement("ApplyButton");
IsEnabled=falseon the TabbedPage, then verifies it cannot reach the Options page (because the TitleView "Options" button presumably becomes inoperable). However, the "Options" button is set viaNavigationPage.SetTitleView, which may not be affected byTabbedPage.IsEnabledon all platforms. This test may pass for the wrong reason on some platforms (e.g., the button tap times out rather than being blocked by IsEnabled). - Recommendation: Add a comment explaining what behavior is expected, and consider a more direct assertion (e.g.,
App.WaitForElement("TabbedPageControl")and verifying a child tap fails) to make the intent clearer.
✅ Looks Good
- NOTE block present at the top of the description — users can test PR artifacts
TEST_FAILS_ON_*constants correctly used for platform-specific exclusions with linked issue numbers[Category(UITestCategories.TabbedPage)]on the class (not per-method) — correct pattern_GalleryUITestbase class used correctly for Feature Matrix tests- Comprehensive test coverage: 25 ordered test scenarios covering BarBackground (gradient/solid), BarTextColor, SelectedTabColor, UnselectedTabColor, FlowDirection, ItemsSource, ItemTemplate, SelectedItem, IconImageSource change, IsEnabled, tab manipulation (Insert, Remove)
- AutomationIds are consistently assigned to all interactive elements in both HostApp and test code
- MVVM pattern used properly with
INotifyPropertyChangedfor all bindable properties - Platform-specific ItemsSourceOne/Two — Android has 5 tabs (no More button), non-Android has 10 tabs (triggers More) — this is intentional and correctly handles the platform difference
- Snapshots provided for all four platforms: Android, iOS (ios-26), Mac, Windows
Summary
| Area | Status |
|---|---|
| Title | 🟡 Update recommended (drop [Testing] prefix) |
| NOTE block | ✅ Present |
| Description accuracy | ✅ Matches implementation |
| Platforms tested section | |
Thread.Sleep in tests |
🔴 Must fix — use WaitForElement + retryTimeout |
| Missing newlines | 🟡 Run dotnet format before merge |
Unused asset fruitsicon.png |
🟡 Remove or use |
| ViewModel reset behavior | 🟡 Low priority — tests pass, UX issue only |
| Overall code quality | ✅ Good — comprehensive, well-structured |
Merge Readiness: The Thread.Sleep is the only blocking issue. After fixing that and running dotnet format, this PR is ready for merge.
I’ve updated the changes based on the summary.
|
1e6bf7d to
9440f7e
Compare
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 31572Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 31572" |
|
/azp run maui-pr-uitests |
|
No pipelines are associated with this pull request. |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
Hi! Looks like tests are failing |
kubaflo
left a comment
There was a problem hiding this comment.
Failing tests :/ Could you please verify?
@kubaflo Resolved the failures. |
> [!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! This PR includes a comprehensive set of UI test cases for the TabbedPage feature matrix. The tests validate TabbedPage styling, behavior, and dynamic configuration including BarBackground (gradient/solid), BarTextColor, Selected/Unselected tab colors, item template swapping, data source changes, programmatic selection, flow direction (RTL), overflow (“More”) handling, and enabled state. ### TabbedPage Implementation: - Adds an options-driven TabbedPage gallery supporting runtime changes to bar background (gradient/solid), bar text color, selected/unselected tab colors, item template, items source, programmatic selection, flow direction (RTL), overflow (“More”), and IsEnabled. - UI tests (TabbedPageFeatureTests) apply each configuration, verify visual state via screenshots, and use method-based naming for multi-step captures. - Platform-specific scenarios (Windows styling, RTL, overflow) are conditionally compiled due to known issues. Establishes a compact Feature matrix for TabbedPage styling, data, and interaction behaviors. ### Issues Identified: - #31121 - #31377 https://github.com/user-attachments/assets/f84e7812-76b3-4cc9-aee6-6de76325b842
> [!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! This PR includes a comprehensive set of UI test cases for the TabbedPage feature matrix. The tests validate TabbedPage styling, behavior, and dynamic configuration including BarBackground (gradient/solid), BarTextColor, Selected/Unselected tab colors, item template swapping, data source changes, programmatic selection, flow direction (RTL), overflow (“More”) handling, and enabled state. ### TabbedPage Implementation: - Adds an options-driven TabbedPage gallery supporting runtime changes to bar background (gradient/solid), bar text color, selected/unselected tab colors, item template, items source, programmatic selection, flow direction (RTL), overflow (“More”), and IsEnabled. - UI tests (TabbedPageFeatureTests) apply each configuration, verify visual state via screenshots, and use method-based naming for multi-step captures. - Platform-specific scenarios (Windows styling, RTL, overflow) are conditionally compiled due to known issues. Establishes a compact Feature matrix for TabbedPage styling, data, and interaction behaviors. ### Issues Identified: - dotnet#31121 - dotnet#31377 https://github.com/user-attachments/assets/f84e7812-76b3-4cc9-aee6-6de76325b842




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!
This PR includes a comprehensive set of UI test cases for the TabbedPage feature matrix. The tests validate TabbedPage styling, behavior, and dynamic configuration including BarBackground (gradient/solid), BarTextColor, Selected/Unselected tab colors, item template swapping, data source changes, programmatic selection, flow direction (RTL), overflow (“More”) handling, and enabled state.
TabbedPage Implementation:
Issues Identified:
Screen.Recording.2025-09-22.at.1.24.48.PM.mov