From 61837403fde5b2f6413dd1caf48da95c2ecf7d00 Mon Sep 17 00:00:00 2001 From: Jeesun Kim Date: Mon, 8 Apr 2024 12:20:24 -0700 Subject: [PATCH] hide fund account and update tests --- src/app/(sidebar)/account/create/page.tsx | 20 ++-- src/app/(sidebar)/account/fund/page.tsx | 14 +++ src/app/(sidebar)/account/layout.tsx | 53 ++++++--- .../layout/LayoutSidebarContent.tsx | 1 + src/hooks/useIsTestingNetwork.ts | 7 ++ tests/createAccountPage.test.ts | 6 +- tests/createMuxedAccountPage.test.ts | 11 +- tests/fundAccountPage.test.ts | 104 ++++++++++++++++-- 8 files changed, 176 insertions(+), 40 deletions(-) create mode 100644 src/hooks/useIsTestingNetwork.ts diff --git a/src/app/(sidebar)/account/create/page.tsx b/src/app/(sidebar)/account/create/page.tsx index 6ba580e2..f2686ada 100644 --- a/src/app/(sidebar)/account/create/page.tsx +++ b/src/app/(sidebar)/account/create/page.tsx @@ -5,6 +5,7 @@ import { useRouter } from "next/navigation"; import { Card, Text, Button } from "@stellar/design-system"; import { Keypair } from "@stellar/stellar-sdk"; +import { useIsTestingNetwork } from "@/hooks/useIsTestingNetwork"; import { Routes } from "@/constants/routes"; import { useStore } from "@/store/useStore"; import { GenerateKeypair } from "@/components/GenerateKeypair"; @@ -17,6 +18,8 @@ export default function CreateAccount() { const router = useRouter(); const [secretKey, setSecretKey] = useState(""); + const IS_TESTING_NETWORK = useIsTestingNetwork(); + const generateKeypair = () => { const keypair = Keypair.random(); @@ -43,14 +46,15 @@ export default function CreateAccount() { - - + {IS_TESTING_NETWORK ? ( + + ) : null} diff --git a/src/app/(sidebar)/account/fund/page.tsx b/src/app/(sidebar)/account/fund/page.tsx index d9bfeb74..e2c38715 100644 --- a/src/app/(sidebar)/account/fund/page.tsx +++ b/src/app/(sidebar)/account/fund/page.tsx @@ -2,8 +2,11 @@ import { useEffect, useState } from "react"; import { Alert, Card, Input, Text, Button } from "@stellar/design-system"; +import Link from "next/link"; +import { Routes } from "@/constants/routes"; import { shortenStellarAddress } from "@/helpers/shortenStellarAddress"; +import { useIsTestingNetwork } from "@/hooks/useIsTestingNetwork"; import { useFriendBot } from "@/query/useFriendBot"; import { useStore } from "@/store/useStore"; @@ -18,6 +21,8 @@ export default function FundAccount() { const [generatedPublicKey, setGeneratedPublicKey] = useState(""); const [inlineErrorMessage, setInlineErrorMessage] = useState(""); + const IS_TESTING_NETWORK = useIsTestingNetwork(); + const { error, isError, isLoading, isSuccess, refetch, isFetchedAfterMount } = useFriendBot({ network: network.id, @@ -30,6 +35,15 @@ export default function FundAccount() { } }, [isError, isSuccess]); + if (!IS_TESTING_NETWORK) { + return ( +
+

Not Found

+

Could not find requested resource

+ Return Home +
+ ); + } return (
diff --git a/src/app/(sidebar)/account/layout.tsx b/src/app/(sidebar)/account/layout.tsx index cb7d5abc..267ff75c 100644 --- a/src/app/(sidebar)/account/layout.tsx +++ b/src/app/(sidebar)/account/layout.tsx @@ -4,33 +4,50 @@ import React from "react"; import { LayoutSidebarContent } from "@/components/layout/LayoutSidebarContent"; import { Routes } from "@/constants/routes"; +import { useIsTestingNetwork } from "@/hooks/useIsTestingNetwork"; + +// Includes navigation items that should ONLY display +// in TESTNET or FUTURENET +const DEFAULT_ACCOUNT_NAV_ITEMS = [ + { + route: Routes.ACCOUNT_CREATE, + label: "Create Account", + }, + { + route: Routes.ACCOUNT_FUND, + label: "Fund Account", + isTestnetOnly: true, + }, + { + route: Routes.ACCOUNT_CREATE_MUXED, + label: "Create Muxed Account", + }, + { + route: Routes.ACCOUNT_PARSE_MUXED, + label: "Parse Muxed Account", + }, +]; export default function AccountTemplate({ children, }: { children: React.ReactNode; }) { + const IS_TESTING_NETWORK = useIsTestingNetwork(); + + // Filtered navigation items for MAINNET + const filteredNavItems = DEFAULT_ACCOUNT_NAV_ITEMS.filter( + ({ isTestnetOnly }) => !isTestnetOnly, + ); + + const navItems = IS_TESTING_NETWORK + ? DEFAULT_ACCOUNT_NAV_ITEMS + : filteredNavItems; + return ( {children} diff --git a/src/components/layout/LayoutSidebarContent.tsx b/src/components/layout/LayoutSidebarContent.tsx index b12fb568..df769fdf 100644 --- a/src/components/layout/LayoutSidebarContent.tsx +++ b/src/components/layout/LayoutSidebarContent.tsx @@ -10,6 +10,7 @@ export type SidebarLink = { route: Routes | string; label: string; icon?: ReactNode; + isTestnetOnly?: boolean; nestedItems?: SidebarLink[]; }; diff --git a/src/hooks/useIsTestingNetwork.ts b/src/hooks/useIsTestingNetwork.ts new file mode 100644 index 00000000..03ec199b --- /dev/null +++ b/src/hooks/useIsTestingNetwork.ts @@ -0,0 +1,7 @@ +import { useStore } from "@/store/useStore"; + +export const useIsTestingNetwork = (): boolean => { + const { network } = useStore(); + + return network.id === "testnet" || network.id === "futurenet"; +}; diff --git a/tests/createAccountPage.test.ts b/tests/createAccountPage.test.ts index 4ae3edf8..e85ae724 100644 --- a/tests/createAccountPage.test.ts +++ b/tests/createAccountPage.test.ts @@ -13,8 +13,8 @@ test.describe("Create Account Page", () => { page, }) => { const buttonContainer = page.getByTestId("createAccount-buttons"); - await expect(buttonContainer.getByText("Generate keypair")).toBeVisible; - await expect(buttonContainer.getByText("Fund account with Friendbot")) + expect(buttonContainer.getByText("Generate keypair")).toBeVisible; + expect(buttonContainer.getByText("Fund account with Friendbot")) .toBeVisible; }); @@ -34,6 +34,6 @@ test.describe("Create Account Page", () => { .getByRole("button", { name: "Fund account with Friendbot" }) .click(); - await page.goto("http://localhost:3000/account/fund"); + await expect(page).toHaveURL(/.*\/account\/fund/); }); }); diff --git a/tests/createMuxedAccountPage.test.ts b/tests/createMuxedAccountPage.test.ts index 2dc7ce06..8b34a165 100644 --- a/tests/createMuxedAccountPage.test.ts +++ b/tests/createMuxedAccountPage.test.ts @@ -1,5 +1,7 @@ import { test, expect } from "@playwright/test"; +import { Account, MuxedAccount } from "@stellar/stellar-sdk"; + test.describe("Create Muxed Account Page", () => { test.beforeEach(async ({ page }) => { await page.goto("http://localhost:3000/account/muxed-create"); @@ -44,11 +46,12 @@ test.describe("Create Muxed Account Page", () => { test("Successfully creates a muxed account", async ({ page }) => { const publicKey = "GDVOT2ALMUF3G54RBHNJUEV6LOAZCQQCARHEVNUPKGMVPWFC4PFN33QR"; + const muxedId = "2"; const publicKeyInput = page.locator("#muxed-public-key"); await publicKeyInput.fill(publicKey); const muxedAccountIdInput = page.locator("#muxed-account-id"); - await muxedAccountIdInput.fill("2"); + await muxedAccountIdInput.fill(muxedId); const createButton = page.getByRole("button").getByText("Create"); @@ -59,5 +62,11 @@ test.describe("Create Muxed Account Page", () => { await createButton.click(); await expect(page.getByTestId("createAccount-success")).toBeVisible(); + + const muxedValue = page.locator("input[id='muxed-account-address-result']"); + + const muxedAccount = new MuxedAccount(new Account(publicKey, "0"), muxedId); + + await expect(muxedValue).toHaveValue(muxedAccount.accountId()); }); }); diff --git a/tests/fundAccountPage.test.ts b/tests/fundAccountPage.test.ts index 054ba35d..c0b006c3 100644 --- a/tests/fundAccountPage.test.ts +++ b/tests/fundAccountPage.test.ts @@ -1,6 +1,6 @@ import { test, expect } from "@playwright/test"; -test.describe("Fund Account Page", () => { +test.describe("[futurenet/testnet] Fund Account Page", () => { test.beforeEach(async ({ page }) => { await page.goto("http://localhost:3000/account/fund"); }); @@ -94,17 +94,16 @@ test.describe("Fund Account Page", () => { await expect(getLumenButton).toBeEnabled(); // Mock the friendbot api call - await page.route("**/*", async (route, request) => { - if (request.url().includes("?addr=")) { + await page.route( + "*/**/?addr=GDVOT2ALMUF3G54RBHNJUEV6LOAZCQQCARHEVNUPKGMVPWFC4PFN33QR", + async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({}), }); - } else { - await route.continue(); - } - }); + }, + ); // Ensure the listener is set up before the action that triggers the request const responsePromise = page.waitForResponse( @@ -122,7 +121,7 @@ test.describe("Fund Account Page", () => { await expect(alertBox).toBeVisible(); }); - test("Gets an error when submitting 'Get lumens' button twice with a valid public key", async ({ + test("Gets an error when submitting 'Get lumens' with a public key that's already been funded", async ({ page, }) => { const publicKeyInput = page.locator("#generate-keypair-publickey"); @@ -138,11 +137,96 @@ test.describe("Fund Account Page", () => { await expect(publicKeyInput).toHaveAttribute("aria-invalid", "false"); await expect(getLumenButton).toBeEnabled(); + // Mock the friendbot api call + await page.route( + "*/**/?addr=GDVOT2ALMUF3G54RBHNJUEV6LOAZCQQCARHEVNUPKGMVPWFC4PFN33QR", + async (route) => { + await route.fulfill({ + status: 400, + contentType: "application/json", + body: JSON.stringify({}), + }); + }, + ); + + // Ensure the listener is set up before the action that triggers the request + const responsePromise = page.waitForResponse( + (response) => + response.url().includes("?addr=") && response.status() === 400, + ); + await getLumenButton.click(); - // Funding the same account twice to get an error alert - await getLumenButton.click(); + + await responsePromise; const alertBox = page.getByText(/Unable to fund/); await expect(alertBox).toBeVisible(); }); + + test("if I switch to 'mainnet' network, I should see 'Not Found' page and no 'Fund account' sidebar", async ({ + page, + }) => { + // Click network selector dropdown button + await page.getByTestId("networkSelector-button").click(); + await expect(page.getByTestId("networkSelector-dropdown")).toBeVisible(); + + // Select Mainnet in the dropdown list + await page + .getByTestId("networkSelector-dropdown") + .getByTestId("networkSelector-option") + .filter({ has: page.getByText("Mainnet") }) + .click(); + + // Network Submit button + const submitButton = page.getByTestId("networkSelector-submit-button"); + + // Select 'Mainnet' in the network dropdown list + await expect(submitButton).toHaveText("Switch to Mainnet"); + await expect(submitButton).toBeEnabled(); + + // Click 'Switch to Mainnet' button + await submitButton.click(); + + await expect(page.getByTestId("networkSelector-button")).toHaveText( + "Mainnet", + ); + await expect(page.locator("h2")).toHaveText("Not Found"); + + await expect(page.getByTestId("endpoints-sidebar-section")).toHaveText( + "Create Account Create Muxed Account Parse Muxed Account", + ); + }); +}); + +test.describe("[mainnet] Fund Account Page", () => { + test.beforeEach(async ({ page }) => { + await page.goto("http://localhost:3000/account"); + + // Switch to mainnet network + await page.getByTestId("networkSelector-button").click(); + await expect(page.getByTestId("networkSelector-dropdown")).toBeVisible(); + + // Select Mainnet in the dropdown list + await page + .getByTestId("networkSelector-dropdown") + .getByTestId("networkSelector-option") + .filter({ has: page.getByText("Mainnet") }) + .click(); + + // Network Submit button + const submitButton = page.getByTestId("networkSelector-submit-button"); + + // Click 'Switch to Mainnet' button + await submitButton.click(); + + await expect(page.getByTestId("networkSelector-button")).toHaveText( + "Mainnet", + ); + }); + + test("I should see 'Not Found' on /account/fund", async ({ page }) => { + await page.goto("http://localhost:3000/account/fund"); + + await expect(page.locator("h2")).toHaveText("Not Found"); + }); });