Add AddResourceDictionary API and cross-app testing sample#135
Open
mattleibow wants to merge 19 commits into
Open
Add AddResourceDictionary API and cross-app testing sample#135mattleibow wants to merge 19 commits into
mattleibow wants to merge 19 commits into
Conversation
This was referenced May 22, 2026
Open
- Add DeviceTestingKitApp.AppTests project that references the real app as a library (IsTestLibrary=true strips entry points and resources) - Add AddResourceDictionary<T>() convenience method on the config builder for cleaner usage in lambda expressions - Add x:Class to sample app's Colors.xaml and Styles.xaml to make them instantiable from test projects - Add NUnit tests verifying MainPage instantiation and style resolution - Wire up library-mode MSBuild in DeviceTestingKitApp.csproj (conditional OutputType, strip MauiIcon/Splash/Images/Fonts/Assets when IsTestLibrary) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Move service/VM/page/font registration into a shared extension method (ServiceCollectionExtensions.AddDeviceTestingKitAppServices) so both the real app and test projects call the same code - Remove font files from AppTests (they flow from the app library reference) - Simplify AppTests MauiProgram to just call the shared method - Reduce IsTestLibrary conditions to only MauiIcon and MauiSplashScreen (images, fonts, and raw assets don't conflict) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Merge each resource dictionary into Application.Resources immediately
after creation (not batch-then-merge). This ensures Styles.xaml can
resolve {StaticResource Primary} from Colors.xaml during its
InitializeComponent().
- Replace Application.Current.Resources lookups in RunStatusToColorConverter
with hardcoded colors. Resources are now page-level scoped so the
converter cannot reach them via Application.Resources, and during app
teardown the lookup would throw KeyNotFoundException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Verify CounterButton exists in MainPage visual tree - Test initial button text renders correctly via converter - Test IncrementCommand is wired to button and updates VM state - Test multiple command executions via button.Command binding - Add helper FindByAutomationId<T> for visual tree traversal Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Push MainPage as a modal onto the runner's navigation stack, then execute the counter button's command and assert that the Button.Text binding updates via the converter (Click me! → Clicked 1 time → ...). Runs on the UI thread via MainThread.InvokeOnMainThreadAsync to satisfy UIKit thread affinity requirements. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Explains the full pattern: making the app buildable as a library, adding x:Class to resource dictionaries, creating the test project, configuring AddResourceDictionary, and writing live binding tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resizetizer's transitive GetMauiItems target doesn't pass AdditionalProperties from ProjectReference, so the app's MauiIcon leaks into the test project even when IsTestLibrary=true strips it from the app's own build. Add a target that removes the imported appicon after ResizetizeCollectItems runs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…unds.targets Adopt Pedro's pattern: Configuration=Library$(Configuration) on ProjectReference triggers IsTestProject=true in the app. This naturally gives separate intermediate paths and eliminates file-locking race conditions during parallel solution builds. Extract all MSBuild workaround logic into TestingWorkarounds.targets files in each project folder to keep csproj files clean. Includes per-platform entry point stripping, Resizetizer item removal, and Windows PRI fix. Update documentation to reflect the new pattern. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Normalize backslashes to forward slashes before Contains() check so the workaround works on both macOS and Windows CI agents. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add section explaining what to remove from TestingWorkarounds.targets once the Resizetizer fix lands, and what must remain (Windows PRI workaround and the app-side library mode targets). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Include complete TestingWorkarounds.targets as code fences that users can copy directly. Explain why Configuration=Library$(Configuration) is needed. Document the Windows PRI and Resizetizer issues with links to dotnet/maui#35574 and #35575. Add section on what to remove once fix ships. Tracking: #136 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When the app builds in library mode (Configuration=LibraryRelease), its ProjectReferences to MauiLibrary/Library were still building as plain Release. This caused a file-locking race with the solution-level build of MauiLibrary (same config, same intermediate path, two MSBuild nodes racing on XamlCTask). Fix: propagate Configuration=LibraryRelease to transitive references via AdditionalProperties when IsTestProject=true, giving them separate output paths that cannot conflict with the solution-level build. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Propagating Configuration=Library$(Configuration) to transitive references (MauiLibrary) caused APPX1101 duplicate payload errors on Windows: the test app sees MauiLibrary.dll from both debug/ and librarydebug/ output paths. The original XamlCTask parallel race was a one-off flaky failure (passed on ADO, failed once on GH Actions). Removing the propagation fixes the Windows packaging error. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
6500747 to
db9c4a5
Compare
Verify that styles from MauiLibrary's CounterStyles.xaml flow correctly into the test app via AddResourceDictionary. Tests confirm: - CounterButtonColor (#FF6B6B) is resolvable from Application.Resources - CounterButtonTextColor (white) is resolvable - Live button actually renders with the coral background, not default purple Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove internal MSBuild details (why Configuration=Library, Resizetizer/PRI internals) and restructure as a quick-start guide for developers who want to test their app's controls and services on device with real styles. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add DeviceRunners.Testing.Targets, VisualRunners.NUnit, and VisualRunners.Maui as PackageReference (not ProjectReference) - Correct resource scoping description: implicit styles still apply globally by design Found by Opus 4.7 and GPT 5.5 review. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…m order - Change prereq from .NET 9+ to .NET 10+ (all examples use net10.0 TFMs) - Add GenerateTestingPlatformEntryPoint=false to csproj snippet - Fix FindByAutomationId pattern match: ContentPage arm before IContentView - Add note that helper only covers simple ContentPage/Layout hierarchies Found by Opus 4.7 and GPT 5.5 review. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Enables testing custom controls, ViewModels, and services inside a real MAUI app by referencing the app as a library from a separate test project. The app's styles, DI container, and resources are fully available in tests.
Key changes
AddResourceDictionary<T>()API — Register app resource dictionaries (Colors, Styles) into the visual test runner so{StaticResource}resolves correctly during tests.Page-level runner resources — Runner styles moved from
Application.Resourcesto page-levelVisualRunnerResources.xaml, preventing conflicts with app styles.Library-mode project reference — Test project references the app with
<AdditionalProperties>Configuration=Library$(Configuration)</AdditionalProperties>, which triggers the app-side targets to build as a library (no entry points, no icons, no packaging).TestingWorkarounds.targets(drop-in files) — Two.targetsfiles handle all MSBuild workarounds:OutputType=Library, strips platform entry points, removes icons/splash, disables packaging. Propagates Configuration to transitive refs to prevent parallel build races.Sample
DeviceTestingKitApp.AppTests— 10 NUnit tests demonstrating the pattern: page creation with styles, binding context, custom controls, command wiring, live modal navigation.Documentation — Full guide at
docs/articles/testing-with-app-resources.mdwith drop-in code fences for both targets files.Upstream issues filed
Architecture
What users do
TestingWorkarounds.targetsto their app (imports via csproj)TestingWorkarounds.targetsto their test project<AdditionalProperties>Configuration=Library$(Configuration)</AdditionalProperties>AddResourceDictionary<Colors>()andAddResourceDictionary<Styles>()in test app setupOnce upstream fixes ship
_RemoveImportedAppResizetizerItemsfrom test-side targets (after maui#35575)_FixWindowsPriForAppReferencefrom test-side targets (after WindowsAppSDK fix)