mirror of
https://github.com/luxfi/bank.git
synced 2026-10-30 17:02:07 +00:00
Second polish pass over the dash from the visual sweep — the remaining screens now carry the data a real bank shows and use the space they have. Backend: - Receiving coordinates are currency-correct. The "US IBAN" was wrong — the US issues no IBANs. receivingFor derives bank name + ABA routing + account number + SWIFT + bank address for US accounts, IBAN + BIC for IBAN markets, deterministic per account, exposed as account.receiving. account.iban is now empty for US. Dropped the redundant stored iban metadata. - Card purchases are their own transaction type (`card`) — a debit like a payment but on the card rail, so they carry no wire fee and don't route to forex (both fall through cleanly). The Cards screen lists these specifically. Dash: - Accounts + Send render the full receiving coordinates (one Coordinates component, shape chosen by currency), each line copyable — enough to actually receive a wire. - Cards: spend-limits panel (month-to-date debits vs the account ceiling) and a card-transaction list, filling the desktop dead space; one column on mobile. - Exchange: the pair is priced on arrival (rate is a property of the pair, not the amount) and recent conversions sit beside the converter. - Activity: a conversion reads as one movement (both legs on the line) instead of two adjacent rows; filtering still splits the legs. - Wallet: copy button on the full deposit address. Landing hero balance now equals the demo account, tile for tile. Named nav landmarks; EMV chip detail. SDK 1.3.4: Account.receiving typed. e2e up to 29 green (added activity + cards specs, receiving/landing/exchange/wallet/shell coverage). Backend go test/vet/staticcheck/deadcode clean. Co-authored-by: Hanzo Dev <[email protected]>
46 lines
1.9 KiB
TypeScript
46 lines
1.9 KiB
TypeScript
import { test, expect, type Page } from '@playwright/test'
|
|
import { signIn, shot } from './demo'
|
|
|
|
const box = async (page: Page, heading: string) => {
|
|
const section = page.locator('section').filter({ has: page.getByRole('heading', { name: heading }) })
|
|
return (await section.boundingBox())!
|
|
}
|
|
|
|
test('at desktop width the card sits beside its limits and its spending', async ({ page }) => {
|
|
await page.setViewportSize({ width: 1280, height: 900 })
|
|
await signIn(page)
|
|
await page.goto('/app/cards')
|
|
|
|
await expect(page.getByRole('heading', { name: 'Spend limits' })).toBeVisible()
|
|
await expect(page.getByRole('heading', { name: 'Card transactions' })).toBeVisible()
|
|
await expect(page.getByText('Spent this month')).toBeVisible()
|
|
await expect(page.getByText(/^of \$[\d,]+\.\d{2}$/)).toBeVisible()
|
|
await expect(page.getByText('Daily limit')).toBeVisible()
|
|
|
|
// Payments made on the account show up as the card's spending.
|
|
const spend = page.locator('.card > div').filter({ hasText: 'Card — Apple Store' })
|
|
await expect(spend.first()).toBeVisible()
|
|
|
|
// The right-hand column starts to the right of the card face, on the same
|
|
// band of the page — that is the dead space being used, not a taller stack.
|
|
const face = (await page.locator('.card-face').first().boundingBox())!
|
|
const limits = await box(page, 'Spend limits')
|
|
expect(limits.x).toBeGreaterThan(face.x + face.width)
|
|
expect(limits.y).toBeLessThan(face.y + face.height)
|
|
|
|
await shot(page, 'cards-desktop')
|
|
})
|
|
|
|
test('on mobile the card and its panels stack in one column', async ({ page }) => {
|
|
await page.setViewportSize({ width: 390, height: 844 })
|
|
await signIn(page)
|
|
await page.goto('/app/cards')
|
|
|
|
const face = (await page.locator('.card-face').first().boundingBox())!
|
|
const limits = await box(page, 'Spend limits')
|
|
expect(limits.y).toBeGreaterThan(face.y + face.height)
|
|
expect(limits.x).toBeLessThan(face.x + 8)
|
|
|
|
await shot(page, 'cards-mobile')
|
|
})
|