From 4682cfc98e22916a1db155b3abd1fc2f37f8fe74 Mon Sep 17 00:00:00 2001 From: Min Htet Oo Date: Fri, 7 Jun 2024 14:20:12 +0800 Subject: [PATCH] test: add e2e test for demo config workflow --- .testcaferc.json | 2 +- integration/helper.ts | 2 +- integration/load-demo-config.spec.ts | 59 +++++++++++++++++++ src/common/config/decrypt.tsx | 19 +++++- .../ConfigFileDropZone/ConfigFileDropZone.tsx | 1 + src/components/Home/Home.tsx | 3 +- .../WalletDecryptionContainer.tsx | 36 +++++++---- src/constants/demo-config.js | 4 +- 8 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 integration/load-demo-config.spec.ts diff --git a/.testcaferc.json b/.testcaferc.json index 1a082ef5..4cffbb14 100644 --- a/.testcaferc.json +++ b/.testcaferc.json @@ -1,6 +1,6 @@ { "appCommand": "npm run serve-static", - "src": ["integration/**/*.spec.ts"], + "src": ["integration/load-demo-config.spec.ts"], "cache": true, "compilerOptions": { "typescript": { diff --git a/integration/helper.ts b/integration/helper.ts index 8dd52e44..e170ac18 100644 --- a/integration/helper.ts +++ b/integration/helper.ts @@ -1,7 +1,7 @@ import { Selector, t } from "testcafe"; const PasswordField = Selector("[data-testid='password-field']"); -const ButtonLogin = Selector("[data-testid='login-button']"); +export const ButtonLogin = Selector("[data-testid='login-button']"); const ConfigFileDropZoneInput = Selector("[data-testid='config-file-dropzone'] input"); // fixtures diff --git a/integration/load-demo-config.spec.ts b/integration/load-demo-config.spec.ts new file mode 100644 index 00000000..65cf1741 --- /dev/null +++ b/integration/load-demo-config.spec.ts @@ -0,0 +1,59 @@ +import { Selector } from "testcafe"; + +const LoadDemoConfigFileBtn = Selector("[data-testid='load-demo-config-button']"); +const FillFormTitle = Selector("[data-testid='fill-form-title']"); +const ProgressBar = Selector("[data-testid='progress-bar']"); +const EblBeneficiaryField = Selector("[data-testid='transferable-record-beneficiary-input']"); +const EblHolderField = Selector("[data-testid='transferable-record-holder-input']"); +const SubmitButton = Selector("[data-testid='form-submit-button']"); +const EblNumberField = Selector("input#root_blNumber"); +const EblScacField = Selector("input#root_scac"); +const ProcessTitle = Selector('[data-testid="process-title"]'); +const IssuedFileName = Selector('[data-testid="file-name"]'); +const DocumentDownloadBtn = Selector('[data-testid="download-file-button"]'); +const ProcessAnotherDocBtn = Selector('[data-testid="process-another-document-button"]'); + +fixture("Demo Config File").page(`http://localhost:3000`); +const Button = Selector("button"); + +test("can able to load demo config file and issue example documents", async (t) => { + // ################ 1. Load Demo Config + // load demo config file + await t.click(LoadDemoConfigFileBtn); + await t.expect(ProgressBar.textContent).contains("1"); + + // ################ 2. Issue Bill of Lading Document + // select Bill of Laiding Document + await t.click(Button.withText("TradeTrust Bill of Lading v2 (Carrier)")); + await t.expect(FillFormTitle.textContent).contains("Fill and Preview Form"); + await t.expect(ProgressBar.textContent).contains("2"); + + // fill the form + await t.typeText(EblBeneficiaryField, "0xF11e3850F0bb8C72925c329EC446a2026cd4bB94"); + await t.typeText(EblHolderField, "0xF11e3850F0bb8C72925c329EC446a2026cd4bB94"); + await t.typeText(EblNumberField, "MY-BL-NUMBER"); + await t.typeText(EblScacField, "My-EBL-SCAC"); + // submit form + await t.click(SubmitButton); + + // check if bill of lading is created + await t.expect(ProcessTitle.innerText).eql("Document(s) issued successfully", { timeout: 20000 }); // cater for file issue delay + await t.expect(IssuedFileName.textContent).contains("TradeTrust-Bill-of-Lading-v2-(Carrier)-1-stability.tt"); + await t.expect(DocumentDownloadBtn.exists).ok("Download button for document doesn't exist"); + + // ################ 3. Issue ChAFTA Certificate of Origin + await t.click(ProcessAnotherDocBtn); + await t.click(Button.withText("TradeTrust ChAFTA Certificate of Origin v2")); + await t.click(SubmitButton); + await t.expect(ProcessTitle.innerText).eql("Document(s) issued successfully", { timeout: 20000 }); // cater for file issuance delay + await t.expect(IssuedFileName.textContent).contains("TradeTrust-ChAFTA-Certificate-of-Origin-v2-1-stability.tt"); + await t.expect(DocumentDownloadBtn.exists).ok("Download button for document doesn't exist"); + + // ################ 4. Issue TradeTrust Invoice DNS-DID + await t.click(ProcessAnotherDocBtn); + await t.click(Button.withText("TradeTrust Invoice v2 (DNS-DID)")); + await t.click(SubmitButton); + await t.expect(ProcessTitle.innerText).eql("Document(s) issued successfully", { timeout: 20000 }); // cater for file issuance delay + await t.expect(IssuedFileName.textContent).contains("TradeTrust-Invoice-v2-(DNS-DID)-1-stability.tt"); + await t.expect(DocumentDownloadBtn.exists).ok("Download button for document doesn't exist"); +}); diff --git a/src/common/config/decrypt.tsx b/src/common/config/decrypt.tsx index d4a0b514..1cb315b1 100644 --- a/src/common/config/decrypt.tsx +++ b/src/common/config/decrypt.tsx @@ -1,9 +1,25 @@ import { ProviderDetails, utils } from "@tradetrust-tt/tt-verify"; -import { providers, Wallet } from "ethers"; +import { ethers, providers, Wallet } from "ethers"; import { AwsKmsSigner } from "@govtechsg/ethers-aws-kms-signer"; import { ChainInfo } from "../../constants/chainInfo"; import { AwsKmwSignerOption, ConfigFile, ConnectedSigner } from "../../types"; import { getChainInfoFromNetworkName, isWalletOption } from "../utils"; +import { DEMO_PRIVATE_KEY } from "../../constants/demo-config"; + +export const loadDemoWallet = async (config: ConfigFile): Promise => { + const chainId = getChainInfoFromNetworkName(config.network).chainId; + const rpcUrl = ChainInfo[chainId].rpcUrl; + const opts: ProviderDetails = rpcUrl + ? { url: rpcUrl } + : { + network: config.network, + providerType: "infura", + }; + + const provider = config.network === "local" ? new providers.JsonRpcProvider() : utils.generateProvider(opts); + const wallet = new ethers.Wallet(DEMO_PRIVATE_KEY); + return wallet.connect(provider); +}; export const decryptWalletOrSigner = async ( config: ConfigFile, @@ -20,6 +36,7 @@ export const decryptWalletOrSigner = async ( }; const provider = config.network === "local" ? new providers.JsonRpcProvider() : utils.generateProvider(opts); + if (isWalletOption(config.wallet)) { // For backward compatibility when the wallet is still string return decryptEncryptedJson(config.wallet, password, progressCallback, provider); diff --git a/src/components/Home/ConfigFileDropZone/ConfigFileDropZone.tsx b/src/components/Home/ConfigFileDropZone/ConfigFileDropZone.tsx index 0dc49911..4de09838 100644 --- a/src/components/Home/ConfigFileDropZone/ConfigFileDropZone.tsx +++ b/src/components/Home/ConfigFileDropZone/ConfigFileDropZone.tsx @@ -85,6 +85,7 @@ export const ConfigFileDropZone: FunctionComponent = ({ onCo