test: cover custom paywall tracking, ad tracker, and model parsing - #1013
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
75760bd to
3ded913
Compare
a99499a to
a16c6a6
Compare
62ef6c4 to
98db931
Compare
72cb687 to
7eda6d0
Compare
98db931 to
c91fc0a
Compare
7eda6d0 to
f60e3e3
Compare
c91fc0a to
a45f0a2
Compare
This one's pure harness/CI plumbing, no test content, so it's a small. Adds the `RevenueCat.Tests.EditMode` assembly, `PurchasesWrapperSpy`, and an internal `SetWrapper` hook (via `InternalsVisibleTo`) so tests can inject the spy into `Purchases`. Wires a `test-edit-mode` CircleCI job that imports the packaged SDK and runs the suite the same way CI already exercises the API tests. Stacked on top, each independent of the others: - #1014 configuration and harness smoke tests - #1010 wrapper pass-through tests - #1011 purchase forwarding & result parsing - #1012 single-request callback flows - #1013 tracking + model tests <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Changes are test/CI infrastructure plus a small internal injection hook on `Purchases`; no production purchase or auth behavior changes for shipped apps. > > **Overview** > Adds **Unity Edit Mode test plumbing** so later PRs can assert `Purchases` behavior against the **exported** `Purchases.unitypackage` / `PurchasesUI.unitypackage`. > > Introduces the Editor-only `RevenueCat.Tests.EditMode` assembly and a **`PurchasesWrapperSpy`** that records every `IPurchasesWrapper` call. **`Purchases.SetWrapper`** (internal, exposed via `InternalsVisibleTo` on the SDK assembly) lets tests inject the spy and keeps **`AdTracker`** wired to the same wrapper; platform `Start()` now goes through `SetWrapper` instead of assigning `_wrapper` directly. > > **CircleCI** broadens the pre-import “hide scripts” step to `Assets/Tests` (`.cs` and `.asmdef`), adds a **`test-edit-mode`** job (`unity/test` editmode after `import-package`), stores JUnit artifacts, and gates the release **hold** on that job. **IntegrationTests README** documents running Edit Mode tests locally via Test Runner. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a45f0a2. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
6890f1d to
af190db
Compare
Adds TrackingTests.cs for custom paywall parameter resolution and ad-tracker forwarding/JSON serialization. Expands JsonModelTests.cs with full/minimal CustomerInfo and SubscriptionOption payloads, the epoch-vs-null date quirk, unrecognized-enum fallback, and WebPurchaseRedemption / WebPurchaseRedemptionResult variants.
…oads MinimalCustomerInfoJson omitted every field the mappers always send as an explicit null, plus entitlements.verification: Android's convertToJson maps Kotlin null to JSONObject.NULL and the iOS mappers use NSNull(), so those keys are present on the wire rather than absent. Spelled them out. The web redemption error fixture paired code 11 with readableErrorCode "UNKNOWN_ERROR", which neither platform produces and which contradicts the code. Code 11 is InvalidCredentialsError, so it now carries the iOS values for that code and the deprecated readable_error_code key that ships alongside. Left the deliberately synthetic values alone and documented why: "UNRECOGNIZED" and "BOGUS" stand in for enum members added natively before Unity knows the name, which is what those two fallback tests exist to pin down. Co-Authored-By: Claude <noreply@anthropic.com>
af190db to
b497178
Compare
The pinned version went stale within a day of being written — it was bumped from 18.25.0 to 18.29.0 while this branch was in review. The mapper names alone are enough to find the source. Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit cd17929. Configure here.
| Assert.That(json["mediatorName"].Value, Is.EqualTo("AdMob")); | ||
| Assert.That(json["adFormat"].Value, Is.EqualTo("banner")); | ||
| Assert.That(json["adUnitId"].Value, Is.EqualTo("unit_1")); | ||
| Assert.That(json.HasKey("impressionId"), Is.False); |
There was a problem hiding this comment.
Wrong optional-field assertion in test
Low Severity
AdFailedToLoadDataToJsonStringOmitsOptionalFieldsWhenAbsent asserts that impressionId is absent, but AdFailedToLoadData has no ImpressionId member and never serializes that key. The check always passes and misdocuments the optional fields this type actually supports (placement, mediatorErrorCode).
Reviewed by Cursor Bugbot for commit cd17929. Configure here.
**This is an automatic release.** ## RevenueCat SDK ### ✨ New Features * feat(ads): expose reward verification primitives (#971) via Peter Porfy (@peterporfy) ### 🐞 Bugfixes * Stop sending the purchase response twice on iOS errors (#1042) via Cesar de la Vega (@vegaro) * fix: surface native errors from GetCurrentOfferingForPlacement (#1019) via Cesar de la Vega (@vegaro) ### 📦 Dependency Updates * [AUTOMATIC BUMP] Updates purchases-hybrid-common to 18.30.0 (#1046) via RevenueCat Git Bot (@RCGitBot) * [Android 10.16.1](https://github.com/RevenueCat/purchases-android/releases/tag/10.16.1) * [iOS 5.83.1](https://github.com/RevenueCat/purchases-ios/releases/tag/5.83.1) ### 🔄 Other Changes * feat(ads): ad reward sample app (#1045) via Peter Porfy (@peterporfy) * test: cover custom paywall tracking, ad tracker, and model parsing (#1013) via Cesar de la Vega (@vegaro) * test: cover missing Purchases functions (#1012) via Cesar de la Vega (@vegaro) * Bump fastlane-plugin-revenuecat_internal from `b4e1e7f` to `7fbbe66` (#1040) via dependabot[bot] (@dependabot[bot]) * Bump fastlane-plugin-revenuecat_internal from `dd577ee` to `b4e1e7f` (#1038) via dependabot[bot] (@dependabot[bot]) * Bump fastlane-plugin-revenuecat_internal from `3421c88` to `dd577ee` (#1036) via dependabot[bot] (@dependabot[bot]) * Bump danger from 9.6.0 to 9.6.1 (#1035) via dependabot[bot] (@dependabot[bot]) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches iOS purchase callback behavior and offerings/placement error paths, plus new ads reward-verification APIs backed by a native SDK bump. > > **Overview** > This **automatic release** cuts **9.8.0** by bumping package/plugin versions (`.version`, `package.json`, Android/iOS `PLUGIN_VERSION`) and publishing **CHANGELOG** / **VERSIONS.md** for **purchases-hybrid-common 18.30.0** (iOS **5.83.1**, Android **10.16.1**). > > Shipped in this version (from prior merges, summarized in the changelog): **ad reward verification** primitives (`generateRewardVerificationToken` / `pollRewardVerification` on the native bridge), fixes so **iOS purchase errors** no longer emit the purchase callback twice, and **GetCurrentOfferingForPlacement** now surfaces native failures instead of swallowing them. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a2f2846. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->



Part of the #1006 split. Rebased onto
main; no longer stacked on anything.Adds
TrackingTests.csfor custom paywall parameter resolution and ad-tracker forwarding/JSON serialization, and extendsJsonModelTests.cswith full/minimalCustomerInfoandSubscriptionOptionpayloads, the epoch-vs-null date quirk, unrecognized-enum fallbacks, and theWebPurchaseRedemption/WebPurchaseRedemptionResultvariants.The JsonModelTests overlap is resolved
The earlier note here warned that this and #1014 both create
JsonModelTests.cs. #1014 landed first, so I checked whatmainalready has before rebasing:main's version holds 4 tests (VirtualCurrenciesParsesCurrenciesByCode,SubscriptionPriceSupportsValuesAboveInt32Range,StoreProductParsesKnownProductCategory,StoreProductFallsBackToUnknownProductCategory), this branch's version is a strict superset containing those same 4 with byte-identical bodies plus 11 more. Nothing onmainis unique, so the rebase keeps this version wholesale — no coverage lost, no duplication introduced. The file now has 15 tests.Second commit: fixture fidelity
MinimalCustomerInfoJsonomitted every field the mappers always send as an explicit null, plusentitlements.verification. Android'sconvertToJsonmaps KotlinnulltoJSONObject.NULLand the iOS mappers useNSNull(), so those keys are on the wire, not absent.The web-redemption error fixture paired
"code":11withreadableErrorCode: "UNKNOWN_ERROR"— a value neither platform emits, and inconsistent with the code. Code 11 isInvalidCredentialsError, so it now carries the iOS values for that code plus the deprecatedreadable_error_codethat ships alongside it.The synthetic
"UNRECOGNIZED"and"BOGUS"values are unchanged and now carry comments: they stand in for enum members added natively before Unity knows the name, which is exactly what those fallback tests exist to pin down.Verified against purchases-hybrid-common 18.29.0, which is what
mainpins. TheredeemWebPurchaseresult names and per-variant payload shapes (customerInfoon success,erroron failure,obfuscatedEmailon expiry, bareresultfor the other two) already matched and were left alone.Verification
🤖 Generated with Claude Code
Note
Low Risk
Test-only changes (fixtures and NUnit tests); no runtime SDK or native bridge behavior is modified.
Overview
Adds Edit Mode test coverage for JSON model parsing and analytics forwarding, without changing production SDK code.
JsonModelTests moves inline JSON into
JsonModelFixturesand adds tests for fullCustomerInfo, full/minimalSubscriptionOption, millis0→ null dates,UNKNOWNfallbacks for unrecognized enums/categories, and allWebPurchaseRedemptionResultvariants (plusArgumentExceptionon unknownresult).TrackingTests (new) uses
PurchasesWrapperSpyto verifyTrackCustomPaywallImpressionparameter resolution (offering id/context from first package, deprecated ctor) and thatAdTrackerevents forward to the wrapper, includingToJsonStringoptional-field omission for ad payload types.Reviewed by Cursor Bugbot for commit cd17929. Bugbot is set up for automated code reviews on this repo. Configure here.