Skip to content

Commit 570ea83

Browse files
test: Implement tests for Stellar Wave component enhancements (#642)
1 parent 71e0294 commit 570ea83

4 files changed

Lines changed: 725 additions & 0 deletions

File tree

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
import React from "react";
2+
import { render, screen, waitFor } from "@testing-library/react";
3+
import userEvent from "@testing-library/user-event";
4+
import { useRouter } from "next/navigation";
5+
import PayPreviewButton from "@/components/PayPreviewButton";
6+
7+
vi.mock("next/navigation");
8+
vi.mock("@/lib/freighter");
9+
vi.mock("@/hooks/useNetworkFeeBreakdown", () => ({
10+
useNetworkFeeBreakdown: vi.fn(),
11+
}));
12+
13+
const mockPush = vi.fn();
14+
(useRouter as any).mockReturnValue({
15+
push: mockPush,
16+
});
17+
18+
import { getFreighterPublicKey } from "@/lib/freighter";
19+
import { useNetworkFeeBreakdown } from "@/hooks/useNetworkFeeBreakdown";
20+
21+
describe("PayPreviewButton", () => {
22+
beforeEach(() => {
23+
vi.clearAllMocks();
24+
mockPush.mockClear();
25+
});
26+
27+
test("renders pay button when invoice is Pending", () => {
28+
vi.mocked(getFreighterPublicKey).mockResolvedValue("GKEY123");
29+
render(
30+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
31+
);
32+
expect(screen.getByRole("button", { name: /Pay This Invoice/ })).toBeInTheDocument();
33+
});
34+
35+
test("shows message when invoice is not Pending", () => {
36+
render(
37+
<PayPreviewButton invoiceId="inv-1" status="Released" />
38+
);
39+
expect(screen.getByText(/This invoice is released/i)).toBeInTheDocument();
40+
});
41+
42+
test("navigates to pay page when button clicked and wallet connected", async () => {
43+
const user = userEvent.setup();
44+
vi.mocked(getFreighterPublicKey).mockResolvedValue("GKEY123");
45+
render(
46+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
47+
);
48+
49+
const button = screen.getByRole("button", { name: /Pay This Invoice/ });
50+
await user.click(button);
51+
await waitFor(() => {
52+
expect(mockPush).toHaveBeenCalledWith("/pay/inv-1");
53+
});
54+
});
55+
56+
test("prompts wallet connection when not connected", async () => {
57+
const user = userEvent.setup();
58+
vi.mocked(getFreighterPublicKey)
59+
.mockRejectedValueOnce(new Error("No wallet"))
60+
.mockResolvedValueOnce("GKEY123");
61+
62+
render(
63+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
64+
);
65+
66+
expect(screen.getByText(/Requires Freighter wallet extension/i)).toBeInTheDocument();
67+
68+
const button = screen.getByRole("button", { name: /Pay This Invoice/ });
69+
await user.click(button);
70+
71+
await waitFor(() => {
72+
expect(screen.getByText(/Connecting wallet/i)).toBeInTheDocument();
73+
});
74+
});
75+
76+
test("displays error when wallet connection fails", async () => {
77+
const user = userEvent.setup();
78+
vi.mocked(getFreighterPublicKey).mockRejectedValue(
79+
new Error("Connection failed")
80+
);
81+
82+
render(
83+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
84+
);
85+
86+
const button = screen.getByRole("button", { name: /Pay This Invoice/ });
87+
await user.click(button);
88+
89+
await waitFor(() => {
90+
expect(screen.getByRole("alert")).toHaveTextContent(
91+
/Could not connect wallet/i
92+
);
93+
});
94+
});
95+
96+
test("displays estimated network fee when available", async () => {
97+
vi.mocked(getFreighterPublicKey).mockResolvedValue("GKEY123");
98+
vi.mocked(useNetworkFeeBreakdown).mockReturnValue({
99+
fee: 100n,
100+
loading: false,
101+
error: null,
102+
});
103+
104+
render(
105+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
106+
);
107+
108+
await waitFor(() => {
109+
expect(screen.getByText(/Est\. fee:/i)).toBeInTheDocument();
110+
});
111+
});
112+
113+
test("shows skeleton loader while fee is loading", async () => {
114+
vi.mocked(getFreighterPublicKey).mockResolvedValue("GKEY123");
115+
vi.mocked(useNetworkFeeBreakdown).mockReturnValue({
116+
fee: null,
117+
loading: true,
118+
error: null,
119+
});
120+
121+
const { container } = render(
122+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
123+
);
124+
125+
await waitFor(() => {
126+
const skeleton = container.querySelector("[data-testid='fee-skeleton']");
127+
expect(skeleton).toBeInTheDocument();
128+
});
129+
});
130+
131+
test("hides fee display when fetch fails", async () => {
132+
vi.mocked(getFreighterPublicKey).mockResolvedValue("GKEY123");
133+
vi.mocked(useNetworkFeeBreakdown).mockReturnValue({
134+
fee: null,
135+
loading: false,
136+
error: new Error("Network error"),
137+
});
138+
139+
render(
140+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
141+
);
142+
143+
await waitFor(() => {
144+
expect(screen.queryByText(/Est\. fee:/i)).not.toBeInTheDocument();
145+
});
146+
});
147+
148+
test("formats fee with XLM and USD equivalent", async () => {
149+
vi.mocked(getFreighterPublicKey).mockResolvedValue("GKEY123");
150+
vi.mocked(useNetworkFeeBreakdown).mockReturnValue({
151+
fee: 100n,
152+
loading: false,
153+
error: null,
154+
});
155+
156+
render(
157+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
158+
);
159+
160+
await waitFor(() => {
161+
expect(screen.getByText(/0\.00001 XLM \$0\.00/)).toBeInTheDocument();
162+
});
163+
});
164+
165+
test("button shows connecting state during wallet connection", async () => {
166+
const user = userEvent.setup();
167+
vi.mocked(getFreighterPublicKey).mockImplementationOnce(
168+
() => new Promise(resolve => setTimeout(() => resolve("GKEY123"), 100))
169+
);
170+
171+
render(
172+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
173+
);
174+
175+
const button = screen.getByRole("button", { name: /Pay This Invoice/ });
176+
await user.click(button);
177+
178+
await waitFor(() => {
179+
expect(screen.getByRole("button", { name: /Connecting wallet/i })).toBeInTheDocument();
180+
});
181+
});
182+
183+
test("calls getFreighterPublicKey on mount", async () => {
184+
vi.mocked(getFreighterPublicKey).mockResolvedValue("GKEY123");
185+
186+
render(
187+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
188+
);
189+
190+
await waitFor(() => {
191+
expect(getFreighterPublicKey).toHaveBeenCalled();
192+
});
193+
});
194+
195+
test("does not show Freighter requirement message when wallet is connected", async () => {
196+
vi.mocked(getFreighterPublicKey).mockResolvedValue("GKEY123");
197+
198+
render(
199+
<PayPreviewButton invoiceId="inv-1" status="Pending" />
200+
);
201+
202+
await waitFor(() => {
203+
expect(
204+
screen.queryByText(/Requires Freighter wallet extension/i)
205+
).not.toBeInTheDocument();
206+
});
207+
});
208+
});

0 commit comments

Comments
 (0)