diff --git a/app/dashboard/transaction-history/page.tsx b/app/dashboard/transaction-history/page.tsx index 104b5d3c..e9dc7ca9 100644 --- a/app/dashboard/transaction-history/page.tsx +++ b/app/dashboard/transaction-history/page.tsx @@ -19,10 +19,7 @@ import type { Transaction, TransactionStatus, } from "@/components/Dashboard/TransactionHistoryItem"; -import { startOfDay, subDays, isSameDay, endOfDay, isBefore, isAfter } from "date-fns"; -// @ts-ignore -import { FixedSizeList } from "react-window"; -const List = FixedSizeList as any; +import { FixedSizeList as List } from "react-window"; type Direction = "all" | "sent" | "received"; @@ -38,6 +35,21 @@ export function getGroupKey( return "earlier"; } +export interface VirtualRowProps { + index: number; + style: React.CSSProperties; + data: Transaction[]; +} + +export const TransactionVirtualRow = ({ index, style, data }: VirtualRowProps) => { + const tx = data[index]; + return ( +
+ +
+ ); +}; + const TransactionHistoryPage = () => { useSeo({ title: "Transaction History - RemitWise", diff --git a/tests/unit/dashboard/transaction-history-virtualization.test.tsx b/tests/unit/dashboard/transaction-history-virtualization.test.tsx new file mode 100644 index 00000000..6b0175b5 --- /dev/null +++ b/tests/unit/dashboard/transaction-history-virtualization.test.tsx @@ -0,0 +1,54 @@ +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/react"; +import { FixedSizeList } from "react-window"; +import { + TransactionVirtualRow, +} from "@/app/dashboard/transaction-history/page"; +import type { Transaction } from "@/components/Dashboard/TransactionHistoryItem"; + +const ROW_COUNT = 250; + +function buildTransactions(count: number): Transaction[] { + return Array.from({ length: count }, (_, i) => ({ + id: `tx-${i}`, + hash: `hash-${i}`, + type: "Send Money" as const, + amount: 100 + i, + currency: "USDC", + counterpartyName: `Recipient ${i}`, + counterpartyLabel: "To", + date: new Date(2026, 0, 1 + (i % 28)).toISOString(), + fee: 1.5, + status: "Completed" as const, + })); +} + +describe("transaction history virtualization", () => { + it("renders a 250-row list via react-window without rendering every row into the DOM", () => { + const transactions = buildTransactions(ROW_COUNT); + + render( +
+ + {TransactionVirtualRow} + +
+ ); + + // Only rows within (or just past) the visible window should be mounted -- + // proof the list is actually virtualized, not just rendered in a + // fixed-height scroll container with all 250 rows present. + expect(screen.getByText("Recipient 0")).toBeInTheDocument(); + expect(screen.queryByText(`Recipient ${ROW_COUNT - 1}`)).not.toBeInTheDocument(); + + const renderedRows = screen.getAllByText(/^Recipient \d+$/); + expect(renderedRows.length).toBeGreaterThan(0); + expect(renderedRows.length).toBeLessThan(ROW_COUNT); + }); +});