diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 384a98c..0e22233 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,11 +14,12 @@ 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 - run: yarn test + - run: yarn test:e2e - name: Install Playwright browsers run: npx playwright install --with-deps chromium - name: Run E2E tests diff --git a/e2e/helpers.ts b/e2e/helpers.ts new file mode 100644 index 0000000..3e65bf0 --- /dev/null +++ b/e2e/helpers.ts @@ -0,0 +1,57 @@ +/** + * Test helpers for E2E 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 ( + 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; + } + throw error; + } + } + throw new Error("Failed to create test wallet"); +} diff --git a/e2e/nwc-faucet.test.ts b/e2e/nwc-faucet.test.ts new file mode 100644 index 0000000..4e3c2d5 --- /dev/null +++ b/e2e/nwc-faucet.test.ts @@ -0,0 +1,28 @@ +import { NWCClient } from "../src/nwc/NWCClient"; +import { createTestWallet } from "./helpers"; + +/** + * E2E 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, 3); + + const nwc = new NWCClient({ nostrWalletConnectUrl: nwcUrl }); + try { + const result = await nwc.getBalance(); + expect(result.balance).toBe(EXPECTED_BALANCE_MSATS); + } finally { + nwc.close(); + } + }, + 60_000, + ); +}); diff --git a/jest.config.ts b/jest.config.ts index 6ff84d2..730006b 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,6 +1,6 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ -module.exports = { +export default { 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 0000000..6b2a603 --- /dev/null +++ b/jest.e2e.config.ts @@ -0,0 +1,7 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +export default { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['/e2e/**/*.test.ts'], + testPathIgnorePatterns: ['/node_modules/', '/e2e/browser'], +}; diff --git a/package.json b/package.json index 53da9c3..601bd12 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",