Skip to content

Feat(test)/mwa keep connection alive tests#283

Merged
Kuldotha merged 4 commits into
magicblock-labs:mainfrom
JoshhSandhu:feat(test)/mwa-keepConnectionAlive-tests
May 11, 2026
Merged

Feat(test)/mwa keep connection alive tests#283
Kuldotha merged 4 commits into
magicblock-labs:mainfrom
JoshhSandhu:feat(test)/mwa-keepConnectionAlive-tests

Conversation

@JoshhSandhu
Copy link
Copy Markdown
Contributor

@JoshhSandhu JoshhSandhu commented Apr 23, 2026

Status Type ⚠️ Core Change Issue
Ready Tooling No Follow-up to #276

NOTE: This PR adds EditMode test coverage for the MWA lifecycle work merged in #269 (Deauthorize, GetCapabilities, keepConnectionAlive auth-token restore, and the namespaced PlayerPrefs migration).

Built on top of the test infrastructure introduced in #276. No runtime code is modified.

Related PRs: #269, #276

Problem

PR #269 added three new lifecycle surfaces to the Mobile Wallet Adapter stack:

  • A new Deauthorize(authToken) RPC on IAdapterOperations / MobileWalletAdapterClient.
  • A new GetCapabilities() RPC returning a new CapabilitiesResult response model.
  • A keepConnectionAlive reauthorize path plus a PlayerPrefs migration from the legacy pk / authToken keys to namespaced solana_sdk.mwa.public_key / solana_sdk.mwa.auth_token.

None of that has automated coverage. A rename, a silent JSON property drift, or a regression in the key-migration logic would only surface during manual on-device testing, which is exactly the kind of failure the test infrastructure added in #276 was meant to prevent.

Solution

This PR adds 44 new EditMode unit tests across 4 test classes, using the MockMessageSender and NUnit conventions already established by #276.

Coverage added:

  • CapabilitiesResultTests (11 tests): pins the snake_case JSON wire format (max_transactions_per_request, max_messages_per_request, supported_transaction_versions, supports_clone_authorization), verifies every nullable field stays null when absent (including SupportsCloneAuthorization, which is bool? and must not silently coerce to false), confirms unknown JSON fields are ignored for forward-compat with the MWA spec, and verifies Response<CapabilitiesResult> composes correctly with the existing WasSuccessful / Failed envelope flags.
  • MobileWalletAdapterClientLifecycleTests (16 tests): asserts the exact JSON-RPC request shape sent to the wire for both new RPCs: method name (deauthorize, get_capabilities), JSON-RPC version, monotonic and positive message IDs, parameter whitelist (Deauthorize must not leak identity/cluster/payloads/addresses; GetCapabilities must send a non-null empty Params object), cross-method ID sequencing, and the public return type Task<CapabilitiesResult>.
  • IAdapterOperationsContractTests (11 tests): reflection-based contract tests pinning every method signature on the interface. Guarantees Deauthorize returns the non-generic Task (fire-and-forget), GetCapabilities returns Task<CapabilitiesResult>, every method and the interface itself carry [Preserve] (required so IL2CPP / Unity managed code stripping does not remove them in AOT builds), and the method count stays locked at 6.
  • SolanaMobileWalletAdapterPrefsTests (8 tests, [Category("Lifecycle")]): pins the private const key names (solana_sdk.mwa.public_key, solana_sdk.mwa.auth_token) so a rename breaks CI instead of users' existing installs, and exercises the private static MigrateLegacyPrefKeys via reflection. Covers: no-op when no legacy keys, migrates each legacy key independently, deletes legacy keys after migration, does not overwrite a newer namespaced value, idempotent on a second call, handles half-migrated installs. [SetUp] and [TearDown] scrub PlayerPrefs so the registry-backed store stays clean between runs.

Note: SolanaMobileWalletAdapter itself cannot be instantiated in EditMode because its constructor throws on non-Android platforms, this is the same blocker called out in the #276 PR body. Migration logic is reached through reflection to work around that without modifying runtime code.

Before & After Screenshots

