Skip to content

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

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

Make SetDefault() public on Essentials types for third-party platform backends#34229
Redth wants to merge 9 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

This comment has been minimized.

@github-actions

This comment has been minimized.

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 today’s new Copilot suggestion by adding a guard-rail reflection test.

✅ Added

  • src/Essentials/test/UnitTests/SetDefault_Tests.cs
    • New test: AllEssentialsTypes_ExposePublicSetDefault()
    • It reflects over the Essentials assembly and finds all static types under Microsoft.Maui.* namespaces with a public static interface-typed Default property.
    • For each such type, it asserts a matching public static void SetDefault(<interface>) method exists.
    • Fails with a concrete missing-method list if any future API misses this pattern.

✅ 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: 8, Failed: 0

✅ Push

  • Commit: 748eaa0265
  • Branch: dev/redth/fix-34100

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 1 comment.

Comment on lines +19 to +23
// --- Geocoding SetDefault tests ---

[Fact]
public void Geocoding_SetDefault_SetsCustomImplementation()
{
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

This file adds coverage for SetDefault on a few APIs, but the PR changes SetDefault visibility across many Essentials types. Consider adding a reflection-based test that asserts every Default-based Essentials API exposes the expected public static SetDefault(<interface>?) method so future additions don’t accidentally miss the PublicAPI/visibility change.

Copilot uses AI. Check for mistakes.
- Add AllEssentialsTypes_ExposePublicSetDefault test to ensure every
  static Essentials type with a public interface-typed Default property
  also exposes a matching public static void SetDefault(<interface>) method.
- Uses reflection over the Essentials assembly and fails with a specific
  missing method list to prevent future accidental API pattern regressions.

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

This comment has been minimized.

…rloads

 34 types coverage)
- Add double-set test verifying second SetDefault call overrides first
- Fix MockPreferences: remove superfluous single-param overloads not on IPreferences interface
- Add mocks: MockClipboard, MockSecureStorage, MockBattery with delegation verification

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

This comment has been minimized.

… type categories

- Add null-reset tests for Clipboard, SecureStorage, Battery
- Add IsUsed behavioral tests for Preferences and FilePicker
- Add full test coverage for Share, Launcher, Accelerometer (sensor/media/app types)
- All 9 tested types now have consistent 3-test pattern: set, null-reset, is-used

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

This comment has been minimized.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 9, 2026

🧪 PR Test Evaluation

Overall Verdict: ⚠️ Tests need improvement

The unit tests are well-structured and use the right test type, but behavioral coverage exists for only 9 of 31 changed API types. The reflection guardrail catches API surface issues, but doesn't verify the plumbing actually works for the remaining 22 types.

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

📊 Expand Full Evaluation

PR Test Evaluation Report

PR: #34229 — Essentials SetDefault API visibility fix (internal → public)
Test files evaluated: 1 (SetDefault_Tests.cs)
Fix files: 34 (31 Essentials source files changing internal static void SetDefaultpublic static void SetDefault, plus PublicAPI.Unshipped.txt updates)


Overall Verdict

⚠️ Tests need improvement

The test file is well-designed with a smart reflection guardrail and the right test type (unit tests). However, behavioral tests cover only 9 of the 31 types that gained a public SetDefault method, leaving 22 types verified only at the API-surface level.


1. Fix Coverage — ⚠️

The fix changes SetDefault from internal to public on 31 Essentials types. Tests cover this in two complementary ways:

  • Reflection guardrail (AllEssentialsTypes_ExposePublicSetDefault): Scans the Essentials assembly and asserts every type with a Default property also exposes a public SetDefault. This directly detects a regression if any type's visibility were reverted.
  • ⚠️ Behavioral tests: Only 9 of 31 types are tested with the set/null-reset/is-used pattern (Geocoding, Preferences, FilePicker, Clipboard, SecureStorage, Battery, Share, Launcher, Accelerometer). The remaining 22 types (Barometer, Browser, Compass, Contacts, Email, Flashlight, Geolocation, Gyroscope, HapticFeedback, Magnetometer, Map, MediaPicker, OrientationSensor, PhoneDialer, Screenshot, SemanticScreenReader, Sms, TextToSpeech, VersionTracking, Vibration, WebAuthenticator, AppleSignInAuthenticator) have no behavioral test verifying their plumbing works end-to-end.

