/ packages / frontend / src / components / RelayClient_test.tsx
RelayClient_test.tsx
 1  import "../happyDomSetup.ts";
 2  import { act, cleanup, render, screen, waitFor } from "@testing-library/react";
 3  import { expect } from "@std/expect";
 4  import { userEvent } from "@testing-library/user-event";
 5  import { discoverRelay, IRelayEndpoint } from "@massmarket/client";
 6  import { random256BigInt } from "@massmarket/utils";
 7  import { createClient, publicActions, walletActions, webSocket } from "viem";
 8  import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
 9  import { hardhat } from "viem/chains";
10  import RelayClientTestPage from "./RelayClientTestPage.tsx";
11  
12  // Create a mock wallet client and account
13  const shopId = random256BigInt();
14  const client = createClient({
15    chain: hardhat,
16    transport: webSocket("ws://localhost:8545"),
17  }).extend(walletActions).extend(publicActions);
18  
19  const pk = generatePrivateKey();
20  const kc = privateKeyToAccount(pk);
21  
22  Deno.test("RelayClientTester component connects to relay", {
23    sanitizeResources: false,
24    sanitizeOps: false,
25  }, async (t) => {
26    const relayEndpoint = await discoverRelay("ws://localhost:4444/v4");
27    const user = userEvent.setup();
28  
29    await t.step("renders and connects to relay", async () => {
30      const { unmount } = render(
31        <RelayClientTestPage
32          relayEndpoint={relayEndpoint}
33          walletClient={client}
34          keycard={kc}
35          shopId={shopId}
36        />,
37      );
38  
39      // Check initial rendering
40      screen.getByTestId("relay-client-tester");
41  
42      // Wait for connection to be established
43      await waitFor(() => {
44        const status = screen.getByTestId("connection-status");
45        expect(status.textContent).toContain("connected");
46        const lastPingReceived = screen.getByTestId("stats-last-ping-received");
47        expect(lastPingReceived.textContent).toContain("second");
48        // make sure to align this timeout with PING_INTERVAL. Otherwise, the test will fail.
49      }, { timeout: 10000 });
50  
51      // Test disconnect functionality
52      await act(async () => {
53        const disconnectButton = screen.getByTestId("disconnect-button");
54        await user.click(disconnectButton);
55      });
56  
57      // Verify disconnection
58      await waitFor(() => {
59        const status = screen.getByTestId("connection-status");
60        expect(status.textContent).toContain("disconnected");
61      });
62  
63      unmount();
64      cleanup();
65    });
66  
67    await t.step("handles connection errors", async () => {
68      const relayEndpoint: IRelayEndpoint = {
69        url: new URL("ws://localhost:57192/v99999"),
70        tokenId:
71          "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
72      };
73      const { unmount } = render(
74        <RelayClientTestPage
75          relayEndpoint={relayEndpoint}
76          walletClient={client}
77          keycard={kc}
78          shopId={shopId}
79        />,
80      );
81  
82      // Check that error is displayed
83      await waitFor(() => {
84        const error = screen.getByTestId("connection-error");
85        expect(error.textContent).toContain(
86          "NetworkError: failed to connect to WebSocket",
87        );
88        const lastPingReceived = screen.getByTestId("stats-last-ping-received");
89        expect(lastPingReceived.textContent).toContain("Never");
90      });
91  
92      unmount();
93      cleanup();
94    });
95  });