feat: multi-currency support and E2E tests for Kotlin sample#306
feat: multi-currency support and E2E tests for Kotlin sample#306
Conversation
- Fix SDK type mismatches (Config field names, QuoteSourceOneOf, AccountType enums) - Add multi-currency external account support (MXN, BRL, INR, GBP, PHP, EUR) - Add country selector dropdown and source currency dropdown (USD/USDC) - Add "Start New Payment" button to restart from external account step - Extract shared optText/requireText to JsonUtils, deduplicate across route files - Extract BeneficiaryFields to reduce copy-paste across beneficiary builders - Add Ktor server E2E tests (7 tests hitting Grid sandbox API) - Add Playwright browser E2E tests (8 tests driving the full React UI) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR adds multi-currency support (MXN, BRL, INR, GBP, PHP, EUR) to the Kotlin sample with a country selector dropdown, a source currency (USD/USDC) selector, and a "Start New Payment" reset button. It also fixes SDK v1.1.0 type mismatches, deduplicates Confidence Score: 5/5Safe to merge — both P2 findings are minor style/UX issues that do not block correctness. All remaining findings are P2: the 'Start New Payment' button appearing one step early is a no-op (harmless), and the misleading Playwright comment doesn't affect test correctness. The SDK type fixes, multi-currency routing, and test coverage are solid. samples/frontend/src/App.tsx (Start New Payment button condition) and samples/frontend/e2e/payout-flow.spec.ts (stale comment)
|
| Filename | Overview |
|---|---|
| samples/frontend/e2e/payout-flow.spec.ts | Adds 8 Playwright browser E2E tests covering the full payout flow; comment on line 44 incorrectly states the default country is IN when it is actually MX. |
| samples/frontend/playwright.config.ts | New Playwright config targeting port 8080 (Kotlin backend that serves pre-built React static files); previously flagged baseURL concern is a known trade-off documented in the spec file. |
| samples/frontend/src/App.tsx | Adds selectedCountry state, restartFromExternalAccount function, and "Start New Payment" button; button condition activeStep >= 1 shows it one step too early (no-op at the External Account step). |
| samples/frontend/src/steps/CreateExternalAccount.tsx | Adds COUNTRY_CONFIGS map with 6 currencies and a country selector dropdown; Math.random() in useEffect was already flagged in a prior review thread. |
| samples/frontend/src/steps/CreateQuote.tsx | Adds source currency dropdown (USD/USDC) and reads destination currency from COUNTRY_CONFIGS; clean implementation. |
| samples/kotlin/src/main/kotlin/com/grid/sample/JsonUtils.kt | Extracts optText/requireText extension functions to a shared location; behaviorally equivalent to the per-file implementations they replace. |
| samples/kotlin/src/main/kotlin/com/grid/sample/routes/ExternalAccounts.kt | Adds PHP and EUR account types, fixes SDK type references (e.g. UsdAccountInfo vs UsdExternalAccountInfo), deduplicates beneficiary parsing via parseBeneficiaryFields; EUR SWIFT workaround is documented inline. |
| samples/kotlin/src/main/kotlin/com/grid/sample/routes/Quotes.kt | Updates return type of buildQuoteSource to QuoteSourceOneOf and aligns factory method names to SDK v1.1.0; straightforward SDK migration. |
| samples/kotlin/src/test/kotlin/com/grid/sample/EndToEndTest.kt | Adds 7 backend E2E tests covering customer creation, external accounts (MXN, INR), validation rejections, quote creation, and a full payout flow; env var names in the docstring match Config.kt. |
| samples/kotlin/src/main/kotlin/com/grid/sample/GridClientBuilder.kt | Updates credential property references from gridClientId/gridClientSecret to apiTokenId/apiClientSecret to match renamed Config properties. |
| samples/kotlin/src/main/kotlin/com/grid/sample/routes/Customers.kt | Switches from local requiredText to shared requireText from JsonUtils; clean deduplication. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[POST /api/customers/:id/external-accounts] --> B{accountInfo present?}
B -- No --> ERR1[400 accountInfo is required]
B -- Yes --> C{accountType present?}
C -- No --> ERR2[400 accountType is required]
C -- Yes --> D{accountType value}
D -- USD_ACCOUNT --> USD[buildUsdBeneficiary\n→ UsdExternalAccountInfo]
D -- INR_ACCOUNT --> INR[buildInrBeneficiary\n→ InrExternalAccountInfo]
D -- BRL_ACCOUNT --> BRL[buildBrlBeneficiary\n→ BrlExternalAccountInfo]
D -- MXN_ACCOUNT --> MXN[buildMxnBeneficiary\n→ MxnExternalAccountInfo]
D -- GBP_ACCOUNT --> GBP[buildGbpBeneficiary\n→ GbpExternalAccountInfo]
D -- PHP_ACCOUNT --> PHP[buildPhpBeneficiary\n→ PhpExternalAccountInfo]
D -- EUR_ACCOUNT --> EUR[buildEurBeneficiary\n→ EurAccount + optional swiftBic workaround]
D -- other --> ERR3[throw IllegalArgumentException]
USD & INR & BRL & MXN & GBP & PHP & EUR --> EA[ExternalAccountCreate\nvia GridClient]
EA --> RES[201 Created — external account JSON]
Prompt To Fix All With AI
This is a comment left during a code review.
Path: samples/frontend/src/App.tsx
Line: 92-99
Comment:
**"Start New Payment" button is a no-op at the External Account step**
When `activeStep === 1` (the user is already on the Create External Account step), clicking this button calls `setActiveStep(1)` and clears `externalAccountId`/`quoteId`, both of which are already `null` — so nothing actually changes. The button is most useful after an external account has been created (i.e., from step 2 onwards).
```suggestion
{activeStep >= 2 && (
<button
onClick={restartFromExternalAccount}
className="mt-6 px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded text-sm font-medium text-gray-300"
>
Start New Payment
</button>
)}
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: samples/frontend/e2e/payout-flow.spec.ts
Line: 44-46
Comment:
**Stale comment: default country is MX, not IN**
The comment says the default country is `IN`, but `App.tsx` initialises `selectedCountry` to `'MX'`. The actual test assertions are correct (they explicitly select countries before checking), but the comment is misleading.
```suggestion
// Default country is MX; switch to each and verify the textarea updates.
// Switch to India
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (5): Last reviewed commit: "Merge branch 'main' into feat/sample-mul..." | Re-trigger Greptile
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- India: name, UPI, countryOfResidence - Mexico: name, CLABE, countryOfResidence - Brazil: name, taxId, pixKeyType, pixKey, countryOfResidence - Philippines: name, bankCode, accountNumber, countryOfResidence - EU: name, IBAN, full address, countryOfResidence - UK: name, sortCode, accountNumber, countryOfResidence Removes extra fields (birthDate, email, phone, swiftCode) that are not required per the spec. Makes swiftCode optional in the EUR backend handler. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The API field is countryOfResidence, not nationality. Updated frontend configs, backend parser (with fallback to nationality), and E2E tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
optText/requireTexttoJsonUtils.kt, deduplicateBeneficiaryFieldsparsingTest plan
cd samples/kotlin && ./gradlew test— 7 backend E2E tests passcd samples/frontend && npm run test:e2e— 8 Playwright browser tests pass (requires backend running)🤖 Generated with Claude Code