The reflection test would catch a missing public API, but not a broken implementation (e.g., if defaultImplementation field was typed incorrectly or the null-reset path silently failed for a specific type).


2. Edge Cases & Gaps — ⚠️

Covered:

  • Set custom implementation and verify Default returns it (9 types)
  • Null-reset and verify Default no longer returns the mock (most tested types)
  • Mock is actually invoked after SetDefault — behavioral "is-used" tests (most tested types)
  • Double-set override (Geocoding only)
  • API surface exhaustiveness via reflection

Missing:

  • 22 types have no behavioral test — while the pattern is identical, types like WebAuthenticator, MediaPicker, TextToSpeech, VersionTracking, and sensor types (Barometer, Compass, Gyroscope, Magnetometer, OrientationSensor) are entirely unverified at the behavioral level. If any of these had a subtle wiring bug (wrong field, wrong null check), the tests would not catch it.
  • Double-set test only for Geocoding — only one type has a test verifying that calling SetDefault twice replaces the first mock with the second. This is a common regression pattern.
  • No test for AppleSignInAuthenticator — this type's SetDefault was also made public and it's a distinct pattern (lives in WebAuthenticator/ namespace with Apple-specific logic).

3. Test Type Appropriateness — ✅

Current: Unit Tests (xUnit [Fact])
Recommendation: Same — unit tests are exactly right here. The fix is a pure API-visibility and plumbing change; no platform context, UI, or native rendering is required to verify it. Using UI or device tests would be unnecessarily heavy.


4. Convention Compliance — ✅

  • [Fact] attributes on all 29 test methods (xUnit convention)
  • [Collection("SetDefault")] with DisableParallelization = true — correct for tests modifying static state
  • try/finally blocks to reset state after each test — good practice
  • ✅ No convention issues detected by automated script

5. Flakiness Risk — ✅ Low

  • [Collection("SetDefault")] with DisableParallelization = true prevents race conditions on shared static state ✅
  • try/finally blocks guarantee SetDefault(null) is called even if assertions fail ✅
  • No Task.Delay or Thread.Sleep
  • No UI or Appium dependencies ✅

6. Duplicate Coverage — ✅ No duplicates

No similar SetDefault behavioral tests exist in the codebase. Existing tests in Geocoding_Tests.cs, Browser_Tests.cs, and OrientationSensor_Tests.cs test the platform behavior of those APIs, not the SetDefault plumbing — no overlap.


7. Platform Scope — ⚠️

The fix touches all platforms (Android, iOS, MacCatalyst, Windows, cross-platform). Unit tests run in a netstandard/net TFM context without platform-specific code paths. Since the change is purely API visibility (not platform behavior), unit tests are appropriate and platform-specific device tests are not needed. However, if CI runs these unit tests only on one platform, it's worth confirming they run on at least the net and netstandard TFMs.


8. Assertion Quality — ✅

  • Assert.Same(custom, Type.Default) — identity check, not equality; correctly verifies the exact mock instance ✅
  • Assert.NotSame(custom, Type.Default) — verifies null-reset restores a different (platform default) instance ✅
  • Assert.True(custom.SomeCalled) — verifies the mock was actually invoked via the static API ✅
  • No magic numbers or over-broad assertions ✅

9. Fix-Test Alignment — ✅

The test file directly targets the SetDefault mechanism in Essentials types, which is exactly what the fix changes. The reflection test is particularly well-aligned — it enforces the invariant that every type with Default must also have a public SetDefault, making it a regression guard for the exact change being made.


Recommendations

  1. Add behavioral tests for the remaining 22 types — at minimum, the most commonly used ones: Browser, Sms, Email, Contacts, TextToSpeech, Vibration, HapticFeedback, Flashlight, Screenshot, Geolocation. Consider a [Theory] or a helper method to reduce boilerplate, since all types follow the same 3-test pattern.

  2. Add a double-set test for at least one additional type — e.g., Preferences or Battery, to verify the second assignment fully replaces the first independent of type-specific implementation details.

  3. Add a test for AppleSignInAuthenticator.SetDefault — this is a less common type with Apple-specific concerns; a basic set/null-reset test would confirm it follows the same pattern.

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

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