BEFORE:
34 passing EditMode tests (from #276). No coverage for PR #269's lifecycle surface.
test-framework

AFTER:
78 passing EditMode tests in the Unity Test Runner.
image

Other changes (e.g. bug fixes, small refactors)

  • No runtime code is modified.
  • No existing test is modified.
  • No new assembly references added, all new tests compile against com.solana.unity_sdk, Newtonsoft.Json.dll, nunit.framework.dll, and the Unity test runners already referenced by EditMode.asmdef.
  • New folder layout under Tests/EditMode/: Contracts/, Lifecycle/ (plus files under the existing JsonRpc/ and MwaClient/).

Deploy Notes

Tooling-only. No runtime behavior change.

New scripts:

  • Tests/EditMode/JsonRpc/CapabilitiesResultTests.cs
  • Tests/EditMode/MwaClient/MobileWalletAdapterClientLifecycleTests.cs
  • Tests/EditMode/Contracts/IAdapterOperationsContractTests.cs
  • Tests/EditMode/Lifecycle/SolanaMobileWalletAdapterPrefsTests.cs

New dependencies:

  • None

Summary by CodeRabbit

  • Tests
    • Added contract tests enforcing adapter public surface and method signatures.
    • Added JSON deserialization tests for capabilities responses, including missing/unknown-field handling.
    • Added preferences migration tests covering legacy-to-namespaced key behavior and idempotence.
    • Added client lifecycle tests validating JSON-RPC payloads, id sequencing, and method behavior.

- CapabilitiesResult JSON + Response envelope
- Deauthorize/GetCapabilities request shape via mock sender
- IAdapterOperations reflection contract + [Preserve]
- PlayerPrefs migration via MigrateLegacyPrefKeys reflection
Refs magicblock-labs#269
Stable GUIDs for Unity import and cross-machine consistency.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b8292d2f-0ee4-4a2e-af1b-d419d140f536

📥 Commits

Reviewing files that changed from the base of the PR and between 6f8fba1 and 4b6ffac.

📒 Files selected for processing (2)
  • Tests/EditMode/Lifecycle/SolanaMobileWalletAdapterPrefsTests.cs
  • Tests/EditMode/MwaClient/MobileWalletAdapterClientLifecycleTests.cs

Walkthrough

Adds new Unity EditMode NUnit tests and accompanying .meta files: interface contract tests for IAdapterOperations, JSON deserialization tests for CapabilitiesResult, PlayerPrefs migration tests for SolanaMobileWalletAdapter, and RPC request/ID-sequencing tests for MobileWalletAdapterClient.

Changes

Cohort / File(s) Summary
Folder Metadata
Tests/EditMode/Contracts.meta, Tests/EditMode/Lifecycle.meta
Adds Unity .meta files marking new test folders as assets with persistent GUIDs and format version 2.
IAdapterOperations Contract Tests
Tests/EditMode/Contracts/IAdapterOperationsContractTests.cs, Tests/EditMode/Contracts/IAdapterOperationsContractTests.cs.meta
New NUnit reflection-based contract tests asserting exact public instance methods, return/parameter types, presence of [PreserveAttribute], implementor assignability, and exact method count for IAdapterOperations.
CapabilitiesResult Deserialization Tests
Tests/EditMode/JsonRpc/CapabilitiesResultTests.cs, Tests/EditMode/JsonRpc/CapabilitiesResultTests.cs.meta
Adds tests verifying snake_case JSON mapping to CapabilitiesResult, null/missing-field handling, tolerance of unknown fields, and Response<CapabilitiesResult> success/error envelope behavior.
PlayerPrefs Migration Tests
Tests/EditMode/Lifecycle/SolanaMobileWalletAdapterPrefsTests.cs, Tests/EditMode/Lifecycle/SolanaMobileWalletAdapterPrefsTests.cs.meta
Adds tests that snapshot/restore PlayerPrefs, reflect private migration constants/method, and validate migration semantics (copy legacy→namespaced, delete legacy, no overwrite, idempotency, edge cases).
MobileWalletAdapterClient Lifecycle Tests
Tests/EditMode/MwaClient/MobileWalletAdapterClientLifecycleTests.cs, Tests/EditMode/MwaClient/MobileWalletAdapterClientLifecycleTests.cs.meta
New tests using MockMessageSender to assert JSON-RPC 2.0 payloads (deauthorize, get_capabilities), params composition (including optional auth_token), and monotonic request ID sequencing across calls.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • Kuldotha
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.42% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title mentions 'mwa keep connection alive tests' but PR primarily adds lifecycle test coverage for Deauthorize, GetCapabilities, and PlayerPrefs migration—only partially matching the main deliverables. Consider a more precise title like 'test(editmode): add lifecycle and JSON contract tests' to better reflect the four test suites covering capabilities, deauthorize, preferences, and interface contracts.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description is comprehensive and well-structured, covering problem statement, detailed solution with specific test coverage counts, before/after screenshots, and deploy notes. It fully follows the template structure.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Tests/EditMode/JsonRpc/CapabilitiesResultTests.cs.meta`:
- Around line 1-2: Restore the missing MonoImporter metadata block in the three
new .cs.meta files by adding a MonoImporter section that includes the standard
keys: externalObjects, serializedVersion, defaultReferences, executionOrder,
icon, userData, assetBundleName, and assetBundleVariant; update the files
(Tests/EditMode/JsonRpc/CapabilitiesResultTests.cs.meta,
Tests/EditMode/Contracts/IAdapterOperationsContractTests.cs.meta,
Tests/EditMode/MwaClient/MobileWalletAdapterClientLifecycleTests.cs.meta) to
match existing C# script .meta structure so Unity won’t rewrite them.

In `@Tests/EditMode/Lifecycle/SolanaMobileWalletAdapterPrefsTests.cs`:
- Around line 1-52: Current SetUp/TearDown unconditionally delete keys and can
wipe a developer's real PlayerPrefs; modify tests to snapshot any existing
values for LegacyPk, LegacyAuthToken, NewPkKey, and NewAuthTokenKey in SetUp,
then delete keys for a clean test state (use DeleteAllRelevantKeys as-is for the
interim cleanup), and in TearDown restore the saved snapshots (recreate keys
only if they existed previously, removing keys that were absent) and call
PlayerPrefs.Save(); implement storage fields on the test class to hold the
original existence flags and values and update SetUp/TearDown to use those
fields when restoring.

In `@Tests/EditMode/MwaClient/MobileWalletAdapterClientLifecycleTests.cs`:
- Around line 38-48: Replace round-trip deserialization through JsonRequest with
direct inspection of the raw JSON bytes: update DecodeLastRequest and
DecodeRequestAt to return a JObject parsed from _sender.LastMessage and
_sender.SentMessages[index] (use Encoding.UTF8.GetString(...) then
JObject.Parse), and add helper(s) like DecodeLastParamsObject or
DecodeParamsObjectAt to extract the "params" JObject; update tests that
currently read properties off JsonRequest (e.g., asserting
request.Params.Identity) to instead assert presence/absence and exact key names
("auth_token", "identity", "params", etc.) on the JObject via Property(...) to
ensure wire-format and omitted-vs-null behavior is validated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 87f57257-d542-43cc-bb51-f29f1b25092c

📥 Commits

Reviewing files that changed from the base of the PR and between 74a2179 and 6f8fba1.

📒 Files selected for processing (10)
  • Tests/EditMode/Contracts.meta
  • Tests/EditMode/Contracts/IAdapterOperationsContractTests.cs
  • Tests/EditMode/Contracts/IAdapterOperationsContractTests.cs.meta
  • Tests/EditMode/JsonRpc/CapabilitiesResultTests.cs
  • Tests/EditMode/JsonRpc/CapabilitiesResultTests.cs.meta
  • Tests/EditMode/Lifecycle.meta
  • Tests/EditMode/Lifecycle/SolanaMobileWalletAdapterPrefsTests.cs
  • Tests/EditMode/Lifecycle/SolanaMobileWalletAdapterPrefsTests.cs.meta
  • Tests/EditMode/MwaClient/MobileWalletAdapterClientLifecycleTests.cs
  • Tests/EditMode/MwaClient/MobileWalletAdapterClientLifecycleTests.cs.meta

Comment thread Tests/EditMode/JsonRpc/CapabilitiesResultTests.cs.meta
Comment thread Tests/EditMode/Lifecycle/SolanaMobileWalletAdapterPrefsTests.cs
Comment thread Tests/EditMode/MwaClient/MobileWalletAdapterClientLifecycleTests.cs Outdated
- Assert Deauthorize/GetCapabilities payloads via JObject so JsonProperty
  drift can't hide broken wire keys
- Snapshot/restore MWA PlayerPrefs keys so EditMode runs don't wipe dev state
@JoshhSandhu
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@JoshhSandhu
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@JoshhSandhu
Copy link
Copy Markdown
Contributor Author

@Kuldotha follow-up tests for #269 MWA changes. CodeRabbit feedback incorporated and EditMode suite passes.

No SDK behavior change.

@Kuldotha Kuldotha merged commit c44a770 into magicblock-labs:main May 11, 2026
1 check passed
Zurcusa added a commit to Zurcusa/Solana.Unity-SDK that referenced this pull request May 11, 2026
Semaphore gate:
- Wrap _Login, _SignAllTransactions, SignMessage, GetCapabilities in
  TryAcquireGate/ReleaseGate to prevent concurrent state corruption

Bug fixes:
- Preserve WaitForCommitmentToSendNextTransaction when backfilling MinContextSlot
- Set WalletBase.Account on LoginWithSignIn success
- Default null mwaOptions in SolanaWalletAdapter so cache injection works

Upstream PR magicblock-labs#283 test compat:
- Update IAdapterOperationsContractTests for v2 AuthorizeAsync API
- Rewrite SolanaMobileWalletAdapterPrefsTests for v2 cache-based migration
- Fix MobileWalletAdapterClientLifecycleTests Authorize → AuthorizeAsync
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants