From 3627dd11bd1bc8d5d8c66d59f655675af1d369fd Mon Sep 17 00:00:00 2001 From: MK <53529533+magiziz@users.noreply.github.com> Date: Fri, 11 Oct 2024 15:40:58 +0100 Subject: [PATCH] chore: add max timeouts for frame requests (#3073) Co-authored-by: Enes --- .changeset/cool-walls-fix.md | 23 +++++++++++++++++++ apps/laboratory/playwright.config.ts | 2 +- apps/laboratory/tests/email.spec.ts | 15 +++++++++--- .../tests/shared/pages/ModalPage.ts | 16 +++++++------ .../tests/shared/validators/ModalValidator.ts | 6 +++++ .../ui/src/composites/wui-snackbar/index.ts | 4 +++- packages/wallet/src/W3mFrameProvider.ts | 14 +++++++---- 7 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 .changeset/cool-walls-fix.md diff --git a/.changeset/cool-walls-fix.md b/.changeset/cool-walls-fix.md new file mode 100644 index 0000000000..3ce55f0fa2 --- /dev/null +++ b/.changeset/cool-walls-fix.md @@ -0,0 +1,23 @@ +--- +'@apps/laboratory': patch +'@reown/appkit-wallet': patch +'@reown/appkit-ui': patch +'@apps/demo': patch +'@apps/gallery': patch +'@reown/appkit-adapter-ethers': patch +'@reown/appkit-adapter-ethers5': patch +'@reown/appkit-adapter-polkadot': patch +'@reown/appkit-adapter-solana': patch +'@reown/appkit-adapter-wagmi': patch +'@reown/appkit': patch +'@reown/appkit-utils': patch +'@reown/appkit-cdn': patch +'@reown/appkit-common': patch +'@reown/appkit-core': patch +'@reown/appkit-experimental': patch +'@reown/appkit-polyfills': patch +'@reown/appkit-scaffold-ui': patch +'@reown/appkit-siwe': patch +--- + +Added maximum timeouts for frame requests \ No newline at end of file diff --git a/apps/laboratory/playwright.config.ts b/apps/laboratory/playwright.config.ts index 3392de7bd0..91fbb695f9 100644 --- a/apps/laboratory/playwright.config.ts +++ b/apps/laboratory/playwright.config.ts @@ -21,7 +21,7 @@ export default defineConfig({ expect: { timeout: getValue(60, 15) * 1000 }, - timeout: 60 * 1000, + timeout: 90 * 1000, use: { /* Base URL to use in actions like `await page.goto('/')`. */ diff --git a/apps/laboratory/tests/email.spec.ts b/apps/laboratory/tests/email.spec.ts index 286d83cdb1..9518129f38 100644 --- a/apps/laboratory/tests/email.spec.ts +++ b/apps/laboratory/tests/email.spec.ts @@ -11,7 +11,8 @@ let page: ModalWalletPage let validator: ModalWalletValidator let context: BrowserContext let browserPage: Page -/* eslint-enable init-declarations */ +let email: Email +let tempEmail: string // -- Setup -------------------------------------------------------------------- const emailTest = test.extend<{ library: string }>({ @@ -27,14 +28,15 @@ emailTest.beforeAll(async ({ browser, library }) => { page = new ModalWalletPage(browserPage, library, 'default') validator = new ModalWalletValidator(browserPage) + await page.page.context().setOffline(false) await page.load() const mailsacApiKey = process.env['MAILSAC_API_KEY'] if (!mailsacApiKey) { throw new Error('MAILSAC_API_KEY is not set') } - const email = new Email(mailsacApiKey) - const tempEmail = await email.getEmailAddressToUse() + email = new Email(mailsacApiKey) + tempEmail = await email.getEmailAddressToUse() await page.emailFlow(tempEmail, context, mailsacApiKey) await validator.expectConnected() @@ -105,3 +107,10 @@ emailTest('it should disconnect correctly', async () => { await page.disconnect() await validator.expectDisconnected() }) + +emailTest('it should abort request if it takes more than 30 seconds', async () => { + await page.page.context().setOffline(true) + await page.loginWithEmail(tempEmail, false) + await page.page.waitForTimeout(30_000) + await validator.expectSnackbar('Something went wrong') +}) diff --git a/apps/laboratory/tests/shared/pages/ModalPage.ts b/apps/laboratory/tests/shared/pages/ModalPage.ts index 3b388a456d..33d2f9e48b 100644 --- a/apps/laboratory/tests/shared/pages/ModalPage.ts +++ b/apps/laboratory/tests/shared/pages/ModalPage.ts @@ -179,7 +179,7 @@ export class ModalPage { await this.enterOTP(otp) } - async loginWithEmail(email: string) { + async loginWithEmail(email: string, validate = true) { // Connect Button doesn't have a proper `disabled` attribute so we need to wait for the button to change the text await this.page .getByTestId('connect-button') @@ -188,12 +188,14 @@ export class ModalPage { await this.page.getByTestId('wui-email-input').locator('input').focus() await this.page.getByTestId('wui-email-input').locator('input').fill(email) await this.page.getByTestId('wui-email-input').locator('input').press('Enter') - await expect( - this.page.getByText(email), - `Expected current email: ${email} to be visible on the notification screen` - ).toBeVisible({ - timeout: 20_000 - }) + if (validate) { + await expect( + this.page.getByText(email), + `Expected current email: ${email} to be visible on the notification screen` + ).toBeVisible({ + timeout: 20_000 + }) + } } async loginWithSocial(socialOption: 'github', socialMail: string, socialPass: string) { diff --git a/apps/laboratory/tests/shared/validators/ModalValidator.ts b/apps/laboratory/tests/shared/validators/ModalValidator.ts index 974d8e938f..a4922f1eaa 100644 --- a/apps/laboratory/tests/shared/validators/ModalValidator.ts +++ b/apps/laboratory/tests/shared/validators/ModalValidator.ts @@ -306,4 +306,10 @@ export class ModalValidator { const modal = this.page.getByTestId('w3m-modal') await expect(modal).toBeHidden() } + + async expectSnackbar(message: string) { + await expect(this.page.getByTestId('wui-snackbar-message')).toHaveText(message, { + timeout: MAX_WAIT + }) + } } diff --git a/packages/ui/src/composites/wui-snackbar/index.ts b/packages/ui/src/composites/wui-snackbar/index.ts index 82bec426f3..6928298f53 100644 --- a/packages/ui/src/composites/wui-snackbar/index.ts +++ b/packages/ui/src/composites/wui-snackbar/index.ts @@ -36,7 +36,9 @@ export class WuiSnackbar extends LitElement { icon=${this.icon} background="opaque" >`} - ${this.message} + ${this.message} ` } } diff --git a/packages/wallet/src/W3mFrameProvider.ts b/packages/wallet/src/W3mFrameProvider.ts index 13321839b4..52d15d735f 100644 --- a/packages/wallet/src/W3mFrameProvider.ts +++ b/packages/wallet/src/W3mFrameProvider.ts @@ -471,6 +471,8 @@ export class W3mFrameProvider { return type.replace('@w3m-app/', '') } + const abortController = new AbortController() + const type = replaceEventType(event.type) const shouldCheckForTimeout = [ @@ -484,16 +486,18 @@ export class W3mFrameProvider { .map(replaceEventType) .includes(type) - if (shouldCheckForTimeout && this.onTimeout) { - // 15 seconds timeout - timer = setTimeout(this.onTimeout, 15_000) + if (shouldCheckForTimeout) { + timer = setTimeout(() => { + this.onTimeout?.() + abortController.abort() + }, 30_000) } return new Promise((resolve, reject) => { const id = Math.random().toString(36).substring(7) this.w3mLogger.logger.info?.({ event, id }, 'Sending app event') this.w3mFrame.events.postAppEvent({ ...event, id } as W3mFrameTypes.AppEvent) - const abortController = new AbortController() + if (type === 'RPC_REQUEST') { const rpcEvent = event as Extract this.openRpcRequests = [...this.openRpcRequests, { ...rpcEvent.payload, abortController }] @@ -501,6 +505,8 @@ export class W3mFrameProvider { abortController.signal.addEventListener('abort', () => { if (type === 'RPC_REQUEST') { reject(new Error('Request was aborted')) + } else { + reject(new Error('Something went wrong')) } })