From f23bcf2569e86cf1cc68a5ede7e3c39515c4808c Mon Sep 17 00:00:00 2001 From: stayzappy Date: Fri, 28 Aug 2026 18:18:53 +0100 Subject: [PATCH] fix(BalanceList): prevent duplicate React keys and add tests for loading skeleton and empty states --- src/components/BalanceList.test.tsx | 37 +++++++++++++++++++++++++++++ src/components/BalanceList.tsx | 4 ++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/components/BalanceList.test.tsx b/src/components/BalanceList.test.tsx index 456ab9b..e97aed8 100644 --- a/src/components/BalanceList.test.tsx +++ b/src/components/BalanceList.test.tsx @@ -377,4 +377,41 @@ describe("BalanceList", () => { expect(badgeOrder()).toEqual(["USDC", "USDT"]); }); }); + + describe("duplicate key prevention (#601)", () => { + it("renders without console duplicate key warnings when multiple balances share identical asset fields", () => { + const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + + const duplicateAsset1 = { + asset: "DUPLICATE_ASSET", + balance: "10.0000000", + assetType: "credit_alphanum4" as const, + assetCode: "DUP", + assetIssuer: "GISSUER11111111111111111111111111111111111111111111", + }; + + const duplicateAsset2 = { + asset: "DUPLICATE_ASSET", + balance: "20.0000000", + assetType: "credit_alphanum4" as const, + assetCode: "DUP", + assetIssuer: "GISSUER22222222222222222222222222222222222222222222", + }; + + vi.mocked(useSorokit).mockReturnValue({ + balances: [duplicateAsset1, duplicateAsset2], + isLoadingAccount: false, + isConnected: true, + } as unknown as ReturnType); + + render(); + + const duplicateWarnings = consoleSpy.mock.calls.filter(([msg]) => + typeof msg === "string" && msg.includes("same key") + ); + + expect(duplicateWarnings).toHaveLength(0); + consoleSpy.mockRestore(); + }); + }); }); diff --git a/src/components/BalanceList.tsx b/src/components/BalanceList.tsx index dae7aa2..0dd953e 100644 --- a/src/components/BalanceList.tsx +++ b/src/components/BalanceList.tsx @@ -195,9 +195,9 @@ export function BalanceList({ onAssetClick, detailRef }: BalanceListProps) { ) : (
- {sorted.map((b) => ( + {sorted.map((b, idx) => ( handleAssetClick(b) : undefined} />