From 72338b72e376750f8f9d72e8aadaa85731b6abb5 Mon Sep 17 00:00:00 2001 From: Iveta Date: Mon, 2 Dec 2024 14:41:12 -0500 Subject: [PATCH 1/4] Saved Keypairs UI Tests --- src/app/(sidebar)/account/saved/page.tsx | 9 +- tests/mock/localStorage.ts | 46 +++++ tests/savedKeypairs.test.ts | 241 +++++++++++++++++++++++ yarn.lock | 6 +- 4 files changed, 298 insertions(+), 4 deletions(-) create mode 100644 tests/mock/localStorage.ts create mode 100644 tests/savedKeypairs.test.ts diff --git a/src/app/(sidebar)/account/saved/page.tsx b/src/app/(sidebar)/account/saved/page.tsx index a6e02c73..6dd8f30f 100644 --- a/src/app/(sidebar)/account/saved/page.tsx +++ b/src/app/(sidebar)/account/saved/page.tsx @@ -298,9 +298,14 @@ const SavedKeypairItem = ({ }; return ( - + { + test.beforeEach(async ({ page }) => { + await page.goto("http://localhost:3000/account/saved"); + }); + + test("Loads", async ({ page }) => { + await expect(page.locator("h1")).toHaveText("Saved Keypairs"); + }); + + test("Show no saved keypairs message", async ({ page }) => { + await expect( + page.getByText("There are no saved keypairs on Testnet network."), + ).toBeVisible(); + }); + + test.describe("Saved accounts", () => { + // Setting page context to share among all the tests in this section to keep + // local storage data + let pageContext: Page; + + test.beforeAll(async ({ browser }) => { + const browserContext = await browser.newContext({ + storageState: MOCK_LOCAL_STORAGE, + }); + pageContext = await browserContext.newPage(); + + await pageContext.goto("http://localhost:3000/account/saved"); + + // Account 1 response (funded) + await pageContext.route( + `*/**/accounts/${SAVED_ACCOUNT_1}`, + async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/hal+json; charset=utf-8", + body: JSON.stringify(MOCK_ACCOUNT_1_RESPONSE), + }); + }, + ); + + // Account 2 response (unfunded) + await pageContext.route( + `*/**/accounts/${SAVED_ACCOUNT_2}`, + async (route) => { + await route.fulfill({ + status: 404, + contentType: "application/problem+json; charset=utf-8", + body: JSON.stringify(MOCK_ACCOUNT_2_RESPONSE_UNFUNDED), + }); + }, + ); + }); + + test("Loads", async () => { + await expect( + pageContext.getByText( + "There are no saved keypairs on Testnet network.", + ), + ).toBeHidden(); + + const keypairItems = pageContext.getByTestId("saved-keypair-item"); + + await expect(keypairItems).toHaveCount(2); + }); + + test("Funded account", async () => { + const keypairItem = pageContext.getByTestId("saved-keypair-item").first(); + + await expect(keypairItem).toBeVisible(); + await expect(keypairItem.getByTestId("saved-keypair-name")).toHaveValue( + "Account 1", + ); + await expect(keypairItem.getByTestId("saved-keypair-pk")).toHaveValue( + SAVED_ACCOUNT_1, + ); + await expect(keypairItem.getByTestId("saved-keypair-sk")).toHaveValue( + SAVED_ACCOUNT_1_SECRET, + ); + await expect( + keypairItem.getByText("Balance: 10000.0000000 XLM", { exact: true }), + ).toBeVisible(); + await expect( + keypairItem.getByText("Last saved Nov 22, 2024, 3:04 PM UTC", { + exact: true, + }), + ).toBeVisible(); + }); + + test("Fund unfunded account", async () => { + const keypairItem = pageContext.getByTestId("saved-keypair-item").nth(1); + + await expect(keypairItem).toBeVisible(); + await expect(keypairItem.getByTestId("saved-keypair-name")).toHaveValue( + "Account 2", + ); + + const fundButton = pageContext.getByText("Fund with Friendbot"); + + await expect(fundButton).toBeVisible(); + + // Mock fund account + await pageContext.route( + `*/**/?addr=${SAVED_ACCOUNT_2}`, + async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/hal+json; charset=utf-8", + }); + }, + ); + + // Wait for the Friendbot response + const responsePromise = pageContext.waitForResponse( + (response) => + response.url().includes("?addr=") && response.status() === 200, + ); + + await fundButton.click(); + + await responsePromise; + + // Mock Account 2 response + await pageContext.route( + `*/**/accounts/${SAVED_ACCOUNT_2}`, + async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/hal+json; charset=utf-8", + body: JSON.stringify(MOCK_ACCOUNT_1_RESPONSE), + }); + }, + ); + + await expect(fundButton).toBeHidden(); + await expect( + keypairItem.getByText("Balance: 10000.0000000 XLM", { exact: true }), + ).toBeVisible(); + }); + + test("Delete keypair", async () => { + const keypairItem = pageContext.getByTestId("saved-keypair-item").first(); + const deleteButton = keypairItem.locator(".Button--error"); + + await deleteButton.click(); + + const keypairItems = pageContext.getByTestId("saved-keypair-item"); + await expect(keypairItems).toHaveCount(1); + }); + }); +}); + +// ============================================================================= +// Mock data +// ============================================================================= +const MOCK_ACCOUNT_1_RESPONSE = { + _links: { + self: { + href: "https://horizon-testnet.stellar.org/accounts/GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K", + }, + transactions: { + href: "https://horizon-testnet.stellar.org/accounts/GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K/transactions{?cursor,limit,order}", + templated: true, + }, + operations: { + href: "https://horizon-testnet.stellar.org/accounts/GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K/operations{?cursor,limit,order}", + templated: true, + }, + payments: { + href: "https://horizon-testnet.stellar.org/accounts/GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K/payments{?cursor,limit,order}", + templated: true, + }, + effects: { + href: "https://horizon-testnet.stellar.org/accounts/GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K/effects{?cursor,limit,order}", + templated: true, + }, + offers: { + href: "https://horizon-testnet.stellar.org/accounts/GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K/offers{?cursor,limit,order}", + templated: true, + }, + trades: { + href: "https://horizon-testnet.stellar.org/accounts/GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K/trades{?cursor,limit,order}", + templated: true, + }, + data: { + href: "https://horizon-testnet.stellar.org/accounts/GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K/data/{key}", + templated: true, + }, + }, + id: "GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K", + account_id: "GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K", + sequence: "4914705307009024", + subentry_count: 0, + last_modified_ledger: 1144294, + last_modified_time: "2024-11-25T15:57:29Z", + thresholds: { + low_threshold: 0, + med_threshold: 0, + high_threshold: 0, + }, + flags: { + auth_required: false, + auth_revocable: false, + auth_immutable: false, + auth_clawback_enabled: false, + }, + balances: [ + { + balance: "10000.0000000", + buying_liabilities: "0.0000000", + selling_liabilities: "0.0000000", + asset_type: "native", + }, + ], + signers: [ + { + weight: 1, + key: "GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K", + type: "ed25519_public_key", + }, + ], + data: {}, + num_sponsoring: 0, + num_sponsored: 0, + paging_token: "GDREGRXN4NCEKRACVD4SPMQTF6IEMNVSYT6ELCECQNEOPAIFA7MYVY6K", +}; + +const MOCK_ACCOUNT_2_RESPONSE_UNFUNDED = { + type: "https://stellar.org/horizon-errors/not_found", + title: "Resource Missing", + status: 404, + detail: + "The resource at the url requested was not found. This usually occurs for one of two reasons: The url requested is not valid, or no data in our database could be found with the parameters provided.", +}; diff --git a/yarn.lock b/yarn.lock index 1f8f7b65..ba2262be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2356,9 +2356,9 @@ camelcase@^5.0.0: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== caniuse-lite@^1.0.30001579: - version "1.0.30001632" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001632.tgz#964207b7cba5851701afb4c8afaf1448db3884b6" - integrity sha512-udx3o7yHJfUxMLkGohMlVHCvFvWmirKh9JAH/d7WOLPetlH+LTL5cocMZ0t7oZx/mdlOWXti97xLZWc8uURRHg== + version "1.0.30001685" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001685.tgz" + integrity sha512-e/kJN1EMyHQzgcMEEgoo+YTCO1NGCmIYHk5Qk8jT6AazWemS5QFKJ5ShCJlH3GZrNIdZofcNCEwZqbMjjKzmnA== cashaddrjs@0.4.4: version "0.4.4" From 982c6bafa0049c4995bbd839c0d6a454ed39f54d Mon Sep 17 00:00:00 2001 From: Iveta Date: Mon, 2 Dec 2024 15:16:25 -0500 Subject: [PATCH 2/4] Wait for account response --- tests/savedKeypairs.test.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/savedKeypairs.test.ts b/tests/savedKeypairs.test.ts index 32aceefd..38675823 100644 --- a/tests/savedKeypairs.test.ts +++ b/tests/savedKeypairs.test.ts @@ -118,14 +118,15 @@ test.describe("Saved Keypairs Page", () => { ); // Wait for the Friendbot response - const responsePromise = pageContext.waitForResponse( + const friendbotResponse = pageContext.waitForResponse( (response) => - response.url().includes("?addr=") && response.status() === 200, + response.url().includes(`?addr=${SAVED_ACCOUNT_2}`) && + response.status() === 200, ); await fundButton.click(); - await responsePromise; + await friendbotResponse; // Mock Account 2 response await pageContext.route( @@ -139,6 +140,14 @@ test.describe("Saved Keypairs Page", () => { }, ); + const accountResponse = pageContext.waitForResponse( + (response) => + response.url().includes(`accounts/${SAVED_ACCOUNT_2}`) && + response.status() === 200, + ); + + await accountResponse; + await expect(fundButton).toBeHidden(); await expect( keypairItem.getByText("Balance: 10000.0000000 XLM", { exact: true }), From f601dccb0f5368e06679ca4eb47f33d18d69fd91 Mon Sep 17 00:00:00 2001 From: Iveta Date: Wed, 4 Dec 2024 09:30:26 -0500 Subject: [PATCH 3/4] Fix Friendbot test --- tests/savedKeypairs.test.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/savedKeypairs.test.ts b/tests/savedKeypairs.test.ts index 38675823..ebda9904 100644 --- a/tests/savedKeypairs.test.ts +++ b/tests/savedKeypairs.test.ts @@ -106,16 +106,15 @@ test.describe("Saved Keypairs Page", () => { await expect(fundButton).toBeVisible(); + const friendbotUrl = `https://friendbot.stellar.org/?addr=${SAVED_ACCOUNT_2}`; + // Mock fund account - await pageContext.route( - `*/**/?addr=${SAVED_ACCOUNT_2}`, - async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/hal+json; charset=utf-8", - }); - }, - ); + await pageContext.route(friendbotUrl, async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/hal+json; charset=utf-8", + }); + }); // Wait for the Friendbot response const friendbotResponse = pageContext.waitForResponse( @@ -125,8 +124,8 @@ test.describe("Saved Keypairs Page", () => { ); await fundButton.click(); - await friendbotResponse; + await pageContext.unroute(friendbotUrl); // Mock Account 2 response await pageContext.route( From 2e100e2223df27882505f5bf92c16862c086be5b Mon Sep 17 00:00:00 2001 From: Iveta Date: Wed, 4 Dec 2024 10:02:12 -0500 Subject: [PATCH 4/4] Another try --- tests/mock/localStorage.ts | 4 ++-- tests/savedKeypairs.test.ts | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/mock/localStorage.ts b/tests/mock/localStorage.ts index ebe779d0..0f46647b 100644 --- a/tests/mock/localStorage.ts +++ b/tests/mock/localStorage.ts @@ -3,9 +3,9 @@ export const SAVED_ACCOUNT_1 = export const SAVED_ACCOUNT_1_SECRET = "SADVGAH3VA3NGZ5VLX2ZICV7JQAINB2ZJZYOPMBXUNI3YRLGWLOA2OFY"; export const SAVED_ACCOUNT_2 = - "GD4F2N2OM2IM4MI6F6J5GVENQLNRVCYEE6XFN36MJOU5MOVFUYYSPBYG"; + "GC5TQ7TXKHGE5JQMZPYV5KBSQ67X6PYQVU5QN7JRGWCHRA227UFPZ6LD"; export const SAVED_ACCOUNT_2_SECRET = - "SDVMTXXSUJG6GKFCETCKFV6FCGE7C5FYKBCV4AMD4N3SRYCDSA53KEG4"; + "SCPPMMBZBQGTGQKIPGFJDOHOPGK7SXZJGMYF76PFHF2PBLY2RWGZNSVV"; const SAVED_ACCOUNTS = [ { diff --git a/tests/savedKeypairs.test.ts b/tests/savedKeypairs.test.ts index ebda9904..90b47426 100644 --- a/tests/savedKeypairs.test.ts +++ b/tests/savedKeypairs.test.ts @@ -57,6 +57,17 @@ test.describe("Saved Keypairs Page", () => { }); }, ); + + // Account 2 Friendbot response + await pageContext.route( + `https://friendbot.stellar.org/?addr=${SAVED_ACCOUNT_2}`, + async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/hal+json; charset=utf-8", + }); + }, + ); }); test("Loads", async () => { @@ -106,16 +117,6 @@ test.describe("Saved Keypairs Page", () => { await expect(fundButton).toBeVisible(); - const friendbotUrl = `https://friendbot.stellar.org/?addr=${SAVED_ACCOUNT_2}`; - - // Mock fund account - await pageContext.route(friendbotUrl, async (route) => { - await route.fulfill({ - status: 200, - contentType: "application/hal+json; charset=utf-8", - }); - }); - // Wait for the Friendbot response const friendbotResponse = pageContext.waitForResponse( (response) => @@ -125,7 +126,6 @@ test.describe("Saved Keypairs Page", () => { await fundButton.click(); await friendbotResponse; - await pageContext.unroute(friendbotUrl); // Mock Account 2 response await pageContext.route(