Skip to content

test: lock down PaymentSheet wire-format contract for @JsonKey renames#2418

Open
realmeylisdev wants to merge 3 commits into
flutter-stripe:mainfrom
realmeylisdev:test/payment-sheet-wire-contract
Open

test: lock down PaymentSheet wire-format contract for @JsonKey renames#2418
realmeylisdev wants to merge 3 commits into
flutter-stripe:mainfrom
realmeylisdev:test/payment-sheet-wire-contract

Conversation

@realmeylisdev

@realmeylisdev realmeylisdev commented May 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Add contract tests asserting that SetupPaymentSheetParameters.toJson() emits the JSON field names the native iOS and Android handlers actually read. Complements the regression test added in #2407.

Why

Per CONTRIBUTING.md, the native folders (packages/stripe_ios/ios/.../Stripe Sdk/, packages/stripe_android/.../reactnativestripesdk/) are kept in sync with stripe-react-native and are not editable here. That means the Dart side is the only place to enforce the bridge field-name contract — but there is no type-level link between Dart @JsonKey(name: …) annotations and the RN-derived native readers, so drift goes silent.

Issue #2398 (linkDisplayParams silently ignored) was the third Link-display-class fix in five months (d76710c, #2313, #2407). #2407 added an inline contract test for link.display. This PR extends that approach to the other two @JsonKey(name: …) renames in SetupPaymentSheetParameters:

  • billingDetailsdefaultBillingDetails
    Read by StripeSdkImpl+PaymentSheet.swift:74, StripeSdkImpl+Embedded.swift:354, PaymentSheetManager.kt:311, EmbeddedPaymentElementViewManager.kt:95.
  • customPaymentMethodConfiguration.customPaymentMethods
    Read by Mappers.kt:1044.

The tests assert by field name (not full snapshot), so they won't trip on unrelated additions to the params struct.

Test plan

  • flutter test packages/stripe_platform_interface/test/method_channel_stripe_test.dart — all 28 tests pass, including the 2 new ones
  • dart format clean
  • flutter analyze clean
  • CI re-runs on PR

AI/LLM disclosure

Per CONTRIBUTING.md: this PR was drafted with Claude Code (Anthropic Claude Opus 4.7). The author reviewed all generated code, the tests were run locally, and the author will own all follow-up review comments.

Summary by CodeRabbit

  • Tests
    • Added validation tests for payment sheet initialization to ensure billing details are serialized to the expected native key.
    • Added tests confirming custom payment method configuration nests custom payment methods correctly.
    • Improves confidence that payment sheet parameters are formatted consistently across platforms.

Review Change Stack

Add tests asserting that SetupPaymentSheetParameters.toJson() emits the
field names the native iOS and Android handlers actually read. The native
folders are 1:1 mirrors of stripe-react-native and get overwritten by
periodic Sync commits, so any Dart-side @jsonkey(name: ...) silently
drifting from the native key name breaks PaymentSheet config without a
build error (see flutter-stripe#2398).

Covers two renames not already guarded by the existing link.display test
added in flutter-stripe#2407:

- billingDetails -> "defaultBillingDetails"
- customPaymentMethodConfiguration.customPaymentMethods
@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: df7bddbd-1932-4092-a714-861cbc6f4c4f

📥 Commits

Reviewing files that changed from the base of the PR and between 557b771 and 8ca9e2e.

📒 Files selected for processing (1)
  • packages/stripe_platform_interface/test/method_channel_stripe_test.dart

📝 Walkthrough

Walkthrough

This PR adds test coverage for the initPaymentSheet method-channel wire-format contract. A test helper captures the serialized params payload, and two assertions verify that billingDetails is serialized under the native key defaultBillingDetails and that customPaymentMethodConfiguration nests a customPaymentMethods array.

Changes

Wire-Format Contract Tests

Layer / File(s) Summary
initPaymentSheet wire-format contract validation
packages/stripe_platform_interface/test/method_channel_stripe_test.dart
A serialize test helper constructs a mock-backed MethodChannelStripe, invokes initPaymentSheet, and captures serialized params. Tests verify billingDetails maps to defaultBillingDetails in serialized output and customPaymentMethodConfiguration correctly nests a customPaymentMethods array.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • jonasbark
  • remonh87

Poem

🐰 In test burrows I hop and write,
Capturing params in the soft moonlight,
Billing details renamed just right,
Custom methods nested out of sight,
Hooray — the wire-format tests take flight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding contract tests for PaymentSheet wire-format to lock down @JsonKey renames, which is the primary objective of the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/stripe_platform_interface/test/method_channel_stripe_test.dart (2)

383-392: ⚡ Quick win

Consider verifying the serialized value structure.

The test verifies the key rename but doesn't check if the email value is properly serialized. If defaultBillingDetails is present but null or if BillingDetails serialization is broken, the test would still pass.

🔍 Suggested enhancement
 test('billingDetails is sent as "defaultBillingDetails"', () async {
   final params = await serialize(
     const SetupPaymentSheetParameters(
       paymentIntentClientSecret: 'pi_test',
       billingDetails: BillingDetails(email: 'a@b.com'),
     ),
   );
   expect(params.containsKey('defaultBillingDetails'), isTrue);
   expect(params.containsKey('billingDetails'), isFalse);
+  final billing = params['defaultBillingDetails'] as Map;
+  expect(billing['email'], 'a@b.com');
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/stripe_platform_interface/test/method_channel_stripe_test.dart`
around lines 383 - 392, The test 'billingDetails is sent as
"defaultBillingDetails"' currently only checks key presence; update it to also
verify the serialized value structure by deserializing or inspecting the map
returned by serialize(const SetupPaymentSheetParameters(...)) and assert that
the 'defaultBillingDetails' entry is a non-null map containing the expected
email ('a@b.com'); reference the serialize function,
SetupPaymentSheetParameters, BillingDetails, and the 'defaultBillingDetails' key
when adding an expectation that params['defaultBillingDetails']['email'] ==
'a@b.com' (or equivalent null-safe access) so the test fails if the billing
details are missing or improperly serialized.

394-413: ⚡ Quick win

Consider verifying the array type and content.

The test verifies the key exists but doesn't check if customPaymentMethods is actually a List or if the test payment method is serialized correctly. If the field is present but has the wrong type or empty content, the test would still pass.

🔍 Suggested enhancement
 test(
   'customPaymentMethodConfiguration nests customPaymentMethods array',
   () async {
     final params = await serialize(
       const SetupPaymentSheetParameters(
         paymentIntentClientSecret: 'pi_test',
         customPaymentMethodConfiguration:
             CustomPaymentMethodConfiguration(
               customPaymentMethods: [
                 CustomPaymentMethod(id: 'cpmt_test'),
               ],
             ),
       ),
     );
     final config =
         params['customPaymentMethodConfiguration']
             as Map<dynamic, dynamic>;
     expect(config.containsKey('customPaymentMethods'), isTrue);
+    final methods = config['customPaymentMethods'] as List;
+    expect(methods, isNotEmpty);
+    expect((methods.first as Map)['id'], 'cpmt_test');
   },
 );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/stripe_platform_interface/test/method_channel_stripe_test.dart`
around lines 394 - 413, Update the test "customPaymentMethodConfiguration nests
customPaymentMethods array" to not only assert the presence of the key but also
validate that params['customPaymentMethodConfiguration'] (config) holds a List
under 'customPaymentMethods' and that the serialized list contains the expected
serialized CustomPaymentMethod with id 'cpmt_test'; specifically, after
obtaining config from serialize(SetupPaymentSheetParameters(...)) assert that
config['customPaymentMethods'] is a List (or List<dynamic>) and that at least
one element in that list is a Map containing the key/value pair for id:
'cpmt_test' so the serialization for CustomPaymentMethodConfiguration and
CustomPaymentMethod is verified.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/stripe_platform_interface/test/method_channel_stripe_test.dart`:
- Around line 383-392: The test 'billingDetails is sent as
"defaultBillingDetails"' currently only checks key presence; update it to also
verify the serialized value structure by deserializing or inspecting the map
returned by serialize(const SetupPaymentSheetParameters(...)) and assert that
the 'defaultBillingDetails' entry is a non-null map containing the expected
email ('a@b.com'); reference the serialize function,
SetupPaymentSheetParameters, BillingDetails, and the 'defaultBillingDetails' key
when adding an expectation that params['defaultBillingDetails']['email'] ==
'a@b.com' (or equivalent null-safe access) so the test fails if the billing
details are missing or improperly serialized.
- Around line 394-413: Update the test "customPaymentMethodConfiguration nests
customPaymentMethods array" to not only assert the presence of the key but also
validate that params['customPaymentMethodConfiguration'] (config) holds a List
under 'customPaymentMethods' and that the serialized list contains the expected
serialized CustomPaymentMethod with id 'cpmt_test'; specifically, after
obtaining config from serialize(SetupPaymentSheetParameters(...)) assert that
config['customPaymentMethods'] is a List (or List<dynamic>) and that at least
one element in that list is a Map containing the key/value pair for id:
'cpmt_test' so the serialization for CustomPaymentMethodConfiguration and
CustomPaymentMethod is verified.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 34c7fd04-a939-4807-bf44-2162970ae45a

📥 Commits

Reviewing files that changed from the base of the PR and between 8b8d0eb and 557b771.

📒 Files selected for processing (1)
  • packages/stripe_platform_interface/test/method_channel_stripe_test.dart

Add value-shape assertions on top of the key-rename checks, so the tests
also catch regressions in the nested model toJson() output:

- billingDetails: assert defaultBillingDetails.email round-trips
- customPaymentMethodConfiguration: assert customPaymentMethods is a
  non-empty List whose first element's "id" matches
@realmeylisdev

Copy link
Copy Markdown
Contributor Author

Heads-up: the failing stripe_js / build check is the known fork-PR secrets limitation, not anything from this change.

  • stripe_js.yaml reads secrets.STRIPE_PUBLISHABLE_KEY and env-files.sh sed-substitutes it into /example/lib/.env.dart, which packages/stripe_js/test/src/js/helpers/test_keys.dart then imports.
  • For pull_request from a fork, GitHub Actions resolves secrets.* to empty string, so stripePublishableKey == "" and Stripe("") throws IntegrationError: Please call Stripe() with your publishable key. You used an empty string.
  • Last 30 stripe_js runs: 7 SUCCESS, all on internal sync_v0.65.1; 15 FAILURE, all on fork branches — including Fix: Link display params serialization #2407 (fix/link-display-json-name2), which was merged despite the identical red check.

This PR only touches packages/stripe_platform_interface/test/, which the stripe_js tests don't depend on. Happy to defer to your usual workflow — re-run with secrets, merge as-is, or address the workflow separately.

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.

1 participant