From 4d6315629455c1cf8143e6d8dea6979e93602660 Mon Sep 17 00:00:00 2001 From: Jeesun Kim Date: Fri, 17 Jan 2025 21:51:30 -0800 Subject: [PATCH] add test --- .../build/components/Operations.tsx | 8 +- tests/buildTransaction.test.ts | 41 ++++++ tests/mock/localStorage.ts | 40 ++++++ tests/savedTransactions.test.ts | 121 +++++++++++++++++- 4 files changed, 203 insertions(+), 7 deletions(-) diff --git a/src/app/(sidebar)/transaction/build/components/Operations.tsx b/src/app/(sidebar)/transaction/build/components/Operations.tsx index 5c467da1..4b17cce1 100644 --- a/src/app/(sidebar)/transaction/build/components/Operations.tsx +++ b/src/app/(sidebar)/transaction/build/components/Operations.tsx @@ -153,7 +153,7 @@ export const Operations = () => { // Preserve values and validate inputs when components mounts useEffect(() => { // If no operations to preserve, add inital operation and error template - if (txnOperations.length === 0) { + if (txnOperations.length === 0 && !soroban.operation.operation_type) { updateOptionParamAndError({ type: "add", item: INITIAL_OPERATION }); } else { // Validate all params in all operations @@ -799,6 +799,10 @@ export const Operations = () => { }; const renderSourceAccount = (opType: string, index: number) => { + const currentOperation = isSorobanOperationType(opType) + ? sorobanOperation + : txnOperations[index]; + const sourceAccountComponent = formComponentTemplateTxnOps({ param: "source_account", opType, @@ -807,7 +811,7 @@ export const Operations = () => { return opType && sourceAccountComponent ? sourceAccountComponent.render({ - value: txnOperations[index].source_account, + value: currentOperation.source_account, error: operationsError[index]?.error?.["source_account"], isRequired: false, onChange: (e: ChangeEvent) => { diff --git a/tests/buildTransaction.test.ts b/tests/buildTransaction.test.ts index a7923830..5fa74d33 100644 --- a/tests/buildTransaction.test.ts +++ b/tests/buildTransaction.test.ts @@ -1393,6 +1393,47 @@ test.describe("Build Transaction Page", () => { errorMessage: "Expected a whole number.", }); }); + + test("Check rendering betweem classic and soroban", async ({ page }) => { + // Select Soroban Operation + const { operation_0 } = await selectOperationType({ + page, + opType: "extend_footprint_ttl", + }); + // we are going from classic operation to soroban operation + // so the classic operation should not be visible + await expect(operation_0).not.toBeVisible(); + + const soroban_operation = page.getByTestId( + "build-soroban-transaction-operation", + ); + + // Verify warning message about one operation limit + await expect( + page.getByText( + "Note that Soroban transactions can only contain one operation per transaction.", + ), + ).toBeVisible(); + + // Soroban Operation only allows one operation + // Add Operation button should not be visible + await expect(page.getByText("Add Operation")).not.toBeVisible(); + + // Select Classic Operation + await soroban_operation.getByLabel("Operation type").selectOption({ + value: "payment", + }); + + const classicOperation = page.getByTestId( + "build-transaction-operation-0", + ); + + await expect(classicOperation).toBeVisible(); + + // Soroban Operation only allows one operation + // Add Operation button should not be visible + await expect(page.getByText("Add Operation")).toBeVisible(); + }); }); }); }); diff --git a/tests/mock/localStorage.ts b/tests/mock/localStorage.ts index 9f10127e..b550d361 100644 --- a/tests/mock/localStorage.ts +++ b/tests/mock/localStorage.ts @@ -156,6 +156,46 @@ const SAVED_TRANSACTIONS = [ }, ], }, + // Soroban Transaction + { + timestamp: 1737143650128, + network: { id: "testnet", label: "Testnet" }, + name: "Extend to TTL", + xdr: "AAAAAgAAAAB+TL0HLiAjanMRnyeqyhb8Iu+4d1g2dl1cwPi1UZAigwAAtwUABiLjAAAAGQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAGQAAAAAAAHUwAAAAAQAAAAAAAAABAAAABgAAAAEg/u86MzPrVcpNrsFUa84T82Kss8DLAE9ZMxLqhM22HwAAABAAAAABAAAAAgAAAA8AAAAHQ291bnRlcgAAAAASAAAAAAAAAAB+TL0HLiAjanMRnyeqyhb8Iu+4d1g2dl1cwPi1UZAigwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtqEAAAAA", + page: "build", + shareableUrl: + "http://localhost:3000/transaction/build?$=network$id=testnet&label=Testnet&horizonUrl=https:////horizon-testnet.stellar.org&rpcUrl=https:////soroban-testnet.stellar.org&passphrase=Test%20SDF%20Network%20/;%20September%202015;&transaction$build$params$source_account=GB7EZPIHFYQCG2TTCGPSPKWKC36CF35YO5MDM5S5LTAPRNKRSARIHWGG&seq_num=1727208213184537;&operations@$operation_type=payment¶ms$destination=GAQ6LVQXNRX26CBIKCYGGGD6B4SNQACTJ46QMHS4Q5S52UHZW76XJJPJ&asset$code=&issuer=&type=native;&amount=5;&source_account=;;&isValid$params:true&operations:true;&soroban$operation$operation_type=extend_footprint_ttl¶ms$durability=persistent&contract=CAQP53Z2GMZ6WVOKJWXMCVDLZYJ7GYVMWPAMWACPLEZRF2UEZW3B636S&key_xdr=AAAAEAAAAAEAAAACAAAADwAAAAdDb3VudGVyAAAAABIAAAAAAAAAAH5MvQcuICNqcxGfJ6rKFvwi77h3WDZ2XVzA+LVRkCKD&extend_ttl_to=30000&resource_fee=46753;;", + params: { + source_account: + "GB7EZPIHFYQCG2TTCGPSPKWKC36CF35YO5MDM5S5LTAPRNKRSARIHWGG", + fee: "100", + seq_num: "1727208213184537", + cond: { time: { min_time: "", max_time: "" } }, + memo: {}, + }, + operations: [ + { + operation_type: "extend_footprint_ttl", + params: { + durability: "persistent", + contract: "CAQP53Z2GMZ6WVOKJWXMCVDLZYJ7GYVMWPAMWACPLEZRF2UEZW3B636S", + key_xdr: + "AAAAEAAAAAEAAAACAAAADwAAAAdDb3VudGVyAAAAABIAAAAAAAAAAH5MvQcuICNqcxGfJ6rKFvwi77h3WDZ2XVzA+LVRkCKD", + extend_ttl_to: "30000", + resource_fee: "46753", + }, + source_account: "", + }, + ], + }, + { + timestamp: 1737148428325, + network: { id: "testnet", label: "Testnet" }, + name: "Extend TTL", + xdr: "AAAAAgAAAAB+TL0HLiAjanMRnyeqyhb8Iu+4d1g2dl1cwPi1UZAigwAAtwUABiLjAAAAGQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAGQAAAAAAAHUwAAAAAQAAAAAAAAABAAAABgAAAAEg/u86MzPrVcpNrsFUa84T82Kss8DLAE9ZMxLqhM22HwAAABAAAAABAAAAAgAAAA8AAAAHQ291bnRlcgAAAAASAAAAAAAAAAB+TL0HLiAjanMRnyeqyhb8Iu+4d1g2dl1cwPi1UZAigwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtqEAAAABUZAigwAAAEADYbntiznotYPblvJQ35DiGEpMTQU9jCYANxV18VVGV6zDFSjB+qK++dF656Pr4oMTpyBVvE15YSo6ITxR5DoE", + page: "submit", + shareableUrl: "http://localhost:3000/transaction/submit?$=;;", + }, ]; export const MOCK_LOCAL_STORAGE = { diff --git a/tests/savedTransactions.test.ts b/tests/savedTransactions.test.ts index 8107028c..215fd85b 100644 --- a/tests/savedTransactions.test.ts +++ b/tests/savedTransactions.test.ts @@ -25,7 +25,7 @@ test.describe("Saved Transactions Page", () => { // local storage data let pageContext: Page; - test.beforeAll(async ({ browser }) => { + test.beforeEach(async ({ browser }) => { const browserContext = await browser.newContext({ storageState: MOCK_LOCAL_STORAGE, }); @@ -42,10 +42,10 @@ test.describe("Saved Transactions Page", () => { const txItems = pageContext.getByTestId("saved-transactions-item"); - await expect(txItems).toHaveCount(2); + await expect(txItems).toHaveCount(4); }); - test("Submit item", async () => { + test("[Classic] Submit item", async () => { const submitItem = pageContext .getByTestId("saved-transactions-item") .nth(0); @@ -86,7 +86,7 @@ test.describe("Saved Transactions Page", () => { ); }); - test("Build item", async () => { + test("[Classic] Build item", async () => { const buildItem = pageContext .getByTestId("saved-transactions-item") .nth(1); @@ -137,13 +137,124 @@ test.describe("Saved Transactions Page", () => { ); }); + test("[Soroban] Submit item", async () => { + await pageContext.waitForSelector( + '[data-testid="saved-transactions-item"]', + ); + const items = pageContext.getByTestId("saved-transactions-item"); + + const submitItem = items.last(); + await expect(submitItem).toBeVisible(); + + const nameInput = submitItem.getByTestId("saved-transactions-name"); + await expect(nameInput).toBeVisible(); + + await expect(nameInput).toHaveValue("Extend TTL"); + await expect( + submitItem.getByText("Last saved Jan 17, 2025, 9:13 PM UTC"), + ).toBeVisible(); + + // Edit name + await submitItem.getByTestId("saved-transactions-edit").click(); + + await expect( + pageContext.getByText("Edit Saved Transaction", { exact: true }), + ).toBeVisible(); + + const newName = "Extend TTL New"; + + await pageContext.getByLabel("Name").fill(newName); + await pageContext.getByText("Save", { exact: true }).click(); + + await expect(nameInput).toHaveValue(newName); + + // View in submitter + await submitItem.getByText("View in submitter").click(); + await pageContext.waitForURL("**/transaction/submit"); + + await expect(pageContext.locator("h1")).toHaveText("Submit Transaction"); + await expect( + pageContext.getByLabel("Input a base-64 encoded TransactionEnvelope:"), + ).toHaveValue( + "AAAAAgAAAAB+TL0HLiAjanMRnyeqyhb8Iu+4d1g2dl1cwPi1UZAigwAAtwUABiLjAAAAGQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAGQAAAAAAAHUwAAAAAQAAAAAAAAABAAAABgAAAAEg/u86MzPrVcpNrsFUa84T82Kss8DLAE9ZMxLqhM22HwAAABAAAAABAAAAAgAAAA8AAAAHQ291bnRlcgAAAAASAAAAAAAAAAB+TL0HLiAjanMRnyeqyhb8Iu+4d1g2dl1cwPi1UZAigwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtqEAAAABUZAigwAAAEADYbntiznotYPblvJQ35DiGEpMTQU9jCYANxV18VVGV6zDFSjB+qK++dF656Pr4oMTpyBVvE15YSo6ITxR5DoE", + ); + await expect(pageContext.getByLabel("Transaction hash")).toHaveValue( + "0571508f487a343006d231d11f201a855f67973e0e019da6164b32b992dab46f", + ); + }); + + test("[Soroban] Build item", async () => { + const buildItem = pageContext + .getByTestId("saved-transactions-item") + .nth(2); + + await expect( + buildItem.getByTestId("saved-transactions-name"), + ).toHaveValue("Extend to TTL"); + + const ops = buildItem.getByTestId("saved-transactions-op"); + + await expect(ops.nth(0)).toHaveValue("Extend Footprint TTL"); + + await expect( + buildItem.getByText("Last saved Jan 17, 2025, 7:54 PM UTC"), + ).toBeVisible(); + + // Click the button + await buildItem.getByText("View in builder", { exact: true }).click(); + + // Wait for navigation + await pageContext.waitForURL("**/transaction/build"); + + // Params + await expect( + pageContext.getByLabel("Source Account").first(), + ).toHaveValue("GB7EZPIHFYQCG2TTCGPSPKWKC36CF35YO5MDM5S5LTAPRNKRSARIHWGG"); + await expect( + pageContext.getByLabel("Transaction Sequence Number"), + ).toHaveValue("1727208213184537"); + + const sorobanOperation = pageContext.getByTestId( + "build-soroban-transaction-operation", + ); + await expect(sorobanOperation.getByLabel("Operation type")).toHaveValue( + "extend_footprint_ttl", + ); + + // Operations + await expect( + pageContext.getByTestId("build-soroban-transaction-operation"), + ).toBeVisible(); + await expect(pageContext.getByLabel("Contract ID")).toHaveValue( + "CAQP53Z2GMZ6WVOKJWXMCVDLZYJ7GYVMWPAMWACPLEZRF2UEZW3B636S", + ); + await expect(pageContext.getByLabel("Key ScVal in XDR")).toHaveValue( + "AAAAEAAAAAEAAAACAAAADwAAAAdDb3VudGVyAAAAABIAAAAAAAAAAH5MvQcuICNqcxGfJ6rKFvwi77h3WDZ2XVzA+LVRkCKD", + ); + await expect(pageContext.getByLabel("Extend To")).toHaveValue("30000"); + await expect( + pageContext.getByLabel("Resource Fee (in stroops)"), + ).toHaveValue("46753"); + + const xdrElement = pageContext.getByTestId( + "build-soroban-transaction-envelope-xdr", + ); + + await xdrElement.isVisible(); + + // XDR + await expect(xdrElement.getByText("XDR").locator("+ div")).toHaveText( + "AAAAAgAAAAB+TL0HLiAjanMRnyeqyhb8Iu+4d1g2dl1cwPi1UZAigwAAtwUABiLjAAAAGQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAGQAAAAAAAHUwAAAAAQAAAAAAAAABAAAABgAAAAEg/u86MzPrVcpNrsFUa84T82Kss8DLAE9ZMxLqhM22HwAAABAAAAABAAAAAgAAAA8AAAAHQ291bnRlcgAAAAASAAAAAAAAAAB+TL0HLiAjanMRnyeqyhb8Iu+4d1g2dl1cwPi1UZAigwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtqEAAAAA", + ); + }); + test("Delete transaction", async () => { const txItem = pageContext.getByTestId("saved-transactions-item").first(); await txItem.locator(".Button--error").click(); const txItems = pageContext.getByTestId("saved-transactions-item"); - await expect(txItems).toHaveCount(1); + await expect(txItems).toHaveCount(3); }); }); });