From 908c16b74f67787002475987a74796c4fae5f7cc Mon Sep 17 00:00:00 2001 From: Dmitriy E Date: Wed, 18 Feb 2026 18:05:09 +0300 Subject: [PATCH 01/10] feat: add NWC faucet integration test --- src/test/helpers.ts | 51 +++++++++++++++++++++++++++++++++++++ src/test/nwc-faucet.test.ts | 27 ++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/test/helpers.ts create mode 100644 src/test/nwc-faucet.test.ts diff --git a/src/test/helpers.ts b/src/test/helpers.ts new file mode 100644 index 00000000..16b5af18 --- /dev/null +++ b/src/test/helpers.ts @@ -0,0 +1,51 @@ +/** + * Test helpers for integration tests using the NWC faucet. + * @see https://github.com/getAlby/cli/tree/master/src/test + */ + +export interface TestWallet { + nwcUrl: string; + lightningAddress: string; +} + +const FAUCET_URL = "https://faucet.nwc.dev"; + +/** + * Creates a test wallet via the NWC faucet with the given balance in sats. + * Retries on failure (faucet can be rate-limited or temporarily unavailable). + */ +export async function createTestWallet( + balanceSats = 10_000, + retries = 5, +): Promise { + for (let i = 0; i < retries; i++) { + try { + const response = await fetch(`${FAUCET_URL}?balance=${balanceSats}`, { + method: "POST", + }); + if (!response.ok) { + if (i < retries - 1) { + await new Promise((r) => setTimeout(r, 2000 * (i + 1))); + continue; + } + throw new Error(`Faucet request failed: ${response.status}`); + } + const nwcUrl = (await response.text()).trim(); + const lud16Match = nwcUrl.match(/lud16=([^&\s]+)/); + if (!lud16Match) { + throw new Error("No lud16 in NWC URL"); + } + return { + nwcUrl, + lightningAddress: decodeURIComponent(lud16Match[1]), + }; + } catch (error) { + if (i < retries - 1) { + await new Promise((r) => setTimeout(r, 2000 * (i + 1))); + continue; + } + throw error; + } + } + throw new Error("Failed to create test wallet"); +} diff --git a/src/test/nwc-faucet.test.ts b/src/test/nwc-faucet.test.ts new file mode 100644 index 00000000..2fa48377 --- /dev/null +++ b/src/test/nwc-faucet.test.ts @@ -0,0 +1,27 @@ +import "websocket-polyfill"; +import { NWCClient } from "../nwc/NWCClient"; +import { createTestWallet } from "./helpers"; + +/** + * Integration test using the NWC faucet. + * Creates a wallet with 10_000 sats and verifies the balance via get_balance. + * Requires network access. + */ +describe("NWC faucet integration", () => { + const EXPECTED_BALANCE_SATS = 10_000; + const EXPECTED_BALANCE_MSATS = EXPECTED_BALANCE_SATS * 1000; + + test( + "creates wallet via faucet and balance is 10_000 sats", + async () => { + const { nwcUrl } = await createTestWallet(EXPECTED_BALANCE_SATS); + + const nwc = new NWCClient({ nostrWalletConnectUrl: nwcUrl }); + const result = await nwc.getBalance(); + nwc.close(); + + expect(result.balance).toBe(EXPECTED_BALANCE_MSATS); + }, + 30_000, + ); +}); From b2ac59d048ae489ece41192480d9bb56751eedd5 Mon Sep 17 00:00:00 2001 From: Dmitriy E Date: Thu, 19 Feb 2026 09:46:17 +0300 Subject: [PATCH 02/10] refactor(test): move NWC faucet test to e2e directory --- {src/test => e2e}/helpers.ts | 2 +- {src/test => e2e}/nwc-faucet.test.ts | 4 ++-- jest.config.ts | 2 +- jest.e2e.config.ts | 7 +++++++ package.json | 1 + 5 files changed, 12 insertions(+), 4 deletions(-) rename {src/test => e2e}/helpers.ts (95%) rename {src/test => e2e}/nwc-faucet.test.ts (88%) create mode 100644 jest.e2e.config.ts diff --git a/src/test/helpers.ts b/e2e/helpers.ts similarity index 95% rename from src/test/helpers.ts rename to e2e/helpers.ts index 16b5af18..7ba64fcc 100644 --- a/src/test/helpers.ts +++ b/e2e/helpers.ts @@ -1,5 +1,5 @@ /** - * Test helpers for integration tests using the NWC faucet. + * Test helpers for E2E integration tests using the NWC faucet. * @see https://github.com/getAlby/cli/tree/master/src/test */ diff --git a/src/test/nwc-faucet.test.ts b/e2e/nwc-faucet.test.ts similarity index 88% rename from src/test/nwc-faucet.test.ts rename to e2e/nwc-faucet.test.ts index 2fa48377..9f312c81 100644 --- a/src/test/nwc-faucet.test.ts +++ b/e2e/nwc-faucet.test.ts @@ -1,9 +1,9 @@ import "websocket-polyfill"; -import { NWCClient } from "../nwc/NWCClient"; +import { NWCClient } from "../src/nwc/NWCClient"; import { createTestWallet } from "./helpers"; /** - * Integration test using the NWC faucet. + * E2E integration test using the NWC faucet. * Creates a wallet with 10_000 sats and verifies the balance via get_balance. * Requires network access. */ diff --git a/jest.config.ts b/jest.config.ts index 6ff84d24..cf9060b4 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -2,5 +2,5 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', - testPathIgnorePatterns: ['/node_modules/', '/e2e/browser/'], + testPathIgnorePatterns: ['/node_modules/', '/e2e/'], }; \ No newline at end of file diff --git a/jest.e2e.config.ts b/jest.e2e.config.ts new file mode 100644 index 00000000..a06cb0ff --- /dev/null +++ b/jest.e2e.config.ts @@ -0,0 +1,7 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['/e2e/**/*.test.ts'], + testPathIgnorePatterns: ['/node_modules/'], +}; diff --git a/package.json b/package.json index 53da9c31..601bd12c 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "format:fix": "prettier --loglevel silent --write '**/*.(md|json)' 'src/**/*.(js|ts)' 'examples/**/*.(js|jsx|ts)' 'e2e/**/*.(js|ts)' 'playwright.config.ts'", "prepack": "yarn run build", "test": "jest", + "test:e2e": "jest --config=jest.e2e.config.ts", "test:e2e:browser": "playwright test --project=chromium", "test:e2e:browser:install": "playwright install", "test:e2e:browser:ui": "playwright test --ui", From 68e5fcccc18e7ca3e444249e98216659978eee25 Mon Sep 17 00:00:00 2001 From: Dmitriy E Date: Thu, 19 Feb 2026 14:53:15 +0300 Subject: [PATCH 03/10] fix: improved error catching --- e2e/helpers.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/e2e/helpers.ts b/e2e/helpers.ts index 7ba64fcc..3e65bf0a 100644 --- a/e2e/helpers.ts +++ b/e2e/helpers.ts @@ -40,6 +40,12 @@ export async function createTestWallet( lightningAddress: decodeURIComponent(lud16Match[1]), }; } catch (error) { + if ( + error instanceof Error && + error.message === "No lud16 in NWC URL" + ) { + throw error; + } if (i < retries - 1) { await new Promise((r) => setTimeout(r, 2000 * (i + 1))); continue; From dbb933b346034d368c10842809f97eccbd833900 Mon Sep 17 00:00:00 2001 From: Dmitriy E Date: Thu, 19 Feb 2026 14:55:24 +0300 Subject: [PATCH 04/10] fix(e2e): don't retry parse errors, adjust test timeout --- e2e/nwc-faucet.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/nwc-faucet.test.ts b/e2e/nwc-faucet.test.ts index 9f312c81..62df8a18 100644 --- a/e2e/nwc-faucet.test.ts +++ b/e2e/nwc-faucet.test.ts @@ -14,7 +14,7 @@ describe("NWC faucet integration", () => { test( "creates wallet via faucet and balance is 10_000 sats", async () => { - const { nwcUrl } = await createTestWallet(EXPECTED_BALANCE_SATS); + const { nwcUrl } = await createTestWallet(EXPECTED_BALANCE_SATS, 3); const nwc = new NWCClient({ nostrWalletConnectUrl: nwcUrl }); const result = await nwc.getBalance(); @@ -22,6 +22,6 @@ describe("NWC faucet integration", () => { expect(result.balance).toBe(EXPECTED_BALANCE_MSATS); }, - 30_000, + 60_000, ); }); From 7e7f0345b852aee6ee53175ae1cfbf5f1bdd66bb Mon Sep 17 00:00:00 2001 From: Dmitriy E Date: Thu, 19 Feb 2026 14:56:24 +0300 Subject: [PATCH 05/10] fix(e2e): ensure NWCClient is closed in finally block --- e2e/nwc-faucet.test.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/e2e/nwc-faucet.test.ts b/e2e/nwc-faucet.test.ts index 62df8a18..c70e5053 100644 --- a/e2e/nwc-faucet.test.ts +++ b/e2e/nwc-faucet.test.ts @@ -17,10 +17,12 @@ describe("NWC faucet integration", () => { const { nwcUrl } = await createTestWallet(EXPECTED_BALANCE_SATS, 3); const nwc = new NWCClient({ nostrWalletConnectUrl: nwcUrl }); - const result = await nwc.getBalance(); - nwc.close(); - - expect(result.balance).toBe(EXPECTED_BALANCE_MSATS); + try { + const result = await nwc.getBalance(); + expect(result.balance).toBe(EXPECTED_BALANCE_MSATS); + } finally { + nwc.close(); + } }, 60_000, ); From 7070630343b144ee5cea63a44a59cf6d7f439485 Mon Sep 17 00:00:00 2001 From: Dmitriy E Date: Tue, 24 Feb 2026 09:10:56 +0300 Subject: [PATCH 06/10] fix(e2e): exclude browser folder from Jest e2e config --- jest.e2e.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.e2e.config.ts b/jest.e2e.config.ts index a06cb0ff..30e2f6af 100644 --- a/jest.e2e.config.ts +++ b/jest.e2e.config.ts @@ -3,5 +3,5 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', testMatch: ['/e2e/**/*.test.ts'], - testPathIgnorePatterns: ['/node_modules/'], + testPathIgnorePatterns: ['/node_modules/', '/e2e/browser'], }; From f4450d80403726d0d54c92ef69b7696fd0fd10b0 Mon Sep 17 00:00:00 2001 From: Dmitriy E Date: Fri, 6 Mar 2026 16:06:55 +0300 Subject: [PATCH 07/10] feat(e2e): added e2e test step to ci workflow --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 384a98ca..4c0f4e84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,7 @@ jobs: - run: yarn install --frozen-lockfile - run: yarn build - run: yarn test + - run: yarn test:e2e - name: Install Playwright browsers run: npx playwright install --with-deps chromium - name: Run E2E tests From eeff61fb56f244e39ba0c5866e578830e366a89d Mon Sep 17 00:00:00 2001 From: Dima | Dmitry Ermolenko Date: Tue, 10 Mar 2026 15:23:17 +0300 Subject: [PATCH 08/10] Update nwc-faucet.test.ts --- e2e/nwc-faucet.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e/nwc-faucet.test.ts b/e2e/nwc-faucet.test.ts index c70e5053..4e3c2d55 100644 --- a/e2e/nwc-faucet.test.ts +++ b/e2e/nwc-faucet.test.ts @@ -1,4 +1,3 @@ -import "websocket-polyfill"; import { NWCClient } from "../src/nwc/NWCClient"; import { createTestWallet } from "./helpers"; From c59a603af92693b5dccb57eac0c2b1a0d414dc10 Mon Sep 17 00:00:00 2001 From: Dima | Dmitry Ermolenko Date: Fri, 13 Mar 2026 11:23:02 +0300 Subject: [PATCH 09/10] Updated node version on CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c0f4e84..0e222332 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 20 + node-version: 22 cache: "yarn" - run: yarn install --frozen-lockfile - run: yarn build From 67ad635173cae82669846bcdadb60082f7b6149f Mon Sep 17 00:00:00 2001 From: Dmitriy E Date: Fri, 13 Mar 2026 11:30:07 +0300 Subject: [PATCH 10/10] fix(e2e): CI fix --- jest.config.ts | 2 +- jest.e2e.config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jest.config.ts b/jest.config.ts index cf9060b4..730006b5 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,5 +1,5 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ -module.exports = { +export default { preset: 'ts-jest', testEnvironment: 'node', testPathIgnorePatterns: ['/node_modules/', '/e2e/'], diff --git a/jest.e2e.config.ts b/jest.e2e.config.ts index 30e2f6af..6b2a6036 100644 --- a/jest.e2e.config.ts +++ b/jest.e2e.config.ts @@ -1,5 +1,5 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ -module.exports = { +export default { preset: 'ts-jest', testEnvironment: 'node', testMatch: ['/e2e/**/*.test.ts'],