Repository navigation
feat: Pay later button - #1753
Conversation
…od name (#1732) Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* feat: add pay later wordmark assets * feat: add basic pay later button * fix: remove analytic constants and render PayPalResult as non-optional * refactor: set `offerPayLater` to true * feat: clean-up Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add basic pay later button * fix: remove analytic constants and render PayPalResult as non-optional * refactor: set `offerPayLater` to true * feat: clean-up Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: share button style mapping between paypal and pay later colors Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor(demo): handle pay later return in onResume with separate slots Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * style: fix trailing space and missing final newline Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: extract shared drawing logic into PaymentButtonRenderer Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: disable payment buttons while a flow is in progress Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: re-enable payment buttons when a flow fails or finishes Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: address pr feedback Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: fix lint warnings Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* feat: add pay later wordmark assets * feat: add basic pay later button * fix: remove analytic constants and render PayPalResult as non-optional * refactor: set `offerPayLater` to true * feat: clean-up Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add basic pay later button * fix: remove analytic constants and render PayPalResult as non-optional * refactor: set `offerPayLater` to true * feat: clean-up Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: share button style mapping between paypal and pay later colors Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor(demo): handle pay later return in onResume with separate slots Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * style: fix trailing space and missing final newline Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add composable paylaterbuttonview Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * style: add new line Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: extract shared drawing logic into PaymentButtonRenderer Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: update pay later button composable Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add compose pay later button Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add pay later composable to demo app Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: disable payment buttons while a flow is in progress Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: re-enable payment buttons when a flow fails or finishes Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: address lint warning Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: address pr feedback Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: fix lint warnings Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add composable paylaterbuttonview Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * style: add new line Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: update pay later button composable Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add compose pay later button Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add pay later composable to demo app Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: address lint warning Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: persist compose pay later flow state across activity recreation Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: re-enable compose pay later button when the flow fails to launch Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: adding missing } Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: deliver compose pay later missing-registry failure from a LaunchedEffect Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: extract shared paypal flow for compose paypal and pay laterbuttons Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * test: add unit tests for compose PayPal flow helpers Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: lint issues Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * test: add compose pay later button test Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * test: add test to make sure the flag is only set for pay later request Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* test: add UIComponents unit test coverage for buttons and card field inputs Add unit tests for the View PayPalButton, Compose PayPal/Venmo buttons, button colors, activity/context extensions, PendingRequestException, Compose button views, Compose CardFields CVV truncation, and BaseTextInputView. To make the buttons testable, add an internal constructor to the View PayPalButton and route the Compose buttons through internal PayPalButtonContent/VenmoButtonContent composables that accept factories. Public APIs are unchanged. Add Compose UI test dependencies to the unit test classpath and remove the placeholder ExampleUnitTest. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * test: cover View VenmoButton, PayLaterButton flows and PaymentButtonRenderer Add unit tests for the View VenmoButton, PayLaterButton launch/return flows, PaymentButtonRenderer appearance states and PaymentButtonStyle mappings. Add an internal constructor to the View VenmoButton for dependency injection in tests; the public API is unchanged. Remove the ActivityExtensions and ContextExtensions unit tests, which are covered through the button tests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * test: merge PayLaterButton and PaymentButtonRenderer tests into existing files Move the PayLaterButton flow tests into PayLaterButtonUnitTest and the renderer appearance tests into PaymentButtonRendererUnitTest so each class has a single test file. Replace the weak pressed-state renderer test with fill-color assertions. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * test: remove vacuous and duplicate UIComponents tests Delete tests that restated source constants or could not fail (focus fill, same-color setButtonColor, color keys, PaymentButtonStyleUnitTest, repeated loading cycle, Compose color-style count). Fold error assertions into the existing PayLaterButton failure tests and strengthen click, NPE, hint and icon tests with argument, message and direction checks. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix: remove test bloat * test: merge CardFields CVV truncation tests into CardFieldsUnitTest Move the Compose CardFields CVV truncation tests into the existing CardFieldsUnitTest so the composable has a single test file. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix: remove more test bloat * fix: removing PayPal compose tests since refactor is coming * refactor: restore compose PayPalButton to match the base branch Remove the internal PayPalButtonContent seam added for unit tests, since the compose PayPalButton tests were removed ahead of an upcoming refactor. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * test: add compose PayPalButton unit tests Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix: resolve lint issue --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* feat: add pay later wordmark assets * feat: add basic pay later button * fix: remove analytic constants and render PayPalResult as non-optional * refactor: set `offerPayLater` to true * feat: clean-up Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add basic pay later button * fix: remove analytic constants and render PayPalResult as non-optional * refactor: set `offerPayLater` to true * feat: clean-up Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: share button style mapping between paypal and pay later colors Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor(demo): handle pay later return in onResume with separate slots Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * style: fix trailing space and missing final newline Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * refactor: extract shared drawing logic into PaymentButtonRenderer Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: disable payment buttons while a flow is in progress Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add analytics events to PayLaterButton Sends PAY_LATER_BUTTON_PRESENTED on initialize and PAY_LATER_BUTTON_SELECTED when the PayPal flow is launched, mirroring the existing PayPalButton/VenmoButton pattern. Adds a UIComponentsAnalyticsUnitTest pinning the event name constants. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix: resolve lint issue * fix: remove unnecessary hideLoading * test: mock AnalyticsClient in PayLaterButtonUnitTest The launch failure test reaches the analytics call in completePayPalFlow, which built a real AnalyticsClient and threw because SdkComponent is not initialized in unit tests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * test: verify Pay Later selected analytics event Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * feat: add analytics events to compose PayLaterButton Sends PAY_LATER_BUTTON_PRESENTED once when the composable is first shown and PAY_LATER_BUTTON_SELECTED on click, with the compose UI type, mirroring the compose PayPalButton. Adds unit tests for the compose and XML Pay Later button analytics, and Compose UI test dependencies to the UIComponents unit test classpath. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Alekhya Geddam <ageddam@paypal.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* test: add PayLaterButton instrumentation tests Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * test: Expand PayLaterButton UI and unit test coverage Add XML inflation, drawing, initialize and click instrumentation tests, compose PayLaterButtonView and click-failure tests, and compose PayLaterButton unit tests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * test: Prune redundant PayLaterButton instrumentation tests Remove tests that duplicate PayPalButtonTest coverage of the shared renderer or repeat each other. Fix compose PayLaterButton crashing when it is the first SDK use by resolving AnalyticsClient lazily after PayPalClient is created. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix: remove useless comment --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Dependency Review✅ No vulnerabilities found.Scanned Files
|
|
I think it would be useful to add end-to-end recording of the flow to this PR ❤️ |
|
Ah yup! I forgot again! I'll get that up soon |
…eation (#1755) * feat: fix paypal button compose flows not returning a result when activity is recreated Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: update browser-switch version and add change-log entry Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: update changelog.md Co-authored-by: Jax DesMarais-Leder <jdesmarais@paypal.com> Signed-off-by: agedd <ageddam@paypal.com> * doc: update browser-switch version in DEPENDENCIES.md Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Signed-off-by: agedd <ageddam@paypal.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Jax DesMarais-Leder <jdesmarais@paypal.com>
|
Hey so with |
mzlangreder
left a comment
There was a problem hiding this comment.
Looking good, just a few questions
Do we have any tests that verify resuming after a launched flow?
| * UIComponents | ||
| * Fix Compose `PayPalButton` and `PayLaterButton` not returning a result when the Activity is recreated while the browser is open | ||
| * Fix `VenmoButton` not re-enabling after failure in `createPaymentAuthRequest`, `venmoLauncher.launch()`, or when the hosting Activity is null | ||
| * Add `PayLaterButton` and compose support to generate a PayPal-PayLater branded button for launching the PayLater flow |
There was a problem hiding this comment.
Should we mention the fixes to the existing PayPalButton behavior, such as:
- XML re-enabling after
createPaymentAuthRequestfailure,payPalLauncher.launch()failure, or a null hosting Activity - XML keeping the loading indicator until
tokenizecompletes, rather than re-enabling immediately after dispatching tokenization - Compose re-enabling after
payPalLauncher.launch()failure
There was a problem hiding this comment.
Yeah that's a good callout. I'll add that to the CHANGELOG
| fun setUp() { | ||
| context = ApplicationProvider.getApplicationContext() | ||
| every { mockPayPalClient.createPaymentAuthRequest(any(), any(), capture(authCallback)) } just runs | ||
| mockkObject(AnalyticsClient.Companion) |
There was a problem hiding this comment.
Should this test unmock AnalyticsClient.Companion in an @After, like PayPalButtonUnitTest does?
There was a problem hiding this comment.
Ah! Yes it should. Fix incoming
What exactly do you mean by resuming after a launched flow? Like handling return to app or are you talking about the process death and recreation case? |
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nitTest Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
noguier
left a comment
There was a problem hiding this comment.
I have tested everything end-to-end on emulators and physical device! everything functioning as expected! Great work @saralvasquez and @agedd
|
Just a heads up, @agedd is gonna be pushing a commit for the venmo button fix to this PR since it's super easy and quick so we'll ask for one last check through on this once that's up |
…hangelog Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Backgrounding/resuming I was more my thinking. |
|
@agedd venmo with do not keep activities work in UI components compose, but not XML, can we fix the XML venmo button too :) |
Ah interesting... no I don't think we have tests like that for any of the buttons. I can try and put together a test like, but I'll at least test that manually to make sure everything works as expects |
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary of changes
XML
Screen_recording_20261109_112348.webm
Compose
Screen_recording_20261109_112526.webm
AI Usage
Which AI Agent Was Used?
How was AI used?
Aided in the development of this feature in many ways
Estimated AI Code Contribution
Checklist
Authors