| import { expect, test } from "bun:test"; |
| import { |
| transformAccount, |
| transformAccountBalance, |
| transformTransaction, |
| } from "./transform"; |
|
|
| test("Transform expense transaction (depository)", () => { |
| expect( |
| transformTransaction({ |
| accountType: "depository", |
| transaction: { |
| transactionId: |
| "8wwecA0PsWWCLPLazQzht2oOcxSIQ5UlWPHaNBpC3tjYtc002faJcjWzRpyO4sjz66kRpb7_5rA", |
| entryReference: "5490990006", |
| bookingDate: "2024-02-23", |
| valueDate: "2024-02-23", |
| transactionAmount: { |
| amount: "-38000.00", |
| currency: "SEK", |
| }, |
| additionalInformation: "LÖN 160434262327", |
| proprietaryBankTransactionCode: "Transfer", |
| internalTransactionId: "86b1bc36e6a6d2a5dee8ff7138920255", |
| }, |
| }), |
| ).toMatchSnapshot(); |
| }); |
|
|
| test("Transform income transaction (depository)", () => { |
| expect( |
| transformTransaction({ |
| accountType: "depository", |
| transaction: { |
| transactionId: "income-test-123", |
| bookingDate: "2024-02-23", |
| transactionAmount: { |
| amount: "5000.00", |
| currency: "SEK", |
| }, |
| additionalInformation: "Salary deposit", |
| proprietaryBankTransactionCode: "Transfer", |
| internalTransactionId: "income-internal-123", |
| }, |
| }), |
| ).toMatchSnapshot(); |
| }); |
|
|
| test("Transform credit card payment - should be credit-card-payment not income", () => { |
| |
| |
| expect( |
| transformTransaction({ |
| accountType: "credit", |
| transaction: { |
| transactionId: "cc-payment-123", |
| bookingDate: "2024-02-23", |
| transactionAmount: { |
| amount: "500.00", |
| currency: "SEK", |
| }, |
| additionalInformation: "Credit card payment", |
| proprietaryBankTransactionCode: "Transfer", |
| internalTransactionId: "cc-payment-internal-123", |
| }, |
| }), |
| ).toMatchSnapshot(); |
| }); |
|
|
| test("Transform credit card refund - should be null (user categorizes)", () => { |
| |
| expect( |
| transformTransaction({ |
| accountType: "credit", |
| transaction: { |
| transactionId: "cc-refund-123", |
| bookingDate: "2024-02-23", |
| transactionAmount: { |
| amount: "75.00", |
| currency: "SEK", |
| }, |
| creditorName: "Some Merchant", |
| additionalInformation: "Refund", |
| proprietaryBankTransactionCode: "Card purchase", |
| internalTransactionId: "cc-refund-internal-123", |
| }, |
| }), |
| ).toMatchSnapshot(); |
| }); |
|
|
| test("Transform accounts", () => { |
| |
| const transformedAccount = transformAccount({ |
| id: "b11e5627-cac8-41c9-a74a-2b88438fe07d", |
| created: "2024-02-23T13:29:47.314568Z", |
| last_accessed: "2024-03-06T16:34:16.782598Z", |
| iban: "3133", |
| institution_id: "PLEO_PLEODK00", |
| status: "READY", |
| owner_name: "", |
| account: { |
| resourceId: "3133", |
| currency: "SEK", |
| name: "Pleo Account", |
| product: "Pleo", |
| cashAccountType: "TRAN", |
| iban: "123", |
| ownerName: "Name", |
| }, |
| balance: { |
| currency: "SEK", |
| amount: "1942682.86", |
| }, |
| institution: { |
| id: "PLEO_PLEODK00", |
| name: "Pleo", |
| bic: "PLEODK00", |
| transaction_total_days: "90", |
| countries: ["DK", "GB", "DE", "SE", "ES", "IE", "DK"], |
| logo: "https://cdn-logos.gocardless.com/ais/PLEO_PLEODK00.png", |
| }, |
| }); |
|
|
| |
| |
| const stableAccount = { |
| ...transformedAccount, |
| expires_at: "FIXED_DATE_FOR_TESTING", |
| }; |
|
|
| expect(stableAccount).toMatchSnapshot(); |
| }); |
|
|
| test("Transform credit card account (CARD type)", () => { |
| const transformedAccount = transformAccount({ |
| id: "credit-card-account-123", |
| created: "2024-02-23T13:29:47.314568Z", |
| last_accessed: "2024-03-06T16:34:16.782598Z", |
| iban: "4444", |
| institution_id: "BANK_CREDIT", |
| status: "READY", |
| owner_name: "John Doe", |
| account: { |
| resourceId: "4444", |
| currency: "EUR", |
| name: "Credit Card", |
| product: "Visa Gold", |
| cashAccountType: "CARD", |
| iban: "4444", |
| ownerName: "John Doe", |
| }, |
| balance: { |
| currency: "EUR", |
| amount: "-1500.00", |
| }, |
| institution: { |
| id: "BANK_CREDIT", |
| name: "Test Bank", |
| bic: "TESTBIC", |
| transaction_total_days: "90", |
| countries: ["DE"], |
| logo: "https://example.com/logo.png", |
| }, |
| }); |
|
|
| const stableAccount = { |
| ...transformedAccount, |
| expires_at: "FIXED_DATE_FOR_TESTING", |
| }; |
|
|
| expect(stableAccount).toMatchSnapshot(); |
| }); |
|
|
| test("Transform account balance - depository (positive stays positive)", () => { |
| expect( |
| transformAccountBalance({ |
| balance: { |
| currency: "SEK", |
| amount: "1942682.86", |
| }, |
| accountType: "depository", |
| }), |
| ).toMatchSnapshot(); |
| }); |
|
|
| test("Transform account balance - credit card with negative balance (normalized to positive)", () => { |
| |
| |
| expect( |
| transformAccountBalance({ |
| balance: { |
| currency: "EUR", |
| amount: "-1500.00", |
| }, |
| accountType: "credit", |
| }), |
| ).toEqual({ |
| currency: "EUR", |
| amount: 1500, |
| available_balance: null, |
| credit_limit: null, |
| }); |
| }); |
|
|
| test("Transform account balance - credit card with positive balance (overpayment stays positive)", () => { |
| |
| |
| expect( |
| transformAccountBalance({ |
| balance: { |
| currency: "EUR", |
| amount: "200.00", |
| }, |
| accountType: "credit", |
| }), |
| ).toEqual({ |
| currency: "EUR", |
| amount: 200, |
| available_balance: null, |
| credit_limit: null, |
| }); |
| }); |
|
|
| test("Transform account balance - credit card with zero balance", () => { |
| expect( |
| transformAccountBalance({ |
| balance: { |
| currency: "USD", |
| amount: "0.00", |
| }, |
| accountType: "credit", |
| }), |
| ).toEqual({ |
| currency: "USD", |
| amount: 0, |
| available_balance: null, |
| credit_limit: null, |
| }); |
| }); |
|
|
| test("Transform account balance - no accountType provided", () => { |
| |
| expect( |
| transformAccountBalance({ |
| balance: { |
| currency: "EUR", |
| amount: "-500.00", |
| }, |
| }), |
| ).toEqual({ |
| currency: "EUR", |
| amount: -500, |
| available_balance: null, |
| credit_limit: null, |
| }); |
| }); |
|
|
| test("Transform account balance - handles undefined balance gracefully", () => { |
| expect( |
| transformAccountBalance({ |
| balance: undefined, |
| accountType: "depository", |
| }), |
| ).toEqual({ |
| currency: "EUR", |
| amount: 0, |
| available_balance: null, |
| credit_limit: null, |
| }); |
| }); |
|
|
| test("Transform account balance - very large credit card balance", () => { |
| |
| expect( |
| transformAccountBalance({ |
| balance: { |
| currency: "USD", |
| amount: "-50000.00", |
| }, |
| accountType: "credit", |
| }), |
| ).toEqual({ |
| currency: "USD", |
| amount: 50000, |
| available_balance: null, |
| credit_limit: null, |
| }); |
| }); |
|
|
| test("Transform account balance - decimal precision maintained", () => { |
| expect( |
| transformAccountBalance({ |
| balance: { |
| currency: "EUR", |
| amount: "-1234.56", |
| }, |
| accountType: "credit", |
| }), |
| ).toEqual({ |
| currency: "EUR", |
| amount: 1234.56, |
| available_balance: null, |
| credit_limit: null, |
| }); |
| }); |
|
|
| test("Transform account balance - loan type keeps negative (if bank reports that way)", () => { |
| |
| |
| |
| expect( |
| transformAccountBalance({ |
| balance: { |
| currency: "GBP", |
| amount: "-25000.00", |
| }, |
| accountType: "loan", |
| }), |
| ).toEqual({ |
| currency: "GBP", |
| amount: -25000, |
| available_balance: null, |
| credit_limit: null, |
| }); |
| }); |
|
|
| test("Transform account balance - loan type with positive value", () => { |
| |
| expect( |
| transformAccountBalance({ |
| balance: { |
| currency: "GBP", |
| amount: "25000.00", |
| }, |
| accountType: "loan", |
| }), |
| ).toEqual({ |
| currency: "GBP", |
| amount: 25000, |
| available_balance: null, |
| credit_limit: null, |
| }); |
| }); |
|
|
| test("Transform account - extracts available_balance from balances array", () => { |
| const result = transformAccount({ |
| id: "gc_account_123", |
| created: "2024-02-23T13:29:47.314568Z", |
| last_accessed: "2024-03-06T16:34:16.782598Z", |
| iban: "DE89370400440532013000", |
| institution_id: "REVOLUT_REVOGB21", |
| status: "READY", |
| owner_name: "John Doe", |
| account: { |
| currency: "EUR", |
| iban: "DE89370400440532013000", |
| ownerName: "John Doe", |
| name: "Main Account", |
| product: "Current Account", |
| cashAccountType: "CACC", |
| resourceId: "resource_123", |
| }, |
| balance: { |
| currency: "EUR", |
| amount: "5000.00", |
| }, |
| balances: [ |
| { |
| balanceType: "interimBooked", |
| balanceAmount: { amount: "5000.00", currency: "EUR" }, |
| creditLimitIncluded: false, |
| }, |
| { |
| balanceType: "interimAvailable", |
| balanceAmount: { amount: "4800.00", currency: "EUR" }, |
| creditLimitIncluded: false, |
| }, |
| ], |
| institution: { |
| id: "REVOLUT_REVOGB21", |
| name: "Revolut", |
| bic: "REVOGB21", |
| transaction_total_days: "90", |
| countries: ["GB"], |
| logo: "https://cdn.nordigen.com/revolut.png", |
| }, |
| }); |
|
|
| expect(result.available_balance).toBe(4800); |
| expect(result.credit_limit).toBeNull(); |
| }); |
|
|
| test("Transform account - available_balance falls back to expected balance", () => { |
| const result = transformAccount({ |
| id: "gc_account_456", |
| created: "2024-02-23T13:29:47.314568Z", |
| last_accessed: "2024-03-06T16:34:16.782598Z", |
| iban: "DE89370400440532013001", |
| institution_id: "REVOLUT_REVOGB21", |
| status: "READY", |
| owner_name: "Jane Doe", |
| account: { |
| currency: "EUR", |
| iban: "DE89370400440532013001", |
| ownerName: "Jane Doe", |
| name: "Savings", |
| product: "Savings Account", |
| cashAccountType: "SVGS", |
| resourceId: "resource_456", |
| }, |
| balance: { |
| currency: "EUR", |
| amount: "10000.00", |
| }, |
| balances: [ |
| { |
| balanceType: "expected", |
| balanceAmount: { amount: "10000.00", currency: "EUR" }, |
| creditLimitIncluded: false, |
| }, |
| ], |
| institution: { |
| id: "REVOLUT_REVOGB21", |
| name: "Revolut", |
| bic: "REVOGB21", |
| transaction_total_days: "90", |
| countries: ["GB"], |
| logo: "https://cdn.nordigen.com/revolut.png", |
| }, |
| }); |
|
|
| expect(result.available_balance).toBe(10000); |
| }); |
|
|
| test("Transform account - handles empty balances array", () => { |
| const result = transformAccount({ |
| id: "gc_account_789", |
| created: "2024-02-23T13:29:47.314568Z", |
| last_accessed: "2024-03-06T16:34:16.782598Z", |
| iban: "GB82WEST12345698765432", |
| institution_id: "MONZO_MONZGB21", |
| status: "READY", |
| owner_name: "Test User", |
| account: { |
| currency: "GBP", |
| iban: "GB82WEST12345698765432", |
| ownerName: "Test User", |
| name: "Current", |
| product: "Current Account", |
| cashAccountType: "CACC", |
| resourceId: "resource_789", |
| }, |
| balance: { |
| currency: "GBP", |
| amount: "1000.00", |
| }, |
| balances: [], |
| institution: { |
| id: "MONZO_MONZGB21", |
| name: "Monzo", |
| bic: "MONZGB21", |
| transaction_total_days: "90", |
| countries: ["GB"], |
| logo: "https://cdn.nordigen.com/monzo.png", |
| }, |
| }); |
|
|
| expect(result.available_balance).toBeNull(); |
| expect(result.credit_limit).toBeNull(); |
| }); |
|
|