Skip to content

e2e: Add test for testing different address types#470

Open
Abhay349 wants to merge 1 commit intocaravan-bitcoin:mainfrom
Abhay349:b3
Open

e2e: Add test for testing different address types#470
Abhay349 wants to merge 1 commit intocaravan-bitcoin:mainfrom
Abhay349:b3

Conversation

@Abhay349
Copy link

@Abhay349 Abhay349 commented Feb 8, 2026

What kind of change does this PR introduce?

  • Test improvement / E2E test coverage

Issue Number:

Fixes subtask of #442

If relevant, did you update the documentation?

  • Not applicable (test-only change)

Summary
This PR adds, parameterized end-to-end tests to validate different wallet address types in the Caravan coordinator.

Previously, E2E tests mainly covered the default address behavior. This change ensures comprehensive coverage for:

P2WSH (Native SegWit): Verifies correct address generation (bcrt1q...) and fund reception.
P2SH-P2WSH (Nested SegWit): Verifies correct address generation (2...) and fund reception.
P2TR (Taproot): Test scaffold included but currently skipped.
For each active type, the test validates:

  1. Importing a wallet configuration specific to that address type.
  2. Verifying the generated receive address matches the expected regex format.
  3. Confirming the wallet can receive a transaction (verified by the address path index incrementing locally).

Does this PR introduce a breaking change?

-No

Checklist

  • I have tested my changes thoroughly.
  • I have added or updated tests to cover my changes (if applicable).
  • I have verified that test coverage meets or exceeds 95% (if applicable).
  • I have run the test suite locally, and all tests pass.
  • I have written tests for all new changes/features
  • I have followed the project's coding style and conventions.
  • I have created a changeset to document my changes (npm run changeset)

Other information

P2TR (Taproot) skipped: The P2TR test case is explicitly marked as skip: true. Investigation into
caravan-bitcoin/src/types/addresses.tsrevealed that while P2TR is defined as a valid
MultisigAddressType, it is currently commented as "not able to be used anywhere yet". The test is preserved to enable immediate verification once support is fully implemented in the underlying package.

All coordinator E2E tests (P2WSH and P2SH-P2WSH) pass locally using the Docker-based setup.

Have you read the contributing guide?

Yes

@changeset-bot
Copy link

changeset-bot bot commented Feb 8, 2026

⚠️ No Changeset found

Latest commit: c763cb9

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Feb 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
caravan-coordinator Ready Ready Preview, Comment Mar 11, 2026 6:22pm

Request Review

Copy link
Contributor

@Legend101Zz Legend101Zz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a minor comment , and rest it looks really good to me , can you please also attach a screenshot of the working e2e test ? Thanks

{
type: "P2SH-P2WSH",
label: "Nested SegWit (P2SH-P2WSH)",
regex: /^2[MN][a-zA-Z0-9]{33}$/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question here , Base58 addresses (like P2SH) are not fixed length. While they are usually 35 characters, they can technically be 33 or 34 characters depending on the number of leading zeros in the hash. maybe Loosen the length requirement and refine the allowed characters ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree and that makes sense, I will loosen regex to avoid enforcing a strict length.
I’m planning to change it to something like:

     /^2[1-9A-HJ-NP-Za-km-z]{30,40}$/

so that we can validate structure without assuming an exact length, let me know if it looks good.
Thanks for guidance :)

@Abhay349
Copy link
Author

Screenshot 2026-02-10 at 18 41 45 Screenshot 2026-02-10 at 18 41 20 Screenshot 2026-02-10 at 18 40 12

@Abhay349
Copy link
Author

Hi @Legend101Zz I have attached screenshots of working e2e tests and also updated the regex for P2SH-P2WSH.
Let me know if there are issues, happy to iterate on further feedback.
Thanks :)

@Legend101Zz
Copy link
Contributor

Hi @Abhay349
I’ve recently opened an issue related to a problem in our E2E test suite:
#483

I’m currently working on resolving that. Until the fix is implemented and merged, I’ll hold off on reviewing this PR since the changes from that fix will likely require some adjustments to your code as well.

Thanks a lot for your patience, and really appreciate the contribution!

@Legend101Zz
Copy link
Contributor

Hi @Abhay349 Thanks for your patience. Could you please pull in the latest changes and review the updated E2E setup we’ve implemented, then adjust your changes accordingly?

Signed-off-by: Abhay349 <pandeyabhay967@gmail.com>
@Abhay349
Copy link
Author

