Midday / apps /engine /src /providers /plaid /transform.test.ts
Jules
Final deployment with all fixes and verified content
c09f67c
import { expect, test } from "bun:test";
import {
AccountSubtype,
AccountType,
CounterpartyType,
TransactionCode,
TransactionPaymentChannelEnum,
TransactionTransactionTypeEnum,
} from "plaid";
import {
transformAccount,
transformAccountBalance,
transformTransaction,
} from "./transform";
test("Transform pending transaction", () => {
expect(
transformTransaction({
accountType: "credit",
transaction: {
account_id: "AG7EkLW7DRSVaN8Z75jMT1DJN51QpWc9LKB7w",
account_owner: null,
amount: 5.4,
authorized_date: "2024-02-23",
authorized_datetime: null,
category: ["Travel", "Taxi"],
category_id: "22016000",
check_number: null,
counterparties: [
{
confidence_level: "VERY_HIGH",
entity_id: "eyg8o776k0QmNgVpAmaQj4WgzW9Qzo6O51gdd",
logo_url: "https://plaid-merchant-logos.plaid.com/uber_1060.png",
name: "Uber",
type: CounterpartyType.Merchant,
website: "uber.com",
},
],
date: "2024-02-24",
datetime: null,
iso_currency_code: "CAD",
location: {
address: null,
city: null,
country: null,
lat: null,
lon: null,
postal_code: null,
region: null,
store_number: null,
},
logo_url: "https://plaid-merchant-logos.plaid.com/uber_1060.png",
merchant_entity_id: "eyg8o776k0QmNgVpAmaQj4WgzW9Qzo6O51gdd",
merchant_name: "Uber",
name: "Uber 063015 SF**POOL**",
payment_channel: TransactionPaymentChannelEnum.Online,
payment_meta: {
by_order_of: null,
payee: null,
payer: null,
payment_method: null,
payment_processor: null,
ppd_id: null,
reason: null,
reference_number: null,
},
pending: true,
pending_transaction_id: null,
personal_finance_category: {
confidence_level: "VERY_HIGH",
detailed: "TRANSPORTATION_TAXIS_AND_RIDE_SHARES",
primary: "TRANSPORTATION",
},
personal_finance_category_icon_url:
"https://plaid-category-icons.plaid.com/PFC_TRANSPORTATION.png",
transaction_code: null,
transaction_id: "NxkDjlyk45cQoDm5PEqJuKJaw6qrj9cy89zBA",
transaction_type: TransactionTransactionTypeEnum.Special,
unofficial_currency_code: null,
website: "uber.com",
},
}),
).toMatchSnapshot();
});
test("Transform income transaction", () => {
expect(
transformTransaction({
accountType: "depository",
transaction: {
account_id: "AG7EkLW7DRSVaN8Z75jMT1DJN51QpWc9LKB7w",
account_owner: null,
amount: 1500,
authorized_date: "2024-02-22",
authorized_datetime: null,
category: ["Travel", "Airlines and Aviation Services"],
category_id: "22001000",
check_number: null,
counterparties: [
{
confidence_level: "VERY_HIGH",
entity_id: "NKDjqyAdQQzpyeD8qpLnX0D6yvLe2KYKYYzQ4",
logo_url:
"https://plaid-merchant-logos.plaid.com/united_airlines_1065.png",
name: "United Airlines",
type: CounterpartyType.Merchant,
website: "united.com",
},
],
date: "2024-02-22",
datetime: null,
iso_currency_code: "CAD",
location: {
address: null,
city: null,
country: null,
lat: null,
lon: null,
postal_code: null,
region: null,
store_number: null,
},
logo_url:
"https://plaid-merchant-logos.plaid.com/united_airlines_1065.png",
merchant_entity_id: "NKDjqyAdQQzpyeD8qpLnX0D6yvLe2KYKYYzQ4",
merchant_name: "United Airlines",
name: "United Airlines",
payment_channel: TransactionPaymentChannelEnum.InStore,
payment_meta: {
by_order_of: null,
payee: null,
payer: null,
payment_method: null,
payment_processor: null,
ppd_id: null,
reason: null,
reference_number: null,
},
pending: false,
pending_transaction_id: null,
personal_finance_category: {
confidence_level: "VERY_HIGH",
detailed: "TRAVEL_FLIGHTS",
primary: "TRAVEL",
},
personal_finance_category_icon_url:
"https://plaid-category-icons.plaid.com/PFC_TRAVEL.png",
transaction_code: null,
transaction_id: "5QKmMdaKWgtzkvKEPmqriLZR1mV3kMF5X9EeX",
transaction_type: TransactionTransactionTypeEnum.Special,
unofficial_currency_code: null,
website: "united.com",
},
}),
).toMatchSnapshot();
});
test("Transform type transfer", () => {
expect(
transformTransaction({
accountType: "credit",
transaction: {
account_id: "AG7EkLW7DRSVaN8Z75jMT1DJN51QpWc9LKB7w",
account_owner: null,
amount: 31.53,
authorized_date: "2024-02-23",
authorized_datetime: null,
category: ["Travel", "Taxi"],
category_id: "22016000",
check_number: null,
counterparties: [
{
confidence_level: "VERY_HIGH",
entity_id: "eyg8o776k0QmNgVpAmaQj4WgzW9Qzo6O51gdd",
logo_url: "https://plaid-merchant-logos.plaid.com/uber_1060.png",
name: "Uber",
type: CounterpartyType.Merchant,
website: "uber.com",
},
],
date: "2024-02-24",
datetime: null,
iso_currency_code: "CAD",
location: {
address: null,
city: null,
country: null,
lat: null,
lon: null,
postal_code: null,
region: null,
store_number: null,
},
logo_url: "https://plaid-merchant-logos.plaid.com/uber_1060.png",
merchant_entity_id: "eyg8o776k0QmNgVpAmaQj4WgzW9Qzo6O51gdd",
merchant_name: "Uber",
name: "Uber 063015 SF**POOL**",
payment_channel: TransactionPaymentChannelEnum.Online,
payment_meta: {
by_order_of: null,
payee: null,
payer: null,
payment_method: null,
payment_processor: null,
ppd_id: null,
reason: null,
reference_number: null,
},
pending: true,
pending_transaction_id: null,
personal_finance_category: {
confidence_level: "VERY_HIGH",
detailed: "TRANSPORTATION_TAXIS_AND_RIDE_SHARES",
primary: "TRANSPORTATION",
},
personal_finance_category_icon_url:
"https://plaid-category-icons.plaid.com/PFC_TRANSPORTATION.png",
transaction_code: TransactionCode.Transfer,
transaction_id: "NxkDjlyk45cQoDm5PEqJuKJaw6qrj9cy89zBA",
transaction_type: TransactionTransactionTypeEnum.Special,
unofficial_currency_code: null,
website: "uber.com",
},
}),
).toMatchSnapshot();
});
test("Transform accounts", () => {
expect(
transformAccount({
account_id: "kKZWQnoZVqcBeN71qdyoh8mVoErgb7tL7gmBL",
balances: {
available: 56302.06,
current: 56302.06,
iso_currency_code: "CAD",
limit: null,
unofficial_currency_code: null,
},
mask: "8888",
name: "Plaid Mortgage",
official_name: null,
subtype: AccountSubtype.Mortgage,
type: AccountType.Loan,
institution: {
id: "ins_100546",
name: "American Funds Retirement Solutions",
logo: null,
},
}),
).toMatchSnapshot();
});
test("Transform account balance - depository uses available", () => {
expect(
transformAccountBalance({
balances: {
available: 2000,
current: 1500,
iso_currency_code: "USD",
limit: null,
unofficial_currency_code: null,
},
accountType: "depository",
}),
).toMatchSnapshot();
});
test("Transform account balance - credit uses current (amount owed)", () => {
// Credit card with $5000 limit, $1000 owed
// available = $4000 (available credit), current = $1000 (debt)
// We should show $1000 (current), not $4000 (available)
expect(
transformAccountBalance({
balances: {
available: 4000,
current: 1000,
iso_currency_code: "USD",
limit: 5000,
unofficial_currency_code: null,
},
accountType: "credit",
}),
).toMatchSnapshot();
});
test("Transform account balance - depository falls back to current when available is null", () => {
// Some accounts may not have available balance
expect(
transformAccountBalance({
balances: {
available: null,
current: 5000,
iso_currency_code: "USD",
limit: null,
unofficial_currency_code: null,
},
accountType: "depository",
}),
).toEqual({
currency: "USD",
amount: 5000,
available_balance: null,
credit_limit: null,
});
});
test("Transform account balance - handles null balances gracefully", () => {
expect(
transformAccountBalance({
balances: {
available: null,
current: null,
iso_currency_code: "USD",
limit: null,
unofficial_currency_code: null,
},
accountType: "depository",
}),
).toEqual({
currency: "USD",
amount: 0,
available_balance: null,
credit_limit: null,
});
});
test("Transform account balance - credit card overpayment (negative current)", () => {
// If someone overpays their credit card, Plaid shows negative current
// This means they have a credit balance (bank owes them money)
expect(
transformAccountBalance({
balances: {
available: 5500, // Available credit PLUS overpayment
current: -500, // Negative = overpaid by $500
iso_currency_code: "USD",
limit: 5000,
unofficial_currency_code: null,
},
accountType: "credit",
}),
).toEqual({
currency: "USD",
amount: -500, // Shows as negative (credit in customer's favor)
available_balance: 5500,
credit_limit: 5000,
});
});
test("Transform account balance - loan account uses current", () => {
// Loan accounts don't have available balance
expect(
transformAccountBalance({
balances: {
available: null,
current: 75000, // Outstanding loan balance
iso_currency_code: "USD",
limit: null,
unofficial_currency_code: null,
},
accountType: "loan",
}),
).toEqual({
currency: "USD",
amount: 75000,
available_balance: null,
credit_limit: null,
});
});
test("Transform credit card payment - should be credit-card-payment not income", () => {
expect(
transformTransaction({
accountType: "credit",
transaction: {
account_id: "AG7EkLW7DRSVaN8Z75jMT1DJN51QpWc9LKB7w",
account_owner: null,
amount: -500, // Negative in Plaid = money IN to credit card
authorized_date: "2024-02-23",
authorized_datetime: null,
category: ["Payment", "Credit Card"],
category_id: "16001000",
check_number: null,
counterparties: [],
date: "2024-02-24",
datetime: null,
iso_currency_code: "USD",
location: {
address: null,
city: null,
country: null,
lat: null,
lon: null,
postal_code: null,
region: null,
store_number: null,
},
logo_url: null,
merchant_entity_id: null,
merchant_name: null,
name: "Credit Card Payment",
payment_channel: TransactionPaymentChannelEnum.Other,
payment_meta: {
by_order_of: null,
payee: null,
payer: null,
payment_method: null,
payment_processor: null,
ppd_id: null,
reason: null,
reference_number: null,
},
pending: false,
pending_transaction_id: null,
personal_finance_category: {
confidence_level: "VERY_HIGH",
detailed: "LOAN_PAYMENTS_CREDIT_CARD_PAYMENT",
primary: "LOAN_PAYMENTS",
},
personal_finance_category_icon_url: undefined,
transaction_code: TransactionCode.BillPayment,
transaction_id: "payment123",
transaction_type: TransactionTransactionTypeEnum.Special,
unofficial_currency_code: null,
website: null,
},
}),
).toMatchSnapshot();
});
test("Transform credit card refund - should have no category", () => {
expect(
transformTransaction({
accountType: "credit",
transaction: {
account_id: "AG7EkLW7DRSVaN8Z75jMT1DJN51QpWc9LKB7w",
account_owner: null,
amount: -50, // Negative in Plaid = money IN (refund)
authorized_date: "2024-02-23",
authorized_datetime: null,
category: ["Shops", "Computers and Electronics"],
category_id: "19013000",
check_number: null,
counterparties: [
{
confidence_level: "VERY_HIGH",
entity_id: "amazon123",
logo_url: "https://plaid-merchant-logos.plaid.com/amazon.png",
name: "Amazon",
type: CounterpartyType.Merchant,
website: "amazon.com",
},
],
date: "2024-02-24",
datetime: null,
iso_currency_code: "USD",
location: {
address: null,
city: null,
country: null,
lat: null,
lon: null,
postal_code: null,
region: null,
store_number: null,
},
logo_url: "https://plaid-merchant-logos.plaid.com/amazon.png",
merchant_entity_id: "amazon123",
merchant_name: "Amazon",
name: "Amazon Refund",
payment_channel: TransactionPaymentChannelEnum.Online,
payment_meta: {
by_order_of: null,
payee: null,
payer: null,
payment_method: null,
payment_processor: null,
ppd_id: null,
reason: null,
reference_number: null,
},
pending: false,
pending_transaction_id: null,
personal_finance_category: {
confidence_level: "VERY_HIGH",
detailed: "GENERAL_MERCHANDISE_ELECTRONICS",
primary: "GENERAL_MERCHANDISE",
},
personal_finance_category_icon_url: undefined,
transaction_code: null,
transaction_id: "refund123",
transaction_type: TransactionTransactionTypeEnum.Special,
unofficial_currency_code: null,
website: "amazon.com",
},
}),
).toMatchSnapshot();
});
test("Transform account - credit card with available_balance and credit_limit", () => {
const result = transformAccount({
account_id: "credit_123",
balances: {
available: 4000, // Available credit
current: 1000, // Amount owed
iso_currency_code: "USD",
limit: 5000, // Credit limit
unofficial_currency_code: null,
},
mask: "1234",
name: "My Credit Card",
official_name: "Chase Sapphire",
subtype: AccountSubtype.CreditCard,
type: AccountType.Credit,
institution: {
id: "ins_chase",
name: "Chase",
logo: null,
},
});
expect(result.available_balance).toBe(4000);
expect(result.credit_limit).toBe(5000);
expect(result.balance.amount).toBe(1000); // Current balance (amount owed)
});
test("Transform account - depository with available_balance, no credit_limit", () => {
const result = transformAccount({
account_id: "checking_123",
balances: {
available: 5000,
current: 5200, // Includes pending
iso_currency_code: "USD",
limit: null,
unofficial_currency_code: null,
},
mask: "5678",
name: "My Checking",
official_name: "Chase Checking",
subtype: AccountSubtype.Checking,
type: AccountType.Depository,
institution: {
id: "ins_chase",
name: "Chase",
logo: null,
},
});
expect(result.available_balance).toBe(5000);
expect(result.credit_limit).toBeNull();
expect(result.balance.amount).toBe(5000); // Depository uses available
});
test("Transform account - handles null balances gracefully", () => {
const result = transformAccount({
account_id: "savings_123",
balances: {
available: null,
current: 10000,
iso_currency_code: "USD",
limit: null,
unofficial_currency_code: null,
},
mask: "9999",
name: "My Savings",
official_name: null,
subtype: AccountSubtype.Savings,
type: AccountType.Depository,
institution: {
id: "ins_boa",
name: "Bank of America",
logo: null,
},
});
expect(result.available_balance).toBeNull();
expect(result.credit_limit).toBeNull();
});