Skip to content

Make SetDefault() public on Essentials types for third-party platform backends#34229

Open
Redth wants to merge 6 commits intomainfrom
dev/redth/fix-34100
Open

Make SetDefault() public on Essentials types for third-party platform backends#34229
Redth wants to merge 6 commits intomainfrom
dev/redth/fix-34100

Conversation

@Redth
Copy link
Copy Markdown
Member

@Redth Redth commented Feb 25, 2026

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 #34100

Third-party platform backends (e.g. Linux/GTK) cannot wire their Essentials implementations into the static Default properties (FilePicker.Default, Preferences.Default, SecureStorage.Default, etc.) without using private reflection. The internal SetDefault() method is currently the only way to set these, but it is not accessible to external code.

This PR makes SetDefault() public on all 33 Essentials types that follow the Default/SetDefault pattern, enabling custom backends to register their implementations directly:

// In a third-party platform backend (e.g. Linux/GTK):
Preferences.SetDefault(new LinuxPreferences());
FilePicker.SetDefault(new LinuxFilePicker());
SecureStorage.SetDefault(new LinuxSecureStorage());

Changes

  • Changed SetDefault() from internal to public on all 33 Essentials types:
    • 30 cross-platform types (Preferences, FilePicker, SecureStorage, Clipboard, Launcher, Browser, etc.)
    • 3 platform-specific types (ActivityStateManager on Android, WindowStateManager on iOS/Windows)
  • Added XML documentation to all SetDefault() methods
  • Updated PublicAPI.Unshipped.txt for all 7 TFMs (net, net-android, net-ios, net-maccatalyst, net-windows, net-tizen, netstandard)

Affected Types

All types under Microsoft.Maui.Storage, Microsoft.Maui.ApplicationModel, Microsoft.Maui.Devices, Microsoft.Maui.Media, Microsoft.Maui.Accessibility, and Microsoft.Maui.Authentication that expose a static Default property backed by a SetDefault() method.

…form backends

Fixes #34100

Third-party platform backends (e.g. Linux/GTK) cannot wire their
Essentials implementations into the static Default properties without
using private reflection. This change makes the internal SetDefault()
method public on all 33 Essentials types, enabling custom backends to
register implementations directly:

    Preferences.SetDefault(new LinuxPreferences());
    FilePicker.SetDefault(new LinuxFilePicker());

Changes:
- Changed SetDefault() from internal to public on all Essentials types
- Added XML documentation to all SetDefault() methods
- Updated PublicAPI.Unshipped.txt for all TFMs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 25, 2026 02:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR broadens .NET MAUI Essentials extensibility by making the SetDefault(...) registration hook public across all Essentials APIs that expose a static Default implementation, enabling third-party platform backends (e.g., Linux/GTK) to wire their implementations without reflection.

Changes:

  • Changed SetDefault(...) from internal to public across the Essentials Default/SetDefault pattern types.
  • Added XML documentation to the newly-public SetDefault(...) methods (including null-to-reset behavior).
  • Updated PublicAPI.Unshipped.txt across TFMs to reflect the new public surface area.

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Essentials/src/WebAuthenticator/WebAuthenticator.shared.cs Makes SetDefault(IWebAuthenticator?) public and documents it.
src/Essentials/src/WebAuthenticator/AppleSignInAuthenticator.shared.cs Makes SetDefault(IAppleSignInAuthenticator?) public and documents it.
src/Essentials/src/Vibration/Vibration.shared.cs Makes SetDefault(IVibration?) public and documents it.
src/Essentials/src/VersionTracking/VersionTracking.shared.cs Makes SetDefault(IVersionTracking?) public and documents it.
src/Essentials/src/TextToSpeech/TextToSpeech.shared.cs Makes SetDefault(ITextToSpeech?) public and documents it.
src/Essentials/src/Sms/Sms.shared.cs Makes SetDefault(ISms?) public and documents it.
src/Essentials/src/Share/Share.shared.cs Makes SetDefault(IShare?) public and documents it.
src/Essentials/src/SemanticScreenReader/SemanticScreenReader.shared.cs Makes SetDefault(ISemanticScreenReader?) public and documents it.
src/Essentials/src/SecureStorage/SecureStorage.shared.cs Makes SetDefault(ISecureStorage?) public and documents it.
src/Essentials/src/Screenshot/Screenshot.shared.cs Makes SetDefault(IScreenshot?) public and documents it.
src/Essentials/src/Preferences/Preferences.shared.cs Makes SetDefault(IPreferences?) public and documents it.
src/Essentials/src/Platform/ActivityStateManager.android.cs Makes Android ActivityStateManager.SetDefault(...) public and documents it.
src/Essentials/src/Platform/WindowStateManager.ios.cs Makes iOS WindowStateManager.SetDefault(...) public and documents it.
src/Essentials/src/Platform/windowstateManager.windows.cs Makes Windows WindowStateManager.SetDefault(...) public and documents it.
src/Essentials/src/PhoneDialer/PhoneDialer.shared.cs Makes SetDefault(IPhoneDialer?) public and documents it.
src/Essentials/src/OrientationSensor/OrientationSensor.shared.cs Makes SetDefault(IOrientationSensor?) public and documents it.
src/Essentials/src/MediaPicker/MediaPicker.shared.cs Makes SetDefault(IMediaPicker?) public and documents it.
src/Essentials/src/Map/Map.shared.cs Makes SetDefault(IMap?) public and documents it.
src/Essentials/src/Magnetometer/Magnetometer.shared.cs Makes SetDefault(IMagnetometer?) public and documents it.
src/Essentials/src/Launcher/Launcher.shared.cs Makes SetDefault(ILauncher?) public and documents it.
src/Essentials/src/HapticFeedback/HapticFeedback.shared.cs Makes SetDefault(IHapticFeedback?) public and documents it.
src/Essentials/src/Gyroscope/Gyroscope.shared.cs Makes SetDefault(IGyroscope?) public and documents it.
src/Essentials/src/Geolocation/Geolocation.shared.cs Makes SetDefault(IGeolocation?) public and documents it.
src/Essentials/src/Flashlight/Flashlight.shared.cs Makes SetDefault(IFlashlight?) public and documents it.
src/Essentials/src/FilePicker/FilePicker.shared.cs Makes SetDefault(IFilePicker?) public and documents it.
src/Essentials/src/Email/Email.shared.cs Makes SetDefault(IEmail?) public and documents it.
src/Essentials/src/Contacts/Contacts.shared.cs Makes SetDefault(IContacts?) public and documents it.
src/Essentials/src/Compass/Compass.shared.cs Makes SetDefault(ICompass?) public and documents it.
src/Essentials/src/Clipboard/Clipboard.shared.cs Makes SetDefault(IClipboard?) public and documents it.
src/Essentials/src/Browser/Browser.shared.cs Makes SetDefault(IBrowser?) public and documents it.
src/Essentials/src/Battery/Battery.shared.cs Makes SetDefault(IBattery?) public and documents it.
src/Essentials/src/Barometer/Barometer.shared.cs Makes SetDefault(IBarometer?) public and documents it.
src/Essentials/src/Accelerometer/Accelerometer.shared.cs Makes SetDefault(IAccelerometer?) public and documents it.
src/Essentials/src/PublicAPI/netstandard/PublicAPI.Unshipped.txt Adds public API entries for the newly-public SetDefault(...) methods (netstandard).
src/Essentials/src/PublicAPI/net/PublicAPI.Unshipped.txt Adds public API entries for the newly-public SetDefault(...) methods (net).
src/Essentials/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt Adds public API entries including Windows-specific WindowStateManager.SetDefault(...).
src/Essentials/src/PublicAPI/net-tizen/PublicAPI.Unshipped.txt Adds public API entries for the newly-public SetDefault(...) methods (Tizen).
src/Essentials/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt Adds public API entries including WindowStateManager.SetDefault(...) (MacCatalyst).
src/Essentials/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt Adds public API entries including WindowStateManager.SetDefault(...) (iOS).
src/Essentials/src/PublicAPI/net-android/PublicAPI.Unshipped.txt Adds public API entries including Android-specific ActivityStateManager.SetDefault(...).

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 23, 2026

🤖 AI Summary

📊 Expand Full Reviewe9162bc · Make SetDefault() public on all Essentials types for third-party platform backends
🔍 Pre-Flight — Context & Validation

Issue: #34100 - Essentials static Default properties need a public registration mechanism - Every Essentials API (Preferences, FilePicker, SecureStorage, etc.) is inaccessible to custom backends without reflection hacks
PR: #34229 - Make SetDefault() public on Essentials types for third-party platform backends
Platforms Affected: Cross-platform Essentials APIs for third-party backends; platform-specific hooks added for Android, iOS/MacCatalyst, and Windows
Files Changed: 33 implementation, 0 test, 7 PublicAPI

Key Findings

  • The linked issue requests a public registration mechanism so third-party backends can replace Essentials Default implementations without private reflection.
  • The PR description explicitly chooses the minimal Option A from the issue: make SetDefault() public on every Essentials type that follows the Default/SetDefault pattern.
  • There are no PR issue comments, no inline review comments, and no prior agent-review summary to import.
  • The file set contains implementation/API-surface changes only: 33 source files and 7 PublicAPI.Unshipped.txt files, with no new or modified tests.
  • Android is selected for gate/verification because the PR includes an Android-specific API surface change (ActivityStateManager.android.cs) and the requested test platform is android.

Edge Cases Noted

  • The issue mentions an alternative DI-based registration path, but this PR does not implement that broader design.
  • The issue scope is broader than Android because many changed SetDefault() methods are cross-platform, while three are platform-specific.
  • Because the PR adds public API across 7 TFMs, PublicAPI correctness is part of the change surface even without dedicated runtime tests.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #34229 Make SetDefault(...) public on all Essentials types using the static Default/SetDefault pattern, add XML docs, and update PublicAPI files across TFMs ⏳ PENDING (Gate) 40 files Original PR

🚦 Gate — Test Verification

Gate Result: ⚠️ SKIPPED

Platform: android
Mode: Full Verification

  • Tests FAIL without fix: ❌
  • Tests PASS with fix: ❌

Reason: PR #34229 does not add or modify any test files. The changed file set is 33 implementation files plus 7 PublicAPI.Unshipped.txt files, so there is no PR-supplied test to run through fail-without-fix / pass-with-fix verification.

Recommendation from Gate: Add targeted coverage (likely Essentials unit tests) to prove an external caller can replace Default via the newly-public SetDefault(...) methods.


🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Add public Geocoding.SetDefault(...), keep internal SetCurrent(...), and add focused Geocoding unit tests ✅ PASS Geocoding.shared.cs, Geocoding_Tests.cs, 7 PublicAPI files Additive, backward-compatible fix for the omitted API
2 try-fix (claude-sonnet-4.6) Rename Geocoding.SetCurrent(...) directly to public SetDefault(...) and add focused Geocoding unit tests ✅ PASS Geocoding.shared.cs, Geocoding_Tests.cs, 7 PublicAPI files Cleanest naming consistency; no internal callers of SetCurrent remain
3 try-fix (gpt-5.3-codex) Add public SetDefault(...) and expose public SetCurrent(...) as a forwarding compatibility alias ✅ PASS Geocoding.shared.cs, Geocoding_Tests.cs, 7 PublicAPI files Works, but broadens public API more than the issue requires
4 try-fix (gemini-3-pro-preview) Make Geocoding.Default publicly settable and add focused unit tests ✅ PASS Geocoding.shared.cs, Geocoding_Tests.cs, 7 PublicAPI files Functional, but changes the public shape more than other Essentials APIs
5 try-fix (gpt-5.3-codex round 2) Add public ConfigureDefault(Func<IGeocoding?>?) resolver hook with lazy caching, plus focused tests ✅ PASS Geocoding.shared.cs, Geocoding_Tests.cs, 7 PublicAPI files Materially different, but introduces a one-off API pattern unlike the rest of Essentials
6 try-fix (claude-opus-4.6 round 2) Add public SetServiceProvider(IServiceProvider?) so Default resolves IGeocoding from DI first ✅ PASS Geocoding.shared.cs, Geocoding_Tests.cs, 7 PublicAPI files Architecturally distinct, but much broader than the PR and not aligned with other Essentials APIs
7 try-fix (gemini-3-pro-preview round 2) Add ConfigureDefault(...) in Essentials plus a MauiAppBuilder.ConfigureGeocoding(...) integration path in Core ✅ PASS Geocoding.shared.cs, Geocoding_Tests.cs, Core hosting/API files, PublicAPI files Works, but expands a one-file PR gap into a multi-assembly design change
PR PR #34229 Make existing SetDefault(...) methods public on 33 Essentials types and update docs/PublicAPI ⚠️ SKIPPED (Gate) 40 files No PR-supplied tests to verify fail-without-fix / pass-with-fix; still misses Geocoding

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 1 Yes Add a public SetDefault(...) wrapper specifically for Geocoding and validate with targeted unit tests.
claude-sonnet-4.6 1 Yes Replace SetCurrent(...) with public SetDefault(...) for Geocoding and validate with targeted unit tests.
gpt-5.3-codex 1 Yes Expose both public names, with SetCurrent(...) forwarding to SetDefault(...), and validate with targeted unit tests.
gemini-3-pro-preview 1 Yes Make Geocoding.Default settable instead of adding another method.
claude-opus-4.6 2 Yes Resolve IGeocoding from DI/services via public SetServiceProvider(IServiceProvider?).
claude-sonnet-4.6 2 No NO NEW IDEAS
gpt-5.3-codex 2 Yes Add a public resolver/factory hook ConfigureDefault(Func<IGeocoding?>?) with lazy caching.
gemini-3-pro-preview 2 Yes Add a MauiAppBuilder.ConfigureGeocoding(IGeocoding) extension method instead of changing Geocoding directly.
claude-opus-4.6 3 No NO NEW IDEAS
claude-sonnet-4.6 3 Yes Generic cross-Essentials registry idea — broader than this PR and not attempted because round limit reached.
gpt-5.3-codex 3 Yes Implicit DI via IPlatformApplication.Current.Services — broader than this PR and not attempted because round limit reached.
gemini-3-pro-preview 3 Yes Event-based pull registration — broader than this PR and not attempted because round limit reached.

Exhausted: Yes — final allowed cross-pollination round reached
Selected Fix: Candidate #2 — smallest fix that fully addresses the missed API while matching the exact pattern already used by the other Essentials types in this PR


📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Linked issue #34100, file classification, and PR discussion gathered.
Gate ⚠️ SKIPPED PR adds no tests, so fail-without-fix / pass-with-fix verification could not run.
Try-Fix ✅ COMPLETE 7 attempts, 7 passing candidates; best candidate is not the PR as written.
Report ✅ COMPLETE

Summary

PR #34229 correctly publicizes SetDefault(...) on 33 Essentials types, but it leaves one relevant API behind: Geocoding. Geocoding still exposes public static IGeocoding Default while only providing internal static void SetCurrent(IGeocoding? implementation), so third-party backends still cannot register a custom Geocoding implementation without reflection.

Because of that omission, the PR does not fully satisfy issue #34100. It also ships without targeted tests proving the new public registration hooks work.

Root Cause

The PR appears to have enumerated only the existing Default/SetDefault pattern and missed the one inconsistent outlier: src/Essentials/src/Geocoding/Geocoding.shared.cs, which uses Default plus SetCurrent(...) instead. That naming inconsistency caused Geocoding to be excluded from the mechanical update, leaving the issue only partially solved.

Fix Quality

The existing PR changes are mechanically consistent for the 33 touched APIs, and the PublicAPI updates for those APIs look correct. The problem is completeness: the same user-facing extensibility hole remains for Geocoding.

The strongest alternative from Try-Fix was candidate #2: rename Geocoding.SetCurrent(...) directly to public SetDefault(...), add XML documentation, update the 7 PublicAPI.Unshipped.txt files, and add focused Geocoding_Tests coverage. That option passed targeted unit tests, matches the exact pattern already used by the other Essentials types in this PR, and is smaller/cleaner than the broader DI or builder-based variants.


@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 26, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34229

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34229"

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

🧪 PR Test Evaluation

Overall Verdict: ⚠️ Tests need improvement

The single unit test file is well-structured and uses the right test type, but it only covers 3 of the 34 changed APIs (~9%), leaving 31 APIs with identical changes untested.

👍 / 👎 — Was this evaluation helpful? React to let us know!

📊 Expand Full Evaluation

PR Test Evaluation Report

PR: #34229 — [Geocoding] Add SetDefault method and corresponding tests for custom implementation
Test files evaluated: 1 (SetDefault_Tests.cs)
Fix files: 34 (all Essentials APIs — identical pattern: internal → public + XML docs)


Overall Verdict

⚠️ Tests need improvement

The unit test file has good structure and appropriate test type, but covers only 3 of 34 APIs changed by this PR. A typo or copy-paste error in any of the 31 untested APIs would go undetected.


1. Fix Coverage — ⚠️

The fix makes SetDefault public across 34 Essentials APIs. Tests verify the behavior for 3 APIs (Geocoding, Preferences, FilePicker) but leave 31 APIs completely untested:

Accelerometer, Barometer, Battery, Browser, Clipboard, Compass, Contacts, Email, Flashlight, Geolocation, Gyroscope, HapticFeedback, Launcher, Magnetometer, Map, MediaPicker, OrientationSensor, PhoneDialer, ActivityStateManager, WindowStateManager, Screenshot, SecureStorage, SemanticScreenReader, Share, Sms, TextToSpeech, VersionTracking, Vibration, AppleSignInAuthenticator, WebAuthenticator, and more.

For the 3 covered APIs, the tests correctly exercise: set custom implementation → verify used, reset to null → verify platform default returns.

2. Edge Cases & Gaps — ⚠️

Covered:

  • Set a custom implementation and confirm Default returns it (Assert.Same)
  • Reset to null and confirm the platform default is returned (Assert.NotSame)
  • Verify the custom implementation is actually invoked (via GetLocationsCalled flag on Geocoding)

Missing:

  • 31 APIs untested — The same SetDefault pattern applied across Accelerometer, Battery, Clipboard, Geolocation, etc. has no tests
  • Thread safety — Concurrent calls to SetDefault on the same API aren't tested; defaultImplementation is a non-volatile static field
  • Call multiple times — Setting to custom A, then custom B, then null is not tested
  • GetPlacemarksAsync path — Only GetLocationsAsync is exercised in the Geocoding mock; the other interface method has no coverage

3. Test Type Appropriateness — ✅

Current: Unit Tests (xUnit)
Recommendation: Same — this is the ideal test type. The SetDefault pattern is pure logic with no platform/UI requirements. Unit tests are the lightest and most appropriate choice here.

4. Convention Compliance — ✅

No issues found by automated checks:

  • #nullable enable present
  • xUnit [Fact] attributes used correctly
  • Proper try/finally cleanup to reset state between tests
  • Correct namespace (Tests)

5. Flakiness Risk — ✅ Low

All tests are synchronous, stateless (with proper cleanup), and have no timing or external dependencies. The try/finally reset pattern correctly handles test isolation.

6. Duplicate Coverage — ✅ No duplicates

No pre-existing SetDefault tests found in the unit test suite. These are genuinely new test scenarios for the newly public API.

7. Platform Scope — ⚠️

The PR includes 3 platform-specific files (ActivityStateManager.android.cs, WindowStateManager.ios.cs, windowstateManager.windows.cs) with the same SetDefault visibility change. Unit tests run cross-platform and cover the common logic, but these platform-specific variants have no dedicated test.

Since the change is purely a visibility modifier + docs (no platform logic changed), this is a low-risk gap, but worth noting.

8. Assertion Quality — ✅

Assertions are specific and meaningful:

  • Assert.Same — verifies object identity (not just equality), correct for "is this the same instance?"
  • Assert.NotSame — confirms reset works
  • Assert.Empty / Assert.True(custom.GetLocationsCalled) — verifies the mock is actually invoked

9. Fix-Test Alignment — ⚠️

The 3 tested APIs (Geocoding, Preferences, FilePicker) do align with their respective fix files. However, since the PR changes a consistent pattern across 34 APIs, limiting tests to only 3 means 91% of the changed surface area has no test-to-fix alignment.


Recommendations

  1. Add [Theory]-based tests for all changed APIs — Since the behavior is identical across all 34 APIs, a parameterized approach with factory delegates or a [MemberData] source would efficiently cover all APIs without 34× duplicated code. Alternatively, add tests for the most commonly used untested APIs (Accelerometer, Battery, Clipboard, Geolocation, Vibration, etc.).

  2. Cover the SetDefault → use → reset cycle for more APIs — At minimum, the "custom is actually invoked" test (not just "custom is stored") would strengthen confidence. Currently only Geocoding has this deeper check.

  3. Consider thread-safety testdefaultImplementation is a non-volatile static field; concurrent SetDefault calls are theoretically racy. A simple note in code comments or a test with Parallel.Invoke would document the intended behavior.

Warning

⚠️ Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • dc.services.visualstudio.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "dc.services.visualstudio.com"

See Network Configuration for more information.

Note

🔒 Integrity filtering filtered 2 items

Integrity filtering activated and filtered the following items during workflow execution.
This happens when a tool call accesses a resource that does not meet the required integrity or secrecy level of the workflow.

🧪 Test evaluation by Evaluate PR Tests

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

🧪 PR Test Evaluation

Overall Verdict: ⚠️ Tests need improvement

The PR exposes SetDefault() as public on 34 Essentials APIs but tests only 3 of them, and two of those 3 are missing a delegation assertion (verifying the custom implementation is actually called).

👍 / 👎 — Was this evaluation helpful? React to let us know!

📊 Expand Full Evaluation

PR Test Evaluation Report

PR: #34229 — Make SetDefault() public on Essentials types for third-party backends
Test files evaluated: 1 (SetDefault_Tests.cs)
Fix files: 34 (all *.shared.cs Essentials APIs + 3 platform files)


Overall Verdict

⚠️ Tests need improvement

The fix makes SetDefault() public on 34 Essentials APIs; the test file covers 3 (Geocoding, Preferences, FilePicker) and is missing a delegation check for 2 of those 3. The remaining 31 APIs receive no test coverage at all.


1. Fix Coverage — ⚠️

The core mechanism (defaultImplementation = implementation / Default => defaultImplementation ??= new XxxImplementation()) is identical across all 34 APIs and is correctly exercised by the existing tests. However, of 34 APIs that had their visibility changed:

  • Covered: Geocoding (set, reset, delegation), Preferences (set, reset), FilePicker (set, reset)
  • Uncovered: 31 APIs — Accelerometer, Barometer, Battery, Browser, Clipboard, Compass, Contacts, Email, Flashlight, Geolocation, Gyroscope, HapticFeedback, Launcher, Magnetometer, Map, MediaPicker, OrientationSensor, PhoneDialer, Screenshot, SecureStorage, SemanticScreenReader, Share, Sms, TextToSpeech, VersionTracking, Vibration, WebAuthenticator, AppleSignInAuthenticator, ActivityStateManager, WindowStateManager

The pattern is structurally identical for all APIs, so there is a reasonable argument for representative sampling. But zero coverage on 91% of the changed APIs is still a meaningful gap — especially since Geocoding.SetDefault was a rename (from SetCurrent) while all other 33 were purely visibility changes, making the rename the unique risk the tests don't focus on.

2. Edge Cases & Gaps — ⚠️

Covered:

  • Set a custom implementation and verify Default returns it (reference equality)
  • Reset to null and verify Default no longer returns the mock
  • Custom implementation is actually delegated to (Geocoding only: GetLocationsAsync)

Missing:

  • Delegation verification for Preferences and FilePicker — tests confirm the mock is set as Default but do not call any method through the static API to prove delegation works (like the Geocoding GetLocationsCalled assertion)
  • Thread-safetySetDefault is a non-atomic write; no test exercises concurrent calls, though this is an edge case consistent with existing MAUI patterns
  • Representative coverage for renamed method — Geocoding was renamed from SetCurrent to SetDefault; that rename is tested, but notably the 33 pure visibility-change APIs are not tested at all

3. Test Type Appropriateness — ✅

Current: Unit Tests (xUnit [Fact])
Recommendation: Same — unit tests are the ideal and lightest type for this change. SetDefault is a pure in-memory assignment with no UI, platform native, or Appium interaction required.

4. Convention Compliance — ✅

All conventions are met:

  • File in src/Essentials/test/UnitTests/
  • Uses xUnit [Fact] attributes
  • Cleanup via finally { Geocoding.SetDefault(null); } (correct reset pattern)
  • No inline platform #if directives

5. Flakiness Risk — ✅ Low

No Task.Delay, Thread.Sleep, or timing dependencies. The one async test (Geocoding_SetDefault_CustomImplementation_IsUsed) is safe because the mock returns immediately. No external resources or global state leak risk (cleanup is in finally blocks).

6. Duplicate Coverage — ✅ No duplicates

Existing Geocoding, Preferences, and FilePicker unit tests target different behaviors (method logic, data handling). The new SetDefault_Tests.cs file is the only place testing the DI injection mechanism.

7. Platform Scope — ✅

The fix touches all TFMs (net-android, net-ios, net-maccatalyst, net-tizen, net-windows, net, netstandard) and 3 platform-specific files. Unit tests don't require a platform context — SetDefault() is a simple field assignment that runs anywhere. PublicAPI.Unshipped.txt is updated for all 7 TFMs.

8. Assertion Quality — ⚠️

Test Assertion Quality
Geocoding_SetDefault_SetsCustomImplementation Assert.Same(custom, Geocoding.Default) ✅ Reference equality — precise
Geocoding_SetDefault_Null_ResetsToDefault Assert.NotSame(custom, Geocoding.Default) ✅ Correct — platform default is a new instance
Geocoding_SetDefault_CustomImplementation_IsUsed Assert.Empty(results) + Assert.True(custom.GetLocationsCalled) ✅ Verifies delegation
Preferences_SetDefault_SetsCustomImplementation Assert.Same(custom, Preferences.Default) ✅ Reference equality — precise
Preferences_SetDefault_Null_ResetsToDefault Assert.NotSame(custom, Preferences.Default) ✅ Correct
FilePicker_SetDefault_SetsCustomImplementation Assert.Same(custom, FilePicker.Default) ✅ Reference equality — precise
FilePicker_SetDefault_Null_ResetsToDefault Assert.NotSame(custom, FilePicker.Default) ✅ Correct

Missing delegation assertions (Preferences, FilePicker):

  • Preferences_SetDefault_SetsCustomImplementation doesn't call Preferences.Get(...) to confirm the mock is actually used
  • FilePicker_SetDefault_SetsCustomImplementation doesn't call FilePicker.PickAsync() to confirm the mock is used

9. Fix-Test Alignment — ✅

The tests directly exercise SetDefault() — exactly the method that was changed from internal to public. The mock implementations implement the correct interfaces (IGeocoding, IPreferences, IFilePicker). The Geocoding rename (SetCurrentSetDefault) is tested.


Recommendations

  1. Add delegation tests for Preferences and FilePicker — Following the Geocoding pattern, call a method through the static API after setting the mock to verify delegation (e.g., call Preferences.Get(...) and assert a flag on MockPreferences). This closes the gap between "mock is set as Default" and "mock is actually called."

  2. Add tests for 2–3 additional representative APIs — Consider testing one sensor API (e.g., Accelerometer.SetDefault) and one platform-specific API (e.g., Share.SetDefault). Given the identical pattern, full coverage across all 34 is unnecessary, but more than 3 out of 34 would give better confidence.

  3. Consider a test class that uses IDisposable for cleanup — The current finally blocks work correctly, but implementing IDisposable.Dispose() (as done in DeviceDisplay_Tests.cs) would provide automatic cleanup even if a future test throws unexpectedly outside a try.

Warning

⚠️ Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • dc.services.visualstudio.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "dc.services.visualstudio.com"

See Network Configuration for more information.

Note

🔒 Integrity filtering filtered 1 item

Integrity filtering activated and filtered the following item during workflow execution.
This happens when a tool call accesses a resource that does not meet the required integrity or secrecy level of the workflow.

🧪 Test evaluation by Evaluate PR Tests

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 3 comments.

Comment on lines +12 to +18
public class SetDefault_Tests
{
// --- Geocoding SetDefault tests ---

[Fact]
public void Geocoding_SetDefault_SetsCustomImplementation()
{
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests mutate global static *.Default implementations. Since xUnit runs test classes in parallel by default and other Essentials unit tests expect the reference implementations to throw, this can make the test suite flaky (other tests may observe the mocked defaults while this test is running). Please serialize this test class (e.g., put it in a non-parallelized xUnit collection / disable parallelization for the collection) so it can’t run concurrently with other tests.

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +5
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

System.Threading is unused here. With TreatWarningsAsErrors=true in this repo, the unnecessary using directive can fail the build; please remove it (and any other unused usings).

Copilot uses AI. Check for mistakes.
Comment on lines +143 to +150
class MockFilePicker : IFilePicker
{
public Task<FileResult?> PickAsync(PickOptions? options = null)
=> Task.FromResult<FileResult?>(null);

public Task<IEnumerable<FileResult?>> PickMultipleAsync(PickOptions? options = null)
=> Task.FromResult<IEnumerable<FileResult?>>(Array.Empty<FileResult>());
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MockFilePicker.PickMultipleAsync has a nullability-mismatched signature compared to IFilePicker.PickMultipleAsync (interface returns Task<IEnumerable<FileResult>?>). With warnings-as-errors this will fail compilation (nullability/implementation mismatch). Update the mock method signature and its Task.FromResult to match the interface’s annotated return type.

Copilot uses AI. Check for mistakes.
Redth and others added 2 commits April 3, 2026 18:46
- Disable parallel execution for SetDefault_Tests via a dedicated xUnit collection
  to avoid shared static Default implementation races across tests.
- Remove unused System.Threading using.
- Fix MockFilePicker.PickMultipleAsync signature nullability to match IFilePicker.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Redth
Copy link
Copy Markdown
Member Author

Redth commented Apr 3, 2026

Addressed the three new Copilot review comments on this PR (from 2026-04-01) and verified with build/tests.

✅ Fixed

  • src/Essentials/test/UnitTests/SetDefault_Tests.cs
    • Added xUnit collection serialization to avoid shared static *.Default races across parallel test execution:
      • [CollectionDefinition("SetDefault", DisableParallelization = true)]
      • [Collection("SetDefault")] on SetDefault_Tests
    • Removed unused using System.Threading;
    • Fixed nullability signature mismatch for MockFilePicker.PickMultipleAsync to match IFilePicker:
      • Task<IEnumerable<FileResult>?> PickMultipleAsync(...)

✅ Validation run

  • dotnet build src/Essentials/test/UnitTests/Essentials.UnitTests.csproj --no-restore -v q
  • dotnet test src/Essentials/test/UnitTests/Essentials.UnitTests.csproj --no-build --filter "FullyQualifiedName~SetDefault_Tests"
    • Passed: 7, Failed: 0

✅ Push

  • Commit: ae66e4a749
  • Branch: dev/redth/fix-34100

Re: test coverage note (3/34 APIs): this PR’s change is a repeated mechanical visibility update (internalpublic) on the same pattern. The existing tests validate the core set/reset/invocation behavior on representative APIs, and we now also addressed test reliability + nullability correctness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

3 participants