Skip to content

Commit

Permalink
e2e real wallet data using esbuild
Browse files Browse the repository at this point in the history
  • Loading branch information
gbarkhatov committed Oct 7, 2024
1 parent 2bab9f9 commit c4a5e87
Show file tree
Hide file tree
Showing 46 changed files with 3,478 additions and 1,579 deletions.
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ web_modules/
.env.test.local
.env.production.local
.env.local
.env.mainnet
.env.signet

# parcel-bundler cache (https://parceljs.org/)
.cache
Expand Down
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ where,
- `NEXT_PUBLIC_POINTS_API_URL` specifies the Points API to use for the points
system
- `NEXT_PUBLIC_NETWORK` specifies the BTC network environment
- `NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES` boolean value to indicate whether display
- `NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES` boolean value to indicate whether display
testing network related message. Default to true

Then, to start a development server:
Expand All @@ -36,3 +36,26 @@ npm run dev

Instructions for wallet integration can be found in this
[document](./docs/WalletIntegration.md).

## E2E
The end-to-end (E2E) tests are implemented using Playwright. These tests simulate user interactions with the application to ensure that all functionalities work as expected across different Bitcoin network environments (`mainnet` and `signet`). The tests utilize *some* mocked data to prevent interactions with real Bitcoin networks, ensuring safe and reliable testing.

### Prerequisites
Before running the E2E tests, ensure that you have completed the following steps:

- Environment Configuration: Set up the necessary environment variables.
- Install Dependencies: Ensure all dependencies are installed.

### Environment Configuration
The E2E tests can be run using either the .env.local file or the specific environment files .env.mainnet and .env.signet. These files should contain the following environment variables:

- `NEXT_PUBLIC_NETWORK`: Specifies the BTC network environment (mainnet or signet).
- `NEXT_PUBLIC_MEMPOOL_API`: Specifies the mempool.space host to use for Bitcoin node queries.
- `NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES`: Boolean value to indicate whether to display testing network-related messages.
- `NEXT_PUBLIC_API_URL`: Specifies the back-end API to use for staking system queries.

### Commands to run E2E
- `npx playwright install` to install playwright. This is *required* to do after the `npm install`
- Stop the current `dev` server in case you ran it with `npm run dev`
- `npm run test:e2e` to run the test using the network in `.env.local`
- `npm run test:e2e:full` to run the test using the networks in `.env.mainnet` and `.env.signet`
106 changes: 91 additions & 15 deletions e2e/balanceAddress.spec.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,96 @@
import { expect, test } from "@playwright/test";
import { expect, Page, test } from "@playwright/test";

import { satoshiToBtc } from "@/utils/btcConversions";
import { maxDecimals } from "@/utils/maxDecimals";
import { trim } from "@/utils/trim";

import {
NATIVE_SEGWIT_MAINNET_ADDRESS,
NATIVE_SEGWIT_SIGNET_ADDRESS,
TAPROOT_MAINNET_ADDRESS,
TAPROOT_SIGNET_ADDRESS,
} from "./constants/wallet";
import { setupWalletConnection } from "./helper/connect";
import { mockNetwork } from "./helper/mockNetwork";
import { extractNumericBalance } from "./helper/utils";
import { nativeSegwitMainnetBalance } from "./mock/mainnet/wallet/nativeSegwit/utxos";
import { taprootMainnetBalance } from "./mock/mainnet/wallet/taproot/utxos";
import { nativeSegwitSignetBalance } from "./mock/signet/wallet/nativeSegwit/utxos";
import { taprootSignetBalance } from "./mock/signet/wallet/taproot/utxos";

type Network = "mainnet" | "signet";
type AddressType = "taproot" | "nativeSegwit";

// Determine the network from environment variable or default to 'mainnet'
const network: Network =
(process.env.NEXT_PUBLIC_NETWORK as Network) || "mainnet";

// Define the address types to test
const addressTypes: AddressType[] = ["taproot", "nativeSegwit"];

// Mappings for expected addresses based on network and address type
const expectedAddresses: Record<AddressType, Record<Network, string>> = {
taproot: {
mainnet: TAPROOT_MAINNET_ADDRESS,
signet: TAPROOT_SIGNET_ADDRESS,
},
nativeSegwit: {
mainnet: NATIVE_SEGWIT_MAINNET_ADDRESS,
signet: NATIVE_SEGWIT_SIGNET_ADDRESS,
},
};

// Mappings for expected balances based on network and address type
const expectedBalances: Record<AddressType, Record<Network, number>> = {
taproot: {
mainnet: taprootMainnetBalance,
signet: taprootSignetBalance,
},
nativeSegwit: {
mainnet: nativeSegwitMainnetBalance,
signet: nativeSegwitSignetBalance,
},
};

// Reusable function for checking address
async function checkAddress(page: Page, expectedAddress: string) {
const address = await page.getByTestId("address").textContent();
expect(address).toBe(trim(expectedAddress));
}

// Reusable function for checking balance
async function checkBalance(page: Page, expectedBalance: number) {
const balanceText = await page.getByTestId("balance").textContent();
const balance = maxDecimals(extractNumericBalance(balanceText), 8);
expect(balance).toBe(satoshiToBtc(expectedBalance));
}

test.describe("Balance and address checks after connection", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/");
await setupWalletConnection(page);
});

test("balance is correct", async ({ page }) => {
const balance = await page.getByTestId("balance").textContent();
expect(balance).toBe("0.12345678 BTC");
});

test("address is correct", async ({ page }) => {
const address = await page.getByTestId("address").textContent();
expect(address).toBe("bc1p...97sd");
});
// Iterate over each address type
for (const type of addressTypes) {
test.describe(`${type} address on ${network}`, () => {
// Mock the network
test.beforeEach(async ({ page }) => {
await mockNetwork(page, network);
});

// Setup wallet connection before each test
test.beforeEach(async ({ page }) => {
await setupWalletConnection(page, network, type);
});

test(`should verify the ${type} address and balance on ${network}`, async ({
page,
}) => {
const expectedAddress = expectedAddresses[type][network];
const expectedBalance = expectedBalances[type][network];

// Perform address check
await checkAddress(page, expectedAddress);

// Perform balance check
await checkBalance(page, expectedBalance);
});
});
}
});
3 changes: 1 addition & 2 deletions e2e/constants/staking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ import { satoshiToBtc } from "@/utils/btcConversions";

export const STAKING_AMOUNT_SAT = 50000;
export const STAKING_AMOUNT_BTC = satoshiToBtc(STAKING_AMOUNT_SAT);
export const STAKING_TX_HASH =
"47af61d63bcc6c513561d9a1198d082052cc07a81f50c6f130653f0a6ecc0fc1";
export const STAKING_DURATION_BLOCKS = 150;
8 changes: 8 additions & 0 deletions e2e/constants/text.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Constants for selectors and texts

export const BUTTON_TEXT_CONNECT_TO_BTC = "Connect to BTC";
export const LABEL_TEXT_ACCEPT_TERMS = "I certify that I have read";
export const LABEL_TEXT_NO_INSCRIPTIONS = "I certify that there are no";
export const LABEL_TEXT_HW_WALLET = "I acknowledge that Keystone via QR code";
export const BUTTON_TEXT_BROWSER = "Browser";
export const INPUT_DURATION_BLOCKS = "Blocks";
32 changes: 32 additions & 0 deletions e2e/constants/wallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Don't use real funds with these addresses
export const MNEMONIC =
"baby baby baby baby baby baby baby rocket rocket rocket rocket science";

// The following addresses are derived from the above mnemonic
export const TAPROOT_MAINNET_ADDRESS =
"bc1p620x2d0wvycj0y7jmc0lxytk0m64swcx2lp430grtn0klqwugpcsgwalan";
export const TAPROOT_MAINNET_PK =
"038f561718d7f3ead37bd57e7b68360325db2263acfbbc8cb6b129e768d27aa46d";
export const TAPROOT_MAINNET_SCRIPT_PUBKEY =
"5120d29e6535ee61312793d2de1ff311767ef5583b0657c358bd035cdf6f81dc4071";

export const NATIVE_SEGWIT_MAINNET_ADDRESS =
"bc1q7w09t8gl84c7ksus5nt3r2eg0qexk987hk9n23";
export const NATIVE_SEGWIT_MAINNET_PK =
"02ed32cf86745ea2c7a13f72b3194a576c249736e0b773e1a9f837767d60a3adcf";
export const NATIVE_SEGWIT_MAINNET_SCRIPT_PUBKEY =
"0014f39e559d1f3d71eb4390a4d711ab2878326b14fe";

export const TAPROOT_SIGNET_ADDRESS =
"tb1pc29r075qcgypvxzaq34680sk3epwv3xrqu4fnkskrqesd65d9yjqun5x5j";
export const TAPROOT_SIGNET_PK =
"025bf662d62fdfaa781c6ecb6b533d50f5a8a1b6892e9fe5609ccccd07e041b20a";
export const TAPROOT_SIGNET_SCRIPT_PUBKEY =
"5120c28a37fa80c20816185d046ba3be168e42e644c3072a99da16183306ea8d2924";

export const NATIVE_SEGWIT_SIGNET_ADDRESS =
"tb1qrspcmpwh4k05xlflx7fqz5dmgpt06fydfmyzyr";
export const NATIVE_SEGWIT_SIGNET_PK =
"026b4ebd2b5ec63b8e9260c540921e46e75bbdcc42cf14bc3c0274e8d6a544bda1";
export const NATIVE_SEGWIT_SIGNET_SCRIPT_PUBKEY =
"00141c038d85d7ad9f437d3f37920151bb4056fd248d";
Loading

0 comments on commit c4a5e87

Please sign in to comment.