Hi @bucko13 @Legend101Zz I have pushed a fix addressing updates, pls take a look and let me know if I can proceed for similer changes in other PRs..

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Playwright E2E spec to validate Caravan Coordinator behavior across multiple multisig wallet address types (currently P2WSH + P2SH-P2WSH, with P2TR scaffolded but skipped), expanding coverage beyond the default address type.

Changes:

  • Introduces a parameterized E2E test that imports a wallet config per address type and verifies the generated receive address format.
  • Adds a flow to send funds to the generated address and assert the receive-path index advances.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +76 to +86
// Send 1 BTC
await btcClient?.sendToAddress(senderWallet, address, 1);

// Wait for the UI to reflect new tx / increment path
await expect.poll(async () => {
return await receiveTab.getCurrentPathSuffix();
}, {
message: "Address path should increment after receiving funds",
timeout: 30000,
intervals: [1000]
}).not.toBe(initialSuffix);
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After sendToAddress, the test doesn’t mine a block or trigger a UI refresh. Other e2e flows mine blocks and call walletNav.refresh() to ensure Bitcoin Core reports the UTXO and Caravan updates; without this, the path suffix may never change and the poll can time out. Also, btcClient is a required fixture, so avoid optional chaining here to fail loudly if it’s ever missing.

Copilot uses AI. Check for mistakes.
}).not.toBe(initialSuffix);

} catch (error) {
throw new Error(`Failed testing ${type}: ${error}`);
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The try/catch rethrows a new Error using ${error}, which drops the original stack and can hide Playwright assertion details. Prefer letting the original error bubble up, or rethrow while preserving cause (and use error instanceof Error ? error.message : String(error) for the message).

Suggested change
throw new Error(`Failed testing ${type}: ${error}`);
if (error instanceof Error) {
throw new Error(`Failed testing ${type}: ${error.message}`, { cause: error });
}
throw new Error(`Failed testing ${type}: ${String(error)}`);

Copilot uses AI. Check for mistakes.
{
type: "P2TR",
label: "Taproot (P2TR)",
regex: /^bcrt1p.{50,}$/,
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The (currently skipped) P2TR address regex is very permissive (.{50,}) and could pass invalid addresses once the test is enabled. It would be safer to constrain it to the bech32m charset/length expected on regtest (e.g., lowercase alphanumerics with a fixed length).

Suggested change
regex: /^bcrt1p.{50,}$/,
regex: /^bcrt1p[023456789acdefghjklmnpqrstuvwxyz]{52}$/,

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +30
test.beforeEach(async ({ page }) => {
// Ensure we start with a slight delay to allow any previous cleanup
await page.waitForTimeout(1000);
});
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fixed waitForTimeout(1000) introduces an unconditional 1s delay per test run and can hide real synchronization issues. Prefer waiting on a specific UI condition (e.g., tab button visible) or remove this delay if it’s not strictly required.

Suggested change
test.beforeEach(async ({ page }) => {
// Ensure we start with a slight delay to allow any previous cleanup
await page.waitForTimeout(1000);
});

Copilot uses AI. Check for mistakes.
Comment on lines +36 to +43
// 1. Get Base Config
const downloadedWalletFile = testStateManager.getDownloadedWalletFile();
if (!fs.existsSync(downloadedWalletFile)) {
throw new Error(`Wallet file not found at ${downloadedWalletFile}. Please run previous tests.`);
}

const walletConfig = JSON.parse(fs.readFileSync(downloadedWalletFile, "utf-8"));

Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test re-implements wallet-config precondition checks (existsSync + JSON.parse) inline. The e2e suite already has assertWalletFileDownloaded / assertModifiedWalletConfig helpers to fail fast with consistent diagnostics—consider using one of those in a beforeAll and then just read the file path here.

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +60
const tempConfigPath = path.join(
path.dirname(downloadedWalletFile),
`wallet_config_${type}.json`
);
fs.writeFileSync(tempConfigPath, JSON.stringify(walletConfig, null, 2));

Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The temporary config file is written next to the downloaded wallet file and never cleaned up. Over time this can clutter the shared download dir and make debugging harder; consider writing it to the test state upload/temp dir and deleting it in a finally/afterEach.

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +66
await page.locator("button[role=tab][type=button]:has-text('Receive')").click();
const address = await receiveTab.getCurrentAddress();
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test clicks the Receive tab using a raw selector even though a walletNav fixture exists with switchToTab(). Using the page object keeps selectors centralized and reduces flakiness if the UI markup changes.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants