From bc5cb0fafea034aad0fea3daddb30e022bb8ac32 Mon Sep 17 00:00:00 2001 From: Nabin Kawan Date: Wed, 8 May 2024 14:16:30 +0545 Subject: [PATCH] fix: Transaction locking --- .../playwright/lib/constants/environments.ts | 8 +- .../playwright/lib/constants/staticWallets.ts | 2 +- .../playwright/lib/helpers/transaction.ts | 33 +++++-- .../playwright/lib/lockInterceptor.ts | 98 ++++++++++++++----- .../playwright/lib/services/kuberService.ts | 28 +++--- .../playwright/package-lock.json | 14 +-- .../govtool-frontend/playwright/package.json | 2 +- .../playwright/playwright.config.ts | 34 +++++-- ....spec.ts => delegation.delegation.spec.ts} | 30 +++++- .../tests/2-delegation/delegation.tx.spec.ts | 21 ---- .../dRepRegistration.dRep.spec.ts | 19 +++- .../dRepRegistration.tx.spec.ts | 16 --- .../proposalFunctionality.dRep.spec.ts | 4 +- .../miscellaneous.loggedin.spec.ts | 16 +-- .../playwright/tests/dRep.setup.ts | 7 +- ...der.teardown.ts => delegation.teardown.ts} | 7 +- .../playwright/tests/faucet.setup.ts | 16 +++ .../playwright/tests/wallet.bootstrap.ts | 21 +--- 18 files changed, 241 insertions(+), 135 deletions(-) rename tests/govtool-frontend/playwright/tests/2-delegation/{delegation.dRep.spec.ts => delegation.delegation.spec.ts} (72%) delete mode 100644 tests/govtool-frontend/playwright/tests/2-delegation/delegation.tx.spec.ts delete mode 100644 tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.tx.spec.ts rename tests/govtool-frontend/playwright/tests/{adaholder.teardown.ts => delegation.teardown.ts} (66%) create mode 100644 tests/govtool-frontend/playwright/tests/faucet.setup.ts diff --git a/tests/govtool-frontend/playwright/lib/constants/environments.ts b/tests/govtool-frontend/playwright/lib/constants/environments.ts index eea7478db..ccdfd8c14 100644 --- a/tests/govtool-frontend/playwright/lib/constants/environments.ts +++ b/tests/govtool-frontend/playwright/lib/constants/environments.ts @@ -15,9 +15,13 @@ const environments = { process.env.KUBER_API_URL || "https://sanchonet.kuber.cardanoapi.io", apiKey: process.env.KUBER_API_KEY || "", }, - txTimeOut: parseInt(process.env.TX_TIMEOUT) || 120000, + txTimeOut: parseInt(process.env.TX_TIMEOUT) || 240000, metadataBucketUrl: - process.env.METADATA_BUCKET_URL || "https://metadata.cardanoapi.io/data", + `${process.env.CARDANOAPI_METADATA_URL}/data` || + "https://metadata.cardanoapi.io/data", + lockInterceptorUrl: + `${process.env.CARDANOAPI_METADATA_URL}/data` || + "https://metadata.cardanoapi.io/lock", }; export default environments; diff --git a/tests/govtool-frontend/playwright/lib/constants/staticWallets.ts b/tests/govtool-frontend/playwright/lib/constants/staticWallets.ts index 037ccd3ce..21a0289e6 100644 --- a/tests/govtool-frontend/playwright/lib/constants/staticWallets.ts +++ b/tests/govtool-frontend/playwright/lib/constants/staticWallets.ts @@ -18,8 +18,8 @@ export const faucetWallet: StaticWallet = { export const dRep01Wallet: StaticWallet = { payment: { - private: "2f1053f22707b9881ea6112024027a660bd5508e22081cf5e4e95cc663802dd9", public: "891ed5096ee248bc7f31a3094ea90f34485483eb1050c7ee368e64d04b90a009", + private: "2f1053f22707b9881ea6112024027a660bd5508e22081cf5e4e95cc663802dd9", pkh: "5775ad2fb14ca1b45381a40e40f0c06081edaf2261e02bbcebcf8dc3", }, stake: { diff --git a/tests/govtool-frontend/playwright/lib/helpers/transaction.ts b/tests/govtool-frontend/playwright/lib/helpers/transaction.ts index 63107dd9c..d85dc2efa 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/transaction.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/transaction.ts @@ -1,14 +1,17 @@ import environments from "@constants/environments"; import { Page, expect } from "@playwright/test"; import kuberService from "@services/kuberService"; -import { LockInterceptor } from "lib/lockInterceptor"; +import { LockInterceptor, LockInterceptorInfo } from "lib/lockInterceptor"; import { Logger } from "../../../cypress/lib/logger/logger"; /** * Polls the transaction status until it's resolved or times out. * address is used to release lock of that address */ -export async function pollTransaction(txHash: string, address?: string) { +export async function pollTransaction( + txHash: string, + lockInfo?: LockInterceptorInfo +) { try { Logger.info(`Waiting for tx completion: ${txHash}`); await expect @@ -18,17 +21,33 @@ export async function pollTransaction(txHash: string, address?: string) { const data = await response.json(); return data.length; }, - { message: "Transaction failed", timeout: environments.txTimeOut } + { + timeout: environments.txTimeOut, + } ) .toBeGreaterThan(0); Logger.success("Tx completed"); + + if (!lockInfo) return; + + await LockInterceptor.releaseLockForAddress( + lockInfo.address, + lockInfo.lockId, + `Task completed for:${lockInfo.lockId}` + ); } catch (err) { - throw err; - } finally { - if (!address) return; + if (lockInfo) { + const errorMessage = { lockInfo, error: JSON.stringify(err) }; - await LockInterceptor.releaseLockForAddress(address); + await LockInterceptor.releaseLockForAddress( + lockInfo.address, + lockInfo.lockId, + `Task failure: \n${JSON.stringify(errorMessage)}` + ); + } + + throw err; } } diff --git a/tests/govtool-frontend/playwright/lib/lockInterceptor.ts b/tests/govtool-frontend/playwright/lib/lockInterceptor.ts index aa740caa3..a3b13cda7 100644 --- a/tests/govtool-frontend/playwright/lib/lockInterceptor.ts +++ b/tests/govtool-frontend/playwright/lib/lockInterceptor.ts @@ -5,16 +5,29 @@ import { Logger } from "../../cypress/lib/logger/logger"; import path = require("path"); +export interface LockInterceptorInfo { + lockId: string; + address: string; +} + +abstract class BaseLock { + abstract acquireLock(key: string, id?: string): Promise; + + abstract releaseLock(key: string, id?: string): Promise; + + abstract checkLock(key: string): Promise; +} + export class LockInterceptor { private static async acquireLock( address: string, - message?: string + lockId: string ): Promise { const lockFilePath = path.resolve(__dirname, `../.lock-pool/${address}`); try { await log( - `${address} -> acquiring lock` + message && `\nMessage: ${message}` + `Initiator: ${address} \n---------------------> acquiring lock for:${lockId}` ); await new Promise((resolve, reject) => { lockfile.lock(lockFilePath, (err) => { @@ -25,21 +38,23 @@ export class LockInterceptor { } }); }); - await log(`${address} -> acquired lock`); + await log( + `Initiator: ${address} \n---------------------> acquired lock for:${lockId}` + ); } catch (err) { - Logger.fail("Failed to write lock logs"); + throw err; } } private static async releaseLock( address: string, - message?: string + lockId: string ): Promise { const lockFilePath = path.resolve(__dirname, `../.lock-pool/${address}`); try { await log( - `${address} -> releasing lock` + message && `\nMessage: ${message}` + `Initiator: ${address} \n---------------------> releasing lock for:${lockId}` ); await new Promise((resolve, reject) => { lockfile.unlock(lockFilePath, async (err) => { @@ -50,21 +65,23 @@ export class LockInterceptor { } }); }); - await log(`${address} -> released lock\n`); + await log( + `Initiator: ${address} \n---------------------> released lock for:${lockId}\n` + ); } catch (err) { - Logger.fail("Failed to write lock logs"); + throw err; } } private static async waitForReleaseLock( address: string, - message?: string + lockId: string ): Promise { - const pollInterval = 200; + const pollInterval = 4000; // 4 secs try { await log( - `${address} -> waiting lock` + message && `\nMessage: ${message}` + `Initiator: ${address} \n ---------------------> waiting lock for:${lockId}` ); return new Promise((resolve, reject) => { const pollFn = () => { @@ -83,32 +100,57 @@ export class LockInterceptor { pollFn(); }); } catch (err) { - Logger.fail("Failed to write lock logs"); + throw err; } } static async intercept( address: string, callbackFn: () => Promise, - message?: string + lockId: string, + provider: "local" | "server" = "local" ): Promise { - const isAddressLocked = checkAddressLock(address); - if (isAddressLocked) { - await LockInterceptor.waitForReleaseLock(address, message); - } + while (true) { + const isAddressLocked = checkAddressLock(address); + if (isAddressLocked) { + await LockInterceptor.waitForReleaseLock(address, lockId); + } - await LockInterceptor.acquireLock(address, message); + try { + await LockInterceptor.acquireLock(address, lockId); + break; + } catch (err) { + if (err.code === "EEXIST") { + await new Promise((resolve) => setTimeout(resolve, 1000)); // timeout for retry + continue; + } else { + throw err; + } + } + } try { const res = await callbackFn(); - return { ...res, address }; + return { ...res, lockInfo: { lockId, address } }; } catch (err) { - await LockInterceptor.releaseLock(address, "Tx failure"); + const errorMessage = { lock_id: lockId, error: JSON.stringify(err) }; + await log(`Task failure: \n${JSON.stringify(errorMessage)}`); + await LockInterceptor.releaseLock(address, lockId); throw err; } } - static async releaseLockForAddress(address: string) { - await this.releaseLock(address); + static async releaseLockForAddress( + address: string, + lockId: string, + message?: string + ) { + try { + message && (await log(message)); + + await this.releaseLock(address, lockId); + } catch { + Logger.fail("Failed to write lock logs"); + } } } @@ -118,8 +160,18 @@ function checkAddressLock(address: string): boolean { } function log(message: string): Promise { + const options: Intl.DateTimeFormatOptions = { + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + hour12: false, + timeZone: "Asia/Kathmandu", + }; const logFilePath = path.resolve(__dirname, "../.logs/lock_logs.txt"); - const logMessage = `[${new Date().toISOString()}] ${message}\n`; + const logMessage = `[${new Date().toLocaleString("en-US", options)}] ${message}\n`; return new Promise((resolve, reject) => { fs.appendFile(logFilePath, logMessage, (err) => { if (err) { diff --git a/tests/govtool-frontend/playwright/lib/services/kuberService.ts b/tests/govtool-frontend/playwright/lib/services/kuberService.ts index 8ba49b402..65190100e 100644 --- a/tests/govtool-frontend/playwright/lib/services/kuberService.ts +++ b/tests/govtool-frontend/playwright/lib/services/kuberService.ts @@ -3,7 +3,7 @@ import { ShelleyWallet } from "@helpers/crypto"; import { KuberValue } from "@types"; import * as blake from "blakejs"; import environments from "lib/constants/environments"; -import { LockInterceptor } from "lib/lockInterceptor"; +import { LockInterceptor, LockInterceptorInfo } from "lib/lockInterceptor"; import fetch, { BodyInit, RequestInit } from "node-fetch"; import { cborxDecoder, cborxEncoder } from "../helpers/cborEncodeDecode"; import convertBufferToHex from "../helpers/convertBufferToHex"; @@ -11,12 +11,16 @@ import { Logger } from "./../../../cypress/lib/logger/logger"; type CertificateType = "registerstake" | "registerdrep" | "deregisterdrep"; -export type TxSubmitResponse = { cbor: string; txId: string; address?: string }; +export type TxSubmitResponse = { + cbor: string; + txId: string; + lockInfo?: LockInterceptorInfo; +}; type KuberBalanceResponse = { - address: string; txin: string; value: KuberValue; + address?: string; }; const config = { @@ -71,18 +75,20 @@ class Kuber { async signAndSubmitTx(tx: any) { const signedTx = this.signTx(tx); + const signedTxBody = Uint8Array.from(cborxEncoder.encode(tx)); + const lockId = Buffer.from( + blake.blake2b(signedTxBody, undefined, 32) + ).toString("hex"); const submitTxCallback = async () => { - return this.submitTx(signedTx); + return this.submitTx(signedTx, lockId); }; - return LockInterceptor.intercept( - this.walletAddr, - submitTxCallback, - JSON.stringify(signedTx, null, 2) - ); + return LockInterceptor.intercept(this.walletAddr, submitTxCallback, lockId); } - async submitTx(signedTx: any) { - Logger.info(`Submitting tx: ${JSON.stringify(signedTx)}`); + async submitTx(signedTx: any, lockId?: string) { + Logger.info( + `Submitting tx: ${JSON.stringify({ lock_id: lockId, tx: signedTx })}` + ); const res = (await callKuber( `/api/${this.version}/tx?submit=true`, diff --git a/tests/govtool-frontend/playwright/package-lock.json b/tests/govtool-frontend/playwright/package-lock.json index 8c1c2433c..f229e2e72 100644 --- a/tests/govtool-frontend/playwright/package-lock.json +++ b/tests/govtool-frontend/playwright/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@cardanoapi/cardano-test-wallet": "^1.0.0", + "@cardanoapi/cardano-test-wallet": "^1.0.2", "@faker-js/faker": "^8.4.1", "@noble/curves": "^1.3.0", "@noble/ed25519": "^2.0.0", @@ -86,9 +86,9 @@ } }, "node_modules/@cardanoapi/cardano-test-wallet": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-1.0.0.tgz", - "integrity": "sha512-mua97Dqo0E1YbGanLTdq9AhmMe8E0HvmC6uwDFPe4LG3M817Pp/5mXxwUD6CfFbGANQ/PuSTJ8m28qerlw1Arg==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-1.0.2.tgz", + "integrity": "sha512-ABOOSoB0DUggcIwl6nj1v4/IhzFKPPV6krGLAv9RRmX5trkiOBLqGuSNrOlFU+7XELJzagDDwYS1ykhyuVD/HA==" }, "node_modules/@cbor-extract/cbor-extract-linux-x64": { "version": "2.2.0", @@ -3206,9 +3206,9 @@ "dev": true }, "@cardanoapi/cardano-test-wallet": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-1.0.0.tgz", - "integrity": "sha512-mua97Dqo0E1YbGanLTdq9AhmMe8E0HvmC6uwDFPe4LG3M817Pp/5mXxwUD6CfFbGANQ/PuSTJ8m28qerlw1Arg==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-1.0.2.tgz", + "integrity": "sha512-ABOOSoB0DUggcIwl6nj1v4/IhzFKPPV6krGLAv9RRmX5trkiOBLqGuSNrOlFU+7XELJzagDDwYS1ykhyuVD/HA==" }, "@cbor-extract/cbor-extract-linux-x64": { "version": "2.2.0", diff --git a/tests/govtool-frontend/playwright/package.json b/tests/govtool-frontend/playwright/package.json index c42c5ff45..3cb14402e 100644 --- a/tests/govtool-frontend/playwright/package.json +++ b/tests/govtool-frontend/playwright/package.json @@ -26,7 +26,7 @@ "format": "prettier . --write" }, "dependencies": { - "@cardanoapi/cardano-test-wallet": "^1.0.0", + "@cardanoapi/cardano-test-wallet": "^1.0.2", "@faker-js/faker": "^8.4.1", "@noble/curves": "^1.3.0", "@noble/ed25519": "^2.0.0", diff --git a/tests/govtool-frontend/playwright/playwright.config.ts b/tests/govtool-frontend/playwright/playwright.config.ts index caf1350e7..a2adcef75 100644 --- a/tests/govtool-frontend/playwright/playwright.config.ts +++ b/tests/govtool-frontend/playwright/playwright.config.ts @@ -27,7 +27,7 @@ export default defineConfig({ /*use Allure Playwright's testPlanFilter() to determine the grep parameter*/ grep: testPlanFilter(), /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: process.env.CI ? [["dot"], ["allure-playwright"]] : [["dot"]], + reporter: process.env.CI ? [["line"], ["allure-playwright"]] : [["line"]], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ @@ -43,6 +43,10 @@ export default defineConfig({ /* Configure projects for major browsers */ projects: [ + { + name: "faucet setup", + testMatch: "**/faucet.setup.ts", + }, { name: "auth setup", testMatch: "**/auth.setup.ts", @@ -50,18 +54,19 @@ export default defineConfig({ { name: "dRep setup", testMatch: "**/dRep.setup.ts", - dependencies: process.env.CI ? ["wallet bootstrap"] : [], + dependencies: ["faucet setup"], }, { name: "wallet bootstrap", testMatch: "**/wallet.bootstrap.ts", + dependencies: ["faucet setup"], }, - { - name: "transaction", - use: { ...devices["Desktop Chrome"] }, - testMatch: "**/*.tx.spec.ts", - dependencies: process.env.CI ? ["auth setup", "wallet bootstrap"] : [], - }, + // { + // name: "transaction", + // use: { ...devices["Desktop Chrome"] }, + // testMatch: "**/*.tx.spec.ts", + // dependencies: process.env.CI ? ["auth setup", "wallet bootstrap"] : [], + // }, { name: "loggedin (desktop)", use: { ...devices["Desktop Chrome"] }, @@ -80,11 +85,18 @@ export default defineConfig({ testMatch: "**/*.dRep.spec.ts", dependencies: process.env.CI ? ["auth setup", "dRep setup"] : [], }, + { + name: "delegation", + use: { ...devices["Desktop Chrome"] }, + testMatch: "**/*.delegation.spec.ts", + dependencies: process.env.CI ? ["auth setup", "dRep setup"] : [], + teardown: "cleanup delegation", + }, { name: "independent (desktop)", use: { ...devices["Desktop Chrome"] }, testIgnore: [ - "**/*.tx.spec.ts", + "**/*.delegation.spec.ts", "**/*.loggedin.spec.ts", "**/*.dRep.spec.ts", ], @@ -98,5 +110,9 @@ export default defineConfig({ "**/*.dRep.spec.ts", ], }, + { + name: "cleanup delegation", + testMatch: "delegation.teardown.ts", + }, ], }); diff --git a/tests/govtool-frontend/playwright/tests/2-delegation/delegation.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/2-delegation/delegation.delegation.spec.ts similarity index 72% rename from tests/govtool-frontend/playwright/tests/2-delegation/delegation.dRep.spec.ts rename to tests/govtool-frontend/playwright/tests/2-delegation/delegation.delegation.spec.ts index d027f40a2..92811984f 100644 --- a/tests/govtool-frontend/playwright/tests/2-delegation/delegation.dRep.spec.ts +++ b/tests/govtool-frontend/playwright/tests/2-delegation/delegation.delegation.spec.ts @@ -1,5 +1,9 @@ import environments from "@constants/environments"; -import { adaHolder01Wallet, dRep01Wallet } from "@constants/staticWallets"; +import { + adaHolder01Wallet, + adaHolder02Wallet, + dRep01Wallet, +} from "@constants/staticWallets"; import { createTempDRepAuth } from "@datafactory/createAuth"; import { test } from "@fixtures/walletExtension"; import { ShelleyWallet } from "@helpers/crypto"; @@ -45,7 +49,7 @@ test.describe("Delegate to myself", () => { [wallet.addressBech32(environments.networkId)], 600 ); - await pollTransaction(txRes.txId, txRes.address); + await pollTransaction(txRes.txId, txRes.lockInfo); const dRepAuth = await createTempDRepAuth(page, wallet); const dRepPage = await createNewPageWithWallet(browser, { storageState: dRepAuth, @@ -64,3 +68,25 @@ test.describe("Delegate to myself", () => { await expect(dRepPage.getByText("You are a Sole Voter")).toBeVisible(); }); }); + +test.describe("Change Delegation", () => { + test.use({ + storageState: ".auth/adaHolder02.json", + wallet: adaHolder02Wallet, + }); + + // Skipped: Blocked because delegation is not working + test.skip("2F. Should change delegated dRep @slow @critical", async ({ + page, + }) => { + const delegationPage = new DelegationPage(page); + await delegationPage.goto(); + delegationPage.delegateToDRep(dRep01Wallet.dRepId); + await waitForTxConfirmation(page); + + // await delegationPage.goto("/"); + // await adaHolderPage.getByTestId("change-dRep-button").click(); + // await delegationPage.delegateToDRep(dRep02Wallet.dRepId); + // await waitForTxConfirmation(page); + }); +}); diff --git a/tests/govtool-frontend/playwright/tests/2-delegation/delegation.tx.spec.ts b/tests/govtool-frontend/playwright/tests/2-delegation/delegation.tx.spec.ts deleted file mode 100644 index a172805b7..000000000 --- a/tests/govtool-frontend/playwright/tests/2-delegation/delegation.tx.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { adaHolder02Wallet, dRep01Wallet } from "@constants/staticWallets"; -import { test } from "@fixtures/walletExtension"; -import { waitForTxConfirmation } from "@helpers/transaction"; -import DelegationPage from "@pages/delegationPage"; - -test.use({ storageState: ".auth/adaHolder02.json", wallet: adaHolder02Wallet }); - -// Skipped: Blocked because delegation is not working -test.skip("2F. Should change delegated dRep @slow @critical", async ({ - page, -}) => { - const delegationPage = new DelegationPage(page); - await delegationPage.goto(); - delegationPage.delegateToDRep(dRep01Wallet.dRepId); - await waitForTxConfirmation(page); - - // await delegationPage.goto("/"); - // await adaHolderPage.getByTestId("change-dRep-button").click(); - // await delegationPage.delegateToDRep(dRep02Wallet.dRepId); - // await waitForTxConfirmation(page); -}); diff --git a/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts index 92ed56917..2e633866d 100644 --- a/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts +++ b/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts @@ -10,6 +10,7 @@ import DRepRegistrationPage from "@pages/dRepRegistrationPage"; import GovernanceActionsPage from "@pages/governanceActionsPage"; import { expect } from "@playwright/test"; import kuberService from "@services/kuberService"; +import * as crypto from "crypto"; test.describe("Logged in DReps", () => { test.use({ storageState: ".auth/dRep01.json", wallet: dRep01Wallet }); @@ -22,6 +23,16 @@ test.describe("Logged in DReps", () => { dRep01Wallet.dRepId ); // BUG: testId -> dRep-id-display-dashboard (It is taking sidebar dRep-id) }); + + test.use({ storageState: ".auth/dRep01.json", wallet: dRep01Wallet }); + + // Skipped: No option to update metadata + test.skip("3H. Should be able to update metadata @slow", async ({ page }) => { + page.getByTestId("change-metadata-button").click(); + page.getByTestId("url-input").fill("https://google.com"); + page.getByTestId("hash-input").fill(crypto.randomBytes(32).toString("hex")); + await expect(page.getByTestId("confirm-modal-button")).toBeVisible(); + }); }); test.describe("Temporary DReps", () => { @@ -36,7 +47,7 @@ test.describe("Temporary DReps", () => { [wallet.addressBech32(environments.networkId)], 600 ); - await pollTransaction(res.txId, res.address); + await pollTransaction(res.txId, res.lockInfo); const tempDRepAuth = await createTempDRepAuth(page, wallet); const dRepPage = await createNewPageWithWallet(browser, { @@ -66,7 +77,7 @@ test.describe("Temporary DReps", () => { convertBufferToHex(wallet.stakeKey.private), convertBufferToHex(wallet.stakeKey.pkh) ); - await pollTransaction(registrationRes.txId, registrationRes.address); + await pollTransaction(registrationRes.txId, registrationRes.lockInfo); const tempDRepAuth = await createTempDRepAuth(page, wallet); const dRepPage = await createNewPageWithWallet(browser, { @@ -95,12 +106,12 @@ test.describe("Temporary DReps", () => { convertBufferToHex(wallet.stakeKey.private), convertBufferToHex(wallet.stakeKey.pkh) ); - await pollTransaction(registrationRes.txId, registrationRes.address); + await pollTransaction(registrationRes.txId, registrationRes.lockInfo); const res = await kuberService.transferADA([ wallet.addressBech32(environments.networkId), ]); - await pollTransaction(res.txId, res.address); + await pollTransaction(res.txId, res.lockInfo); const dRepAuth = await createTempDRepAuth(page, wallet); const dRepPage = await createNewPageWithWallet(browser, { diff --git a/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.tx.spec.ts b/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.tx.spec.ts deleted file mode 100644 index 50798e04b..000000000 --- a/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.tx.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { dRep01Wallet } from "@constants/staticWallets"; -import { test } from "@fixtures/walletExtension"; -import { expect } from "@playwright/test"; -import * as crypto from "crypto"; - -test.describe("Logged in", () => { - test.use({ storageState: ".auth/dRep01.json", wallet: dRep01Wallet }); - - // Skipped: No option to update metadata - test.skip("3H. Should be able to update metadata @slow", async ({ page }) => { - page.getByTestId("change-metadata-button").click(); - page.getByTestId("url-input").fill("https://google.com"); - page.getByTestId("hash-input").fill(crypto.randomBytes(32).toString("hex")); - await expect(page.getByTestId("confirm-modal-button")).toBeVisible(); - }); -}); diff --git a/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts index 2844c24b8..dd13ab19b 100644 --- a/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts +++ b/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts @@ -112,13 +112,13 @@ test.describe("Perform voting", () => { convertBufferToHex(wallet.stakeKey.private), convertBufferToHex(wallet.stakeKey.pkh) ); - await pollTransaction(registrationRes.txId, registrationRes.address); + await pollTransaction(registrationRes.txId, registrationRes.lockInfo); const res = await kuberService.transferADA( [wallet.addressBech32(environments.networkId)], 40 ); - await pollTransaction(res.txId, registrationRes.address); + await pollTransaction(res.txId, registrationRes.lockInfo); const tempDRepAuth = await createTempDRepAuth(page, wallet); diff --git a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts index 39f9e7a8e..8f58286fb 100644 --- a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts +++ b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts @@ -1,13 +1,15 @@ -import { test } from "@fixtures/walletExtension"; import { user01Wallet } from "@constants/staticWallets"; -import { expect } from "@playwright/test"; +import { test } from "@fixtures/walletExtension"; import DRepRegistrationPage from "@pages/dRepRegistrationPage"; import DelegationPage from "@pages/delegationPage"; +import { expect } from "@playwright/test"; test.use({ storageState: ".auth/user01.json", wallet: user01Wallet }); // Skipped: No dRepId to validate -test.skip("6B. Provides error for invalid format @fast @smoke", async ({ page }) => { +test.skip("6B. Provides error for invalid format @fast @smoke", async ({ + page, +}) => { // invalid dRep delegation const delegationPage = new DelegationPage(page); await delegationPage.goto(); @@ -18,11 +20,11 @@ test.skip("6B. Provides error for invalid format @fast @smoke", async ({ page }) const dRepRegistrationPage = new DRepRegistrationPage(page); await dRepRegistrationPage.goto(); - await dRepRegistrationPage.urlInput.fill("abc"); - await expect(dRepRegistrationPage.urlInputError).toBeVisible(); + // await dRepRegistrationPage.urlInput.fill("abc"); + // await expect(dRepRegistrationPage.urlInputError).toBeVisible(); - await dRepRegistrationPage.hashInput.fill("abc"); - await expect(dRepRegistrationPage.hashInputError).toBeVisible(); + // await dRepRegistrationPage.hashInput.fill("abc"); + // await expect(dRepRegistrationPage.hashInputError).toBeVisible(); }); test("6D: Proper label and recognition of the testnet network @fast @smoke", async ({ diff --git a/tests/govtool-frontend/playwright/tests/dRep.setup.ts b/tests/govtool-frontend/playwright/tests/dRep.setup.ts index 3e844251a..38c587663 100644 --- a/tests/govtool-frontend/playwright/tests/dRep.setup.ts +++ b/tests/govtool-frontend/playwright/tests/dRep.setup.ts @@ -18,7 +18,7 @@ dRepWallets.forEach((wallet) => { wallet.stake.pkh ); - await pollTransaction(res.txId, res.address); + await pollTransaction(res.txId, res.lockInfo); } catch (err) { if (err.status === 400) { expect(true, "DRep already registered").toBeTruthy(); @@ -36,7 +36,8 @@ setup("Setup dRep metadata", async () => { body: JSON.stringify(dRepInfo), }); Logger.success("Uploaded dRep metadata to bucket"); - } catch (e) { - Logger.fail(`Failed to upload dRep metadata: ${e}`); + } catch (err) { + Logger.fail(`Failed to upload dRep metadata: ${err}`); + throw err; } }); diff --git a/tests/govtool-frontend/playwright/tests/adaholder.teardown.ts b/tests/govtool-frontend/playwright/tests/delegation.teardown.ts similarity index 66% rename from tests/govtool-frontend/playwright/tests/adaholder.teardown.ts rename to tests/govtool-frontend/playwright/tests/delegation.teardown.ts index 49c21b8cc..986ab1a45 100644 --- a/tests/govtool-frontend/playwright/tests/adaholder.teardown.ts +++ b/tests/govtool-frontend/playwright/tests/delegation.teardown.ts @@ -1,15 +1,18 @@ +import environments from "@constants/environments"; import { adaHolderWallets } from "@constants/staticWallets"; import { pollTransaction } from "@helpers/transaction"; import { test as cleanup } from "@playwright/test"; import kuberService from "@services/kuberService"; +cleanup.describe.configure({ timeout: environments.txTimeOut }); + cleanup(`Abstain delegation`, async () => { const stakePrivKeys = adaHolderWallets.map((wallet) => wallet.stake.private); const stakePkhs = adaHolderWallets.map((wallet) => wallet.stake.pkh); - const { txId, address } = await kuberService.abstainDelegations( + const { txId, lockInfo } = await kuberService.abstainDelegations( stakePrivKeys, stakePkhs ); - await pollTransaction(txId, address); + await pollTransaction(txId, lockInfo); }); diff --git a/tests/govtool-frontend/playwright/tests/faucet.setup.ts b/tests/govtool-frontend/playwright/tests/faucet.setup.ts new file mode 100644 index 000000000..5aeb32639 --- /dev/null +++ b/tests/govtool-frontend/playwright/tests/faucet.setup.ts @@ -0,0 +1,16 @@ +import { faucetWallet } from "@constants/staticWallets"; +import { pollTransaction } from "@helpers/transaction"; +import { test as setup } from "@playwright/test"; +import { loadAmountFromFaucet } from "@services/faucetService"; +import kuberService from "@services/kuberService"; +import environments from "lib/constants/environments"; + +setup.describe.configure({ mode: "serial", timeout: environments.txTimeOut }); + +setup("Fund faucet wallet", async () => { + const balance = await kuberService.getBalance(faucetWallet.address); + if (balance > 2000) return; + + const res = await loadAmountFromFaucet(faucetWallet.address); + await pollTransaction(res.txid); +}); diff --git a/tests/govtool-frontend/playwright/tests/wallet.bootstrap.ts b/tests/govtool-frontend/playwright/tests/wallet.bootstrap.ts index 55ded87ff..1d7397fda 100644 --- a/tests/govtool-frontend/playwright/tests/wallet.bootstrap.ts +++ b/tests/govtool-frontend/playwright/tests/wallet.bootstrap.ts @@ -1,15 +1,10 @@ -import { - adaHolderWallets, - dRepWallets, - faucetWallet, -} from "@constants/staticWallets"; +import { adaHolderWallets, dRepWallets } from "@constants/staticWallets"; import { ShelleyWallet } from "@helpers/crypto"; import extractDRepsFromStakePubKey from "@helpers/extractDRepsFromStakePubkey"; import generateShellyWallets from "@helpers/generateShellyWallets"; import setupWallets from "@helpers/setupWallets"; import { pollTransaction } from "@helpers/transaction"; import { expect, test as setup } from "@playwright/test"; -import { loadAmountFromFaucet } from "@services/faucetService"; import kuberService from "@services/kuberService"; import { writeFile } from "fs"; import environments from "lib/constants/environments"; @@ -24,30 +19,22 @@ setup("Setup mock wallets", async () => { saveWallets(wallets); }); -setup("Fund faucet wallet", async () => { - const balance = await kuberService.getBalance(faucetWallet.address); - if (balance > 2000) return; - - const res = await loadAmountFromFaucet(faucetWallet.address); - await pollTransaction(res.txid); -}); - setup("Fund static wallets", async () => { const addresses = [...adaHolderWallets, ...dRepWallets].map((e) => e.address); const res = await kuberService.transferADA(addresses); - await pollTransaction(res.txId, res.address); + await pollTransaction(res.txId); }); for (const wallet of [...adaHolderWallets, ...dRepWallets]) { setup(`Register stake of static wallet: ${wallet.address}`, async () => { try { - const { txId, address } = await kuberService.registerStake( + const { txId, lockInfo } = await kuberService.registerStake( wallet.stake.private, wallet.stake.pkh, wallet.payment.private, wallet.address ); - await pollTransaction(txId, address); + await pollTransaction(txId, lockInfo); } catch (err) { if (err.status === 400) { expect(true, "Stake already registered").toBeTruthy();