From 16b8b08ba8573784eebcd5069588456889affae2 Mon Sep 17 00:00:00 2001 From: darian Date: Mon, 13 Jan 2025 12:09:40 +0200 Subject: [PATCH 1/9] e2e test reconnect wallet --- tests/e2e/reconnect.spec.ts | 230 ++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 tests/e2e/reconnect.spec.ts diff --git a/tests/e2e/reconnect.spec.ts b/tests/e2e/reconnect.spec.ts new file mode 100644 index 00000000..608826cc --- /dev/null +++ b/tests/e2e/reconnect.spec.ts @@ -0,0 +1,230 @@ +import { test, expect } from './fixtures/base'; +import { getJWKS, withResolvers } from '@/shared/helpers'; +import { + acceptGrant, + API_URL_ORIGIN, + DEFAULT_CONTINUE_WAIT_MS, + KEYS_PAGE_URL, + LOGIN_PAGE_URL, + revokeKey, + waitForGrantConsentPage, +} from './helpers/testWallet'; +import { getStorage } from './fixtures/helpers'; +import { spy } from 'tinyspy'; +import { getContinueWaitTime, waitForWelcomePage } from './helpers/common'; +import { fillPopup } from './pages/popup'; + +test('Reconnect to test wallet with automatic key addition when not logged-in to wallet', async ({ + page, + popup, + persistentContext: context, + background, + i18n, +}) => { + const username = process.env.TEST_WALLET_USERNAME; + const password = process.env.TEST_WALLET_PASSWORD; + const walletAddressUrl = process.env.TEST_WALLET_ADDRESS_URL; + + const connectButton = await test.step('fill popup', async () => { + const connectButton = await fillPopup(popup, i18n, { + walletAddressUrl, + amount: '10', + recurring: false, + }); + return connectButton; + }); + + await test.step('ensure not logged in', async () => { + await context.clearCookies(); + + await page.goto(KEYS_PAGE_URL); + expect(page.url()).toBe(LOGIN_PAGE_URL); + await page.close(); + }); + + await test.step('asks for key-add consent', async () => { + await connectButton.click(); + await popup.waitForSelector( + `[data-testid="connect-wallet-auto-key-consent"]`, + ); + + expect(popup.getByTestId('connect-wallet-auto-key-consent')).toBeVisible(); + await popup + .getByRole('button', { + name: i18n.getMessage('connectWalletKeyService_label_consentAccept'), + }) + .click(); + }); + + page = await test.step('shows login page', async () => { + const openedPage = await context.waitForEvent('page', { + predicate: (page) => page.url().startsWith(LOGIN_PAGE_URL), + timeout: 3 * 1000, + }); + await openedPage.getByLabel('E-mail').fill(username); + await openedPage.getByLabel('Password').fill(password); + await openedPage.getByRole('button', { name: 'login' }).click(); + await openedPage.waitForURL(KEYS_PAGE_URL); + await expect(openedPage.locator('h1')).toHaveText('Developer Keys'); + + return openedPage; + }); + + const continueWaitMsPromise = getContinueWaitTime( + context, + { walletAddressUrl }, + DEFAULT_CONTINUE_WAIT_MS, + ); + + const revokeInfo = await test.step('adds key to wallet', async () => { + const { resolve, reject, promise } = withResolvers<{ + accountId: string; + walletId: string; + }>(); + const pause = withResolvers(); + page.on('requestfinished', async function intercept(req) { + if (req.serviceWorker()) return; + if (req.method() !== 'POST') return; + const url = new URL(req.url()); + if (url.origin !== API_URL_ORIGIN) return; + if (!url.pathname.startsWith('/accounts/')) return; + if (!url.pathname.includes('/upload-key')) return; + + const pattern = + /^\/accounts\/(?.+)\/wallet-addresses\/(?.+)\/upload-key$/; + const match = url.pathname.match(pattern); + if (!match) { + throw new Error('no match for URL pattern'); + } + const result = match.groups as { accountId: string; walletId: string }; + + const res = await req.response(); + page.off('requestfinished', intercept); + if (!res) { + reject('no response from /upload-key API'); + } else { + await pause.promise; + resolve(result); + } + }); + + const { keyId } = await getStorage(background, ['keyId']); + + const jwksBefore = await getJWKS(walletAddressUrl); + expect(jwksBefore.keys.length).toBeGreaterThanOrEqual(0); + expect(jwksBefore.keys.find((key) => key.kid === keyId)).toBeUndefined(); + + pause.resolve(); + const { accountId, walletId } = await promise; + + const jwks = await getJWKS(walletAddressUrl); + expect(jwks.keys.length).toBeGreaterThan(0); + const key = jwks.keys.find((key) => key.kid === keyId); + expect(key).toMatchObject({ kid: keyId }); + + return { accountId, walletId, keyId }; + }); + + await test.step('shows connect consent page', async () => { + await page.waitForURL((url) => + url.pathname.startsWith('/grant-interactions'), + ); + await waitForGrantConsentPage(page); + }); + + await test.step('connects', async () => { + const continueWaitMs = await continueWaitMsPromise; + await acceptGrant(page, continueWaitMs); + await waitForWelcomePage(page); + + await expect(background).toHaveStorage({ connected: true }); + }); + + const playgroundUrl = 'https://webmonetization.org/play/'; + await page.goto(playgroundUrl); + + const monetizationCallback = spy<[Event], void>(); + await page.exposeFunction('monetizationCallback', monetizationCallback); + await page.evaluate(() => { + window.addEventListener('monetization', monetizationCallback); + }); + + await page + .getByLabel('Wallet address/Payment pointer') + .fill(walletAddressUrl); + await page.getByRole('button', { name: 'Add monetization link' }).click(); + + await expect(page.locator('link[rel=monetization]')).toHaveAttribute( + 'href', + walletAddressUrl, + ); + + await page.waitForSelector('#link-events .log-header'); + await page.waitForSelector('#link-events ul.events li'); + await expect(page.locator('#link-events ul.events li').last()).toContainText( + 'Load Event', + ); + + await test.step('revoke key', async () => { + await revokeKey(page, revokeInfo); + + const { keys } = await getJWKS(walletAddressUrl); + expect(keys.find((key) => key.kid === revokeInfo.keyId)).toBeUndefined(); + }); + + await test.step('make one-time payment', async () => { + await page.goto(playgroundUrl); + + await popup.reload({ waitUntil: 'networkidle' }); + await page.bringToFront(); + await popup.waitForSelector(`[data-testid="home-page"]`); + + await expect(popup.getByRole('button', { name: 'Send now' })).toBeVisible(); + expect(await popup.getByRole('textbox').all()).toHaveLength(1); + + await popup.getByRole('textbox').fill('1.5'); + await popup.getByRole('button', { name: 'Send now' }).click(); + + // payment should not go through + await expect(page.locator('link[rel=monetization]')).toHaveAttribute( + 'href', + walletAddressUrl, + ); + + await page.waitForSelector('#link-events .log-header'); + await page.waitForSelector('#link-events ul.events li'); + await expect( + page.locator('#link-events ul.events li').last(), + ).toContainText('Load Event'); + + await expect(monetizationCallback).toHaveBeenCalledTimes(0); + }); + + await test.step('asks for key-add consent', async () => { + // revoked key should be detected + await expect( + popup.getByRole('button', { + name: 'It was a mistake, I’d like to reconnect my wallet', + }), + ).toBeVisible(); + await popup + .getByRole('button', { + name: 'It was a mistake, I’d like to reconnect my wallet', + }) + .click(); + + expect(popup.getByTestId('connect-wallet-auto-key-consent')).toBeVisible(); + await popup + .getByRole('button', { + name: i18n.getMessage('connectWalletKeyService_label_consentAccept'), + }) + .click(); + + // show home-page + await popup.reload({ waitUntil: 'networkidle' }); + await page.bringToFront(); + await popup.waitForSelector(`[data-testid="home-page"]`); + + await expect(popup.getByRole('button', { name: 'Send now' })).toBeVisible(); + }); +}); From 572029d8ac1a480702822c7edc693025d390f5cb Mon Sep 17 00:00:00 2001 From: darian Date: Tue, 14 Jan 2025 01:55:35 +0200 Subject: [PATCH 2/9] fix test --- tests/e2e/helpers/common.ts | 8 + tests/e2e/reconnect.spec.ts | 230 ------------------ tests/e2e/reconnectAutoKeyTestWallet.spec.ts | 233 +++++++++++++++++++ 3 files changed, 241 insertions(+), 230 deletions(-) delete mode 100644 tests/e2e/reconnect.spec.ts create mode 100644 tests/e2e/reconnectAutoKeyTestWallet.spec.ts diff --git a/tests/e2e/helpers/common.ts b/tests/e2e/helpers/common.ts index 0675d71d..38d735f5 100644 --- a/tests/e2e/helpers/common.ts +++ b/tests/e2e/helpers/common.ts @@ -12,6 +12,14 @@ export async function waitForWelcomePage(page: Page) { ); } +export async function waitForReconnectWelcomePage(page: Page) { + await page.waitForURL( + (url) => + url.href.startsWith(OPEN_PAYMENTS_REDIRECT_URL) && + url.searchParams.get('result') === 'key_add_success', + ); +} + export async function getContinueWaitTime( context: BrowserContext, params: Pick, diff --git a/tests/e2e/reconnect.spec.ts b/tests/e2e/reconnect.spec.ts deleted file mode 100644 index 608826cc..00000000 --- a/tests/e2e/reconnect.spec.ts +++ /dev/null @@ -1,230 +0,0 @@ -import { test, expect } from './fixtures/base'; -import { getJWKS, withResolvers } from '@/shared/helpers'; -import { - acceptGrant, - API_URL_ORIGIN, - DEFAULT_CONTINUE_WAIT_MS, - KEYS_PAGE_URL, - LOGIN_PAGE_URL, - revokeKey, - waitForGrantConsentPage, -} from './helpers/testWallet'; -import { getStorage } from './fixtures/helpers'; -import { spy } from 'tinyspy'; -import { getContinueWaitTime, waitForWelcomePage } from './helpers/common'; -import { fillPopup } from './pages/popup'; - -test('Reconnect to test wallet with automatic key addition when not logged-in to wallet', async ({ - page, - popup, - persistentContext: context, - background, - i18n, -}) => { - const username = process.env.TEST_WALLET_USERNAME; - const password = process.env.TEST_WALLET_PASSWORD; - const walletAddressUrl = process.env.TEST_WALLET_ADDRESS_URL; - - const connectButton = await test.step('fill popup', async () => { - const connectButton = await fillPopup(popup, i18n, { - walletAddressUrl, - amount: '10', - recurring: false, - }); - return connectButton; - }); - - await test.step('ensure not logged in', async () => { - await context.clearCookies(); - - await page.goto(KEYS_PAGE_URL); - expect(page.url()).toBe(LOGIN_PAGE_URL); - await page.close(); - }); - - await test.step('asks for key-add consent', async () => { - await connectButton.click(); - await popup.waitForSelector( - `[data-testid="connect-wallet-auto-key-consent"]`, - ); - - expect(popup.getByTestId('connect-wallet-auto-key-consent')).toBeVisible(); - await popup - .getByRole('button', { - name: i18n.getMessage('connectWalletKeyService_label_consentAccept'), - }) - .click(); - }); - - page = await test.step('shows login page', async () => { - const openedPage = await context.waitForEvent('page', { - predicate: (page) => page.url().startsWith(LOGIN_PAGE_URL), - timeout: 3 * 1000, - }); - await openedPage.getByLabel('E-mail').fill(username); - await openedPage.getByLabel('Password').fill(password); - await openedPage.getByRole('button', { name: 'login' }).click(); - await openedPage.waitForURL(KEYS_PAGE_URL); - await expect(openedPage.locator('h1')).toHaveText('Developer Keys'); - - return openedPage; - }); - - const continueWaitMsPromise = getContinueWaitTime( - context, - { walletAddressUrl }, - DEFAULT_CONTINUE_WAIT_MS, - ); - - const revokeInfo = await test.step('adds key to wallet', async () => { - const { resolve, reject, promise } = withResolvers<{ - accountId: string; - walletId: string; - }>(); - const pause = withResolvers(); - page.on('requestfinished', async function intercept(req) { - if (req.serviceWorker()) return; - if (req.method() !== 'POST') return; - const url = new URL(req.url()); - if (url.origin !== API_URL_ORIGIN) return; - if (!url.pathname.startsWith('/accounts/')) return; - if (!url.pathname.includes('/upload-key')) return; - - const pattern = - /^\/accounts\/(?.+)\/wallet-addresses\/(?.+)\/upload-key$/; - const match = url.pathname.match(pattern); - if (!match) { - throw new Error('no match for URL pattern'); - } - const result = match.groups as { accountId: string; walletId: string }; - - const res = await req.response(); - page.off('requestfinished', intercept); - if (!res) { - reject('no response from /upload-key API'); - } else { - await pause.promise; - resolve(result); - } - }); - - const { keyId } = await getStorage(background, ['keyId']); - - const jwksBefore = await getJWKS(walletAddressUrl); - expect(jwksBefore.keys.length).toBeGreaterThanOrEqual(0); - expect(jwksBefore.keys.find((key) => key.kid === keyId)).toBeUndefined(); - - pause.resolve(); - const { accountId, walletId } = await promise; - - const jwks = await getJWKS(walletAddressUrl); - expect(jwks.keys.length).toBeGreaterThan(0); - const key = jwks.keys.find((key) => key.kid === keyId); - expect(key).toMatchObject({ kid: keyId }); - - return { accountId, walletId, keyId }; - }); - - await test.step('shows connect consent page', async () => { - await page.waitForURL((url) => - url.pathname.startsWith('/grant-interactions'), - ); - await waitForGrantConsentPage(page); - }); - - await test.step('connects', async () => { - const continueWaitMs = await continueWaitMsPromise; - await acceptGrant(page, continueWaitMs); - await waitForWelcomePage(page); - - await expect(background).toHaveStorage({ connected: true }); - }); - - const playgroundUrl = 'https://webmonetization.org/play/'; - await page.goto(playgroundUrl); - - const monetizationCallback = spy<[Event], void>(); - await page.exposeFunction('monetizationCallback', monetizationCallback); - await page.evaluate(() => { - window.addEventListener('monetization', monetizationCallback); - }); - - await page - .getByLabel('Wallet address/Payment pointer') - .fill(walletAddressUrl); - await page.getByRole('button', { name: 'Add monetization link' }).click(); - - await expect(page.locator('link[rel=monetization]')).toHaveAttribute( - 'href', - walletAddressUrl, - ); - - await page.waitForSelector('#link-events .log-header'); - await page.waitForSelector('#link-events ul.events li'); - await expect(page.locator('#link-events ul.events li').last()).toContainText( - 'Load Event', - ); - - await test.step('revoke key', async () => { - await revokeKey(page, revokeInfo); - - const { keys } = await getJWKS(walletAddressUrl); - expect(keys.find((key) => key.kid === revokeInfo.keyId)).toBeUndefined(); - }); - - await test.step('make one-time payment', async () => { - await page.goto(playgroundUrl); - - await popup.reload({ waitUntil: 'networkidle' }); - await page.bringToFront(); - await popup.waitForSelector(`[data-testid="home-page"]`); - - await expect(popup.getByRole('button', { name: 'Send now' })).toBeVisible(); - expect(await popup.getByRole('textbox').all()).toHaveLength(1); - - await popup.getByRole('textbox').fill('1.5'); - await popup.getByRole('button', { name: 'Send now' }).click(); - - // payment should not go through - await expect(page.locator('link[rel=monetization]')).toHaveAttribute( - 'href', - walletAddressUrl, - ); - - await page.waitForSelector('#link-events .log-header'); - await page.waitForSelector('#link-events ul.events li'); - await expect( - page.locator('#link-events ul.events li').last(), - ).toContainText('Load Event'); - - await expect(monetizationCallback).toHaveBeenCalledTimes(0); - }); - - await test.step('asks for key-add consent', async () => { - // revoked key should be detected - await expect( - popup.getByRole('button', { - name: 'It was a mistake, I’d like to reconnect my wallet', - }), - ).toBeVisible(); - await popup - .getByRole('button', { - name: 'It was a mistake, I’d like to reconnect my wallet', - }) - .click(); - - expect(popup.getByTestId('connect-wallet-auto-key-consent')).toBeVisible(); - await popup - .getByRole('button', { - name: i18n.getMessage('connectWalletKeyService_label_consentAccept'), - }) - .click(); - - // show home-page - await popup.reload({ waitUntil: 'networkidle' }); - await page.bringToFront(); - await popup.waitForSelector(`[data-testid="home-page"]`); - - await expect(popup.getByRole('button', { name: 'Send now' })).toBeVisible(); - }); -}); diff --git a/tests/e2e/reconnectAutoKeyTestWallet.spec.ts b/tests/e2e/reconnectAutoKeyTestWallet.spec.ts new file mode 100644 index 00000000..a8e4c7be --- /dev/null +++ b/tests/e2e/reconnectAutoKeyTestWallet.spec.ts @@ -0,0 +1,233 @@ +import { test, expect } from './fixtures/base'; +import { getJWKS, withResolvers } from '@/shared/helpers'; +import { + acceptGrant, + API_URL_ORIGIN, + DEFAULT_CONTINUE_WAIT_MS, + revokeKey, + waitForGrantConsentPage, +} from './helpers/testWallet'; +import { getStorage } from './fixtures/helpers'; +import { spy } from 'tinyspy'; +import { + getContinueWaitTime, + waitForWelcomePage, + waitForReconnectWelcomePage, +} from './helpers/common'; +import { disconnectWallet, fillPopup } from './pages/popup'; + +test('Reconnect to test wallet with automatic key addition', async ({ + page, + popup, + persistentContext: context, + background, + i18n, +}) => { + const walletAddressUrl = process.env.TEST_WALLET_ADDRESS_URL; + const monetizationCallback = spy<[Event], void>(); + const revokeInfo = await test.step('connect wallet', async () => { + const connectButton = await test.step('fill popup', async () => { + const connectButton = await fillPopup(popup, i18n, { + walletAddressUrl, + amount: '10', + recurring: false, + }); + return connectButton; + }); + + await test.step('asks for key-add consent', async () => { + await connectButton.click(); + await popup.waitForSelector( + `[data-testid="connect-wallet-auto-key-consent"]`, + ); + + expect( + popup.getByTestId('connect-wallet-auto-key-consent'), + ).toBeVisible(); + await popup + .getByRole('button', { + name: i18n.getMessage('connectWalletKeyService_label_consentAccept'), + }) + .click(); + }); + + const continueWaitMsPromise = getContinueWaitTime( + context, + { walletAddressUrl }, + DEFAULT_CONTINUE_WAIT_MS, + ); + + const revokeInfo = await test.step('adds key to wallet', async () => { + page = await context.waitForEvent('page', { + predicate: (page) => + page + .url() + .includes( + `${process.env.TEST_WALLET_ORIGIN}/settings/developer-keys`, + ), + timeout: 3 * 1000, + }); + + const { resolve, reject, promise } = withResolvers<{ + accountId: string; + walletId: string; + }>(); + page.on('requestfinished', async function intercept(req) { + if (req.serviceWorker()) return; + if (req.method() !== 'POST') return; + const url = new URL(req.url()); + if (url.origin !== API_URL_ORIGIN) return; + if (!url.pathname.startsWith('/accounts/')) return; + if (!url.pathname.includes('/upload-key')) return; + + const pattern = + /^\/accounts\/(?.+)\/wallet-addresses\/(?.+)\/upload-key$/; + const match = url.pathname.match(pattern); + if (!match) { + throw new Error('no match for URL pattern'); + } + const result = match.groups as { accountId: string; walletId: string }; + + const res = await req.response(); + page.off('requestfinished', intercept); + if (!res) { + reject('no response from /upload-key API'); + } else { + resolve(result); + } + }); + + const { keyId } = await getStorage(background, ['keyId']); + const { accountId, walletId } = await promise; + + const jwks = await getJWKS(walletAddressUrl); + expect(jwks.keys.length).toBeGreaterThan(0); + const key = jwks.keys.find((key) => key.kid === keyId); + expect(key).toMatchObject({ kid: keyId }); + + return { accountId, walletId, keyId }; + }); + + await test.step('shows connect consent page', async () => { + await page.waitForURL((url) => + url.pathname.startsWith('/grant-interactions'), + ); + await waitForGrantConsentPage(page); + }); + + await test.step('connects', async () => { + const continueWaitMs = await continueWaitMsPromise; + await acceptGrant(page, continueWaitMs); + await waitForWelcomePage(page); + + await expect(background).toHaveStorage({ connected: true }); + }); + + return revokeInfo; + }); + + await test.step('start monetization', async () => { + const playgroundUrl = 'https://webmonetization.org/play/'; + await page.goto(playgroundUrl); + + await page.exposeFunction('monetizationCallback', monetizationCallback); + await page.evaluate(() => { + window.addEventListener('monetization', monetizationCallback); + }); + + await page + .getByLabel('Wallet address/Payment pointer') + .fill(walletAddressUrl); + await page.getByRole('button', { name: 'Add monetization link' }).click(); + + await expect(monetizationCallback).toHaveBeenCalledTimes(1); + }); + + await test.step('revoke key', async () => { + const newPage = await context.newPage(); + await revokeKey(newPage, revokeInfo); + newPage.close(); + + const { keys } = await getJWKS(walletAddressUrl); + expect(keys.find((key) => key.kid === revokeInfo.keyId)).toBeUndefined(); + }); + + await test.step('trigger key-revoked state by making one-time payment', async () => { + await expect(monetizationCallback).toHaveBeenCalledTimes(1); + + await popup.waitForSelector(`[data-testid="home-page"]`); + + await expect(popup.getByRole('button', { name: 'Send now' })).toBeVisible(); + expect(await popup.getByRole('textbox').all()).toHaveLength(1); + + await popup.getByRole('textbox').fill('1.5'); + await popup.getByRole('button', { name: 'Send now' }).click(); + + await expect(monetizationCallback).toHaveBeenCalledTimes(1); + }); + + await test.step('asks for key-add consent to reconnect wallet', async () => { + await expect( + popup.getByRole('button', { + name: i18n.getMessage('keyRevoked_action_reconnect'), + }), + ).toBeVisible(); + await popup + .getByRole('button', { + name: i18n.getMessage('keyRevoked_action_reconnect'), + }) + .click(); + + await popup.waitForSelector( + `[data-testid="connect-wallet-auto-key-consent"]`, + ); + + expect(popup.getByTestId('connect-wallet-auto-key-consent')).toBeVisible(); + await popup + .getByRole('button', { + name: i18n.getMessage('connectWalletKeyService_label_consentAccept'), + }) + .click(); + + const newPage = await context.waitForEvent('page', { + predicate: (page) => + page + .url() + .includes( + `${process.env.TEST_WALLET_ORIGIN}/settings/developer-keys`, + ), + timeout: 3 * 1000, + }); + + await waitForReconnectWelcomePage(newPage); + newPage.close(); + }); + + await test.step('make one-time payment after reconnecting the wallet', async () => { + await popup.reload({ waitUntil: 'networkidle' }); + await popup.waitForSelector(`[data-testid="home-page"]`); + await expect(popup.getByRole('button', { name: 'Send now' })).toBeVisible(); + + await popup.getByRole('textbox').fill('1.5'); + await popup.getByRole('button', { name: 'Send now' }).click(); + + await expect(monetizationCallback).toHaveBeenCalledTimes(2, { + timeout: 1000, + }); + await expect(monetizationCallback).toHaveBeenLastCalledWithMatching({ + paymentPointer: walletAddressUrl, + amountSent: { + currency: expect.stringMatching(/^[A-Z]{3}$/), + value: expect.stringMatching(/^1\.\d+$/), + }, + incomingPayment: expect.stringContaining( + new URL(walletAddressUrl).origin, + ), + }); + }); + + await test.step('revoke keys and disconnect wallet', async () => { + await revokeKey(page, revokeInfo); + await disconnectWallet(popup); + }); +}); From 1638fe6a96e61969d52b116d41e613e9bd9c581a Mon Sep 17 00:00:00 2001 From: darian Date: Tue, 14 Jan 2025 16:08:25 +0200 Subject: [PATCH 3/9] fix pr comments --- tests/e2e/reconnectAutoKeyTestWallet.spec.ts | 39 +++++++++----------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/tests/e2e/reconnectAutoKeyTestWallet.spec.ts b/tests/e2e/reconnectAutoKeyTestWallet.spec.ts index a8e4c7be..6f8982da 100644 --- a/tests/e2e/reconnectAutoKeyTestWallet.spec.ts +++ b/tests/e2e/reconnectAutoKeyTestWallet.spec.ts @@ -4,6 +4,7 @@ import { acceptGrant, API_URL_ORIGIN, DEFAULT_CONTINUE_WAIT_MS, + KEYS_PAGE_URL, revokeKey, waitForGrantConsentPage, } from './helpers/testWallet'; @@ -167,20 +168,15 @@ test('Reconnect to test wallet with automatic key addition', async ({ }); await test.step('asks for key-add consent to reconnect wallet', async () => { - await expect( - popup.getByRole('button', { - name: i18n.getMessage('keyRevoked_action_reconnect'), - }), - ).toBeVisible(); - await popup - .getByRole('button', { - name: i18n.getMessage('keyRevoked_action_reconnect'), - }) - .click(); + const reconnectButton = popup.getByRole('button', { + name: i18n.getMessage('keyRevoked_action_reconnect'), + }); + await expect(reconnectButton).toBeVisible(); + await reconnectButton.click(); - await popup.waitForSelector( - `[data-testid="connect-wallet-auto-key-consent"]`, - ); + // await popup.waitForSelector( + // `[data-testid="connect-wallet-auto-key-consent"]`, + // ); expect(popup.getByTestId('connect-wallet-auto-key-consent')).toBeVisible(); await popup @@ -190,13 +186,14 @@ test('Reconnect to test wallet with automatic key addition', async ({ .click(); const newPage = await context.waitForEvent('page', { - predicate: (page) => - page - .url() - .includes( - `${process.env.TEST_WALLET_ORIGIN}/settings/developer-keys`, - ), - timeout: 3 * 1000, + // predicate: (page) => + // page + // .url() + // .includes( + // `${process.env.TEST_WALLET_ORIGIN}/settings/developer-keys`, + // ), + // timeout: 3 * 1000, + predicate: (page) => page.url().startsWith(KEYS_PAGE_URL), }); await waitForReconnectWelcomePage(newPage); @@ -227,7 +224,7 @@ test('Reconnect to test wallet with automatic key addition', async ({ }); await test.step('revoke keys and disconnect wallet', async () => { - await revokeKey(page, revokeInfo); await disconnectWallet(popup); + await revokeKey(page, revokeInfo); }); }); From c0f2da1751a82ea526c44273623e816508ce0394 Mon Sep 17 00:00:00 2001 From: darian Date: Tue, 14 Jan 2025 18:33:21 +0200 Subject: [PATCH 4/9] change e2e fails without the fix --- tests/e2e/reconnectAutoKeyTestWallet.spec.ts | 57 +++++--------------- 1 file changed, 13 insertions(+), 44 deletions(-) diff --git a/tests/e2e/reconnectAutoKeyTestWallet.spec.ts b/tests/e2e/reconnectAutoKeyTestWallet.spec.ts index 6f8982da..25180306 100644 --- a/tests/e2e/reconnectAutoKeyTestWallet.spec.ts +++ b/tests/e2e/reconnectAutoKeyTestWallet.spec.ts @@ -60,13 +60,7 @@ test('Reconnect to test wallet with automatic key addition', async ({ const revokeInfo = await test.step('adds key to wallet', async () => { page = await context.waitForEvent('page', { - predicate: (page) => - page - .url() - .includes( - `${process.env.TEST_WALLET_ORIGIN}/settings/developer-keys`, - ), - timeout: 3 * 1000, + predicate: (page) => page.url().startsWith(KEYS_PAGE_URL), }); const { resolve, reject, promise } = withResolvers<{ @@ -127,6 +121,15 @@ test('Reconnect to test wallet with automatic key addition', async ({ return revokeInfo; }); + await test.step('revoke key', async () => { + const newPage = await context.newPage(); + await revokeKey(newPage, revokeInfo); + await newPage.close(); + + const { keys } = await getJWKS(walletAddressUrl); + expect(keys.find((key) => key.kid === revokeInfo.keyId)).toBeUndefined(); + }); + await test.step('start monetization', async () => { const playgroundUrl = 'https://webmonetization.org/play/'; await page.goto(playgroundUrl); @@ -141,30 +144,7 @@ test('Reconnect to test wallet with automatic key addition', async ({ .fill(walletAddressUrl); await page.getByRole('button', { name: 'Add monetization link' }).click(); - await expect(monetizationCallback).toHaveBeenCalledTimes(1); - }); - - await test.step('revoke key', async () => { - const newPage = await context.newPage(); - await revokeKey(newPage, revokeInfo); - newPage.close(); - - const { keys } = await getJWKS(walletAddressUrl); - expect(keys.find((key) => key.kid === revokeInfo.keyId)).toBeUndefined(); - }); - - await test.step('trigger key-revoked state by making one-time payment', async () => { - await expect(monetizationCallback).toHaveBeenCalledTimes(1); - - await popup.waitForSelector(`[data-testid="home-page"]`); - - await expect(popup.getByRole('button', { name: 'Send now' })).toBeVisible(); - expect(await popup.getByRole('textbox').all()).toHaveLength(1); - - await popup.getByRole('textbox').fill('1.5'); - await popup.getByRole('button', { name: 'Send now' }).click(); - - await expect(monetizationCallback).toHaveBeenCalledTimes(1); + await expect(monetizationCallback).toHaveBeenCalledTimes(0); }); await test.step('asks for key-add consent to reconnect wallet', async () => { @@ -174,10 +154,6 @@ test('Reconnect to test wallet with automatic key addition', async ({ await expect(reconnectButton).toBeVisible(); await reconnectButton.click(); - // await popup.waitForSelector( - // `[data-testid="connect-wallet-auto-key-consent"]`, - // ); - expect(popup.getByTestId('connect-wallet-auto-key-consent')).toBeVisible(); await popup .getByRole('button', { @@ -186,18 +162,11 @@ test('Reconnect to test wallet with automatic key addition', async ({ .click(); const newPage = await context.waitForEvent('page', { - // predicate: (page) => - // page - // .url() - // .includes( - // `${process.env.TEST_WALLET_ORIGIN}/settings/developer-keys`, - // ), - // timeout: 3 * 1000, predicate: (page) => page.url().startsWith(KEYS_PAGE_URL), }); await waitForReconnectWelcomePage(newPage); - newPage.close(); + await newPage.close(); }); await test.step('make one-time payment after reconnecting the wallet', async () => { @@ -208,7 +177,7 @@ test('Reconnect to test wallet with automatic key addition', async ({ await popup.getByRole('textbox').fill('1.5'); await popup.getByRole('button', { name: 'Send now' }).click(); - await expect(monetizationCallback).toHaveBeenCalledTimes(2, { + await expect(monetizationCallback).toHaveBeenCalledTimes(1, { timeout: 1000, }); await expect(monetizationCallback).toHaveBeenLastCalledWithMatching({ From ccdf44cccd5b0d696132cac8bcd8891867834a67 Mon Sep 17 00:00:00 2001 From: Sid Vishnoi <8426945+sidvishnoi@users.noreply.github.com> Date: Wed, 15 Jan 2025 14:55:19 +0530 Subject: [PATCH 5/9] nits --- tests/e2e/reconnectAutoKeyTestWallet.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/reconnectAutoKeyTestWallet.spec.ts b/tests/e2e/reconnectAutoKeyTestWallet.spec.ts index 25180306..80996081 100644 --- a/tests/e2e/reconnectAutoKeyTestWallet.spec.ts +++ b/tests/e2e/reconnectAutoKeyTestWallet.spec.ts @@ -170,8 +170,8 @@ test('Reconnect to test wallet with automatic key addition', async ({ }); await test.step('make one-time payment after reconnecting the wallet', async () => { - await popup.reload({ waitUntil: 'networkidle' }); - await popup.waitForSelector(`[data-testid="home-page"]`); + await popup.reload(); + await expect(popup.getByTestId('home-page')).toBeVisible(); await expect(popup.getByRole('button', { name: 'Send now' })).toBeVisible(); await popup.getByRole('textbox').fill('1.5'); From 31d8ab59093024f7e91b2a0ddb15ce21de5dfa79 Mon Sep 17 00:00:00 2001 From: Sid Vishnoi <8426945+sidvishnoi@users.noreply.github.com> Date: Wed, 15 Jan 2025 14:58:29 +0530 Subject: [PATCH 6/9] nit: remove redundant wait --- tests/e2e/reconnectAutoKeyTestWallet.spec.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/e2e/reconnectAutoKeyTestWallet.spec.ts b/tests/e2e/reconnectAutoKeyTestWallet.spec.ts index 80996081..4be5c007 100644 --- a/tests/e2e/reconnectAutoKeyTestWallet.spec.ts +++ b/tests/e2e/reconnectAutoKeyTestWallet.spec.ts @@ -38,10 +38,6 @@ test('Reconnect to test wallet with automatic key addition', async ({ await test.step('asks for key-add consent', async () => { await connectButton.click(); - await popup.waitForSelector( - `[data-testid="connect-wallet-auto-key-consent"]`, - ); - expect( popup.getByTestId('connect-wallet-auto-key-consent'), ).toBeVisible(); From 48b9b41f36675c97588b123f084711af89e078fd Mon Sep 17 00:00:00 2001 From: Sid Vishnoi <8426945+sidvishnoi@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:12:06 +0530 Subject: [PATCH 7/9] debug: check what commit we're actually on --- .github/workflows/tests-e2e.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests-e2e.yml b/.github/workflows/tests-e2e.yml index 77b74a24..90b91c08 100644 --- a/.github/workflows/tests-e2e.yml +++ b/.github/workflows/tests-e2e.yml @@ -32,6 +32,8 @@ jobs: environment: test steps: - uses: actions/checkout@v4 + - run: git log --oneline -n10 + - run: sed -n '186,210p' src/background/services/wallet.ts - name: Environment setup uses: ./.github/actions/setup From 1ac8703ff51f3b8ca97767ba732f7d520bf5ab80 Mon Sep 17 00:00:00 2001 From: Sid Vishnoi <8426945+sidvishnoi@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:18:10 +0530 Subject: [PATCH 8/9] debug: checkout pull request head instead of /merge --- .github/workflows/tests-e2e.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests-e2e.yml b/.github/workflows/tests-e2e.yml index 90b91c08..643339f2 100644 --- a/.github/workflows/tests-e2e.yml +++ b/.github/workflows/tests-e2e.yml @@ -32,6 +32,8 @@ jobs: environment: test steps: - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - run: git log --oneline -n10 - run: sed -n '186,210p' src/background/services/wallet.ts From eec4391902527b3b98674a98c807abd557c402ee Mon Sep 17 00:00:00 2001 From: Sid Vishnoi <8426945+sidvishnoi@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:23:48 +0530 Subject: [PATCH 9/9] fix(ci): test-e2e checked out wrong commit --- .github/workflows/tests-e2e.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/tests-e2e.yml b/.github/workflows/tests-e2e.yml index 643339f2..2bf99b5e 100644 --- a/.github/workflows/tests-e2e.yml +++ b/.github/workflows/tests-e2e.yml @@ -33,9 +33,8 @@ jobs: steps: - uses: actions/checkout@v4 with: + # In a pull request trigger, ref is required as GitHub Actions checks out in detached HEAD mode, meaning it doesn’t check out your branch by default. ref: ${{ github.event.pull_request.head.sha }} - - run: git log --oneline -n10 - - run: sed -n '186,210p' src/background/services/wallet.ts - name: Environment setup uses: ./.github/actions/setup