From 20257c7c68ca3d68a7c520e46865e1291b417f27 Mon Sep 17 00:00:00 2001 From: ignaciosantise Date: Mon, 15 Apr 2024 16:50:54 -0300 Subject: [PATCH 1/9] fix: check updateEmail response to redirect to primary or secondary update OTP view --- .../w3m-update-email-wallet-view/index.ts | 18 +++++++++++++----- packages/wallet/src/W3mFrameProvider.ts | 12 +++++++----- packages/wallet/src/W3mFrameSchema.ts | 5 ++++- packages/wallet/src/W3mFrameTypes.ts | 4 +++- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/packages/scaffold/src/views/w3m-update-email-wallet-view/index.ts b/packages/scaffold/src/views/w3m-update-email-wallet-view/index.ts index 22ab43a531..7a27296d28 100644 --- a/packages/scaffold/src/views/w3m-update-email-wallet-view/index.ts +++ b/packages/scaffold/src/views/w3m-update-email-wallet-view/index.ts @@ -84,12 +84,20 @@ export class W3mUpdateEmailWalletView extends LitElement { throw new Error('w3m-update-email-wallet: Email connector not found') } - await emailConnector.provider.updateEmail({ email: this.email }) + const response = await emailConnector.provider.updateEmail({ email: this.email }) EventsController.sendEvent({ type: 'track', event: 'EMAIL_EDIT' }) - RouterController.replace('UpdateEmailPrimaryOtp', { - email: this.initialEmail, - newEmail: this.email - }) + + if (response.action === 'VERIFY_PRIMARY_OTP') { + RouterController.push('UpdateEmailPrimaryOtp', { + email: this.initialEmail, + newEmail: this.email + }) + } else if (response.action === 'VERIFY_SECONDARY_OTP') { + RouterController.push('UpdateEmailSecondaryOtp', { + email: this.initialEmail, + newEmail: this.email + }) + } } catch (error) { SnackController.showError(error) this.loading = false diff --git a/packages/wallet/src/W3mFrameProvider.ts b/packages/wallet/src/W3mFrameProvider.ts index 1736274217..b1aad9055c 100644 --- a/packages/wallet/src/W3mFrameProvider.ts +++ b/packages/wallet/src/W3mFrameProvider.ts @@ -15,7 +15,7 @@ type IsConnectedResolver = Resolver type SwitchChainResolver = Resolver type RpcRequestResolver = Resolver -type UpdateEmailResolver = Resolver +type UpdateEmailResolver = Resolver type UpdateEmailPrimaryOtpResolver = Resolver type UpdateEmailSecondaryOtpResolver = Resolver< W3mFrameTypes.Responses['FrameUpdateEmailSecondaryOtpResolver'] @@ -109,7 +109,7 @@ export class W3mFrameProvider { case W3mFrameConstants.FRAME_SESSION_UPDATE: return this.onSessionUpdate(event) case W3mFrameConstants.FRAME_UPDATE_EMAIL_SUCCESS: - return this.onUpdateEmailSuccess() + return this.onUpdateEmailSuccess(event) case W3mFrameConstants.FRAME_UPDATE_EMAIL_ERROR: return this.onUpdateEmailError(event) case W3mFrameConstants.FRAME_UPDATE_EMAIL_PRIMARY_OTP_SUCCESS: @@ -210,7 +210,7 @@ export class W3mFrameProvider { W3mFrameHelpers.checkIfAllowedToTriggerEmail() this.w3mFrame.events.postAppEvent({ type: W3mFrameConstants.APP_UPDATE_EMAIL, payload }) - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { this.updateEmailResolver = { resolve, reject } }) } @@ -523,8 +523,10 @@ export class W3mFrameProvider { } } - private onUpdateEmailSuccess() { - this.updateEmailResolver?.resolve(undefined) + private onUpdateEmailSuccess( + event: Extract + ) { + this.updateEmailResolver?.resolve(event.payload) this.setNewLastEmailLoginTime() } diff --git a/packages/wallet/src/W3mFrameSchema.ts b/packages/wallet/src/W3mFrameSchema.ts index 0d17180af4..bb50391ae3 100644 --- a/packages/wallet/src/W3mFrameSchema.ts +++ b/packages/wallet/src/W3mFrameSchema.ts @@ -65,6 +65,9 @@ export const AppSetPreferredAccountRequest = z.object({ type: z.string() }) export const FrameConnectEmailResponse = z.object({ action: z.enum(['VERIFY_DEVICE', 'VERIFY_OTP']) }) +export const FrameUpdateEmailResponse = z.object({ + action: z.enum(['VERIFY_PRIMARY_OTP', 'VERIFY_SECONDARY_OTP']) +}) export const FrameGetUserResponse = z.object({ email: z.string().email(), address: z.string(), @@ -406,7 +409,7 @@ export const W3mFrameSchema = { .or(z.object({ type: zType('FRAME_UPDATE_EMAIL_ERROR'), payload: zError })) - .or(z.object({ type: zType('FRAME_UPDATE_EMAIL_SUCCESS') })) + .or(z.object({ type: zType('FRAME_UPDATE_EMAIL_SUCCESS'), payload: FrameUpdateEmailResponse })) .or(z.object({ type: zType('FRAME_UPDATE_EMAIL_PRIMARY_OTP_ERROR'), payload: zError })) diff --git a/packages/wallet/src/W3mFrameTypes.ts b/packages/wallet/src/W3mFrameTypes.ts index d3483d68f1..70082342f3 100644 --- a/packages/wallet/src/W3mFrameTypes.ts +++ b/packages/wallet/src/W3mFrameTypes.ts @@ -55,7 +55,8 @@ import { RpcEthChainId, FrameSwitchNetworkResponse, AppSyncDappDataRequest, - FrameGetSmartAccountEnabledNetworksResponse + FrameGetSmartAccountEnabledNetworksResponse, + FrameUpdateEmailResponse } from './W3mFrameSchema.js' import type { W3mFrameRpcConstants } from './W3mFrameConstants.js' @@ -86,6 +87,7 @@ export namespace W3mFrameTypes { FrameGetSmartAccountEnabledNetworksResponse: z.infer< typeof FrameGetSmartAccountEnabledNetworksResponse > + FrameUpdateEmailResponse: z.infer } export interface Network { From 183c798318cefcc93e9798dcf8b99d935504ed42 Mon Sep 17 00:00:00 2001 From: ignaciosantise Date: Mon, 15 Apr 2024 17:51:36 -0300 Subject: [PATCH 2/9] chore: changed redirect otp condition --- .../src/views/w3m-update-email-wallet-view/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/scaffold/src/views/w3m-update-email-wallet-view/index.ts b/packages/scaffold/src/views/w3m-update-email-wallet-view/index.ts index 7a27296d28..079ee62fe9 100644 --- a/packages/scaffold/src/views/w3m-update-email-wallet-view/index.ts +++ b/packages/scaffold/src/views/w3m-update-email-wallet-view/index.ts @@ -87,13 +87,13 @@ export class W3mUpdateEmailWalletView extends LitElement { const response = await emailConnector.provider.updateEmail({ email: this.email }) EventsController.sendEvent({ type: 'track', event: 'EMAIL_EDIT' }) - if (response.action === 'VERIFY_PRIMARY_OTP') { - RouterController.push('UpdateEmailPrimaryOtp', { + if (response.action === 'VERIFY_SECONDARY_OTP') { + RouterController.push('UpdateEmailSecondaryOtp', { email: this.initialEmail, newEmail: this.email }) - } else if (response.action === 'VERIFY_SECONDARY_OTP') { - RouterController.push('UpdateEmailSecondaryOtp', { + } else { + RouterController.push('UpdateEmailPrimaryOtp', { email: this.initialEmail, newEmail: this.email }) From 5d3beffb365043859a0116290abf91fa28abbf80 Mon Sep 17 00:00:00 2001 From: ignaciosantise Date: Wed, 17 Apr 2024 16:25:23 -0300 Subject: [PATCH 3/9] chore: added update email test --- apps/laboratory/tests/email.spec.ts | 9 +++ .../tests/shared/pages/ModalPage.ts | 61 +++++++++++++++++-- apps/laboratory/tests/shared/utils/email.ts | 6 ++ .../w3m-account-default-widget/index.ts | 1 + 4 files changed, 71 insertions(+), 6 deletions(-) diff --git a/apps/laboratory/tests/email.spec.ts b/apps/laboratory/tests/email.spec.ts index 8b20538af1..3916bf66ce 100644 --- a/apps/laboratory/tests/email.spec.ts +++ b/apps/laboratory/tests/email.spec.ts @@ -2,6 +2,11 @@ import { expect } from '@playwright/test' import { testMEmail } from './shared/fixtures/w3m-email-fixture' import { SECURE_WEBSITE_URL } from './shared/constants' +const mailsacApiKey = process.env['MAILSAC_API_KEY'] +if (!mailsacApiKey) { + throw new Error('MAILSAC_API_KEY is not set') +} + testMEmail.beforeEach(async ({ modalValidator }) => { await modalValidator.expectConnected() }) @@ -48,3 +53,7 @@ testMEmail('it should disconnect correctly', async ({ modalPage, modalValidator await modalPage.disconnect() await modalValidator.expectDisconnected() }) + +testMEmail('it should update email', async ({ modalPage }) => { + await modalPage.updateEmail(mailsacApiKey) +}) diff --git a/apps/laboratory/tests/shared/pages/ModalPage.ts b/apps/laboratory/tests/shared/pages/ModalPage.ts index 3fae7819b4..f99a26f153 100644 --- a/apps/laboratory/tests/shared/pages/ModalPage.ts +++ b/apps/laboratory/tests/shared/pages/ModalPage.ts @@ -13,6 +13,7 @@ export class ModalPage { private readonly connectButton: Locator private readonly url: string + private emailAddress = '' constructor( public readonly page: Page, @@ -61,6 +62,8 @@ export class ModalPage { ): Promise { await this.load() + this.emailAddress = emailAddress + const email = new Email(mailsacApiKey) await email.deleteAllMessages(emailAddress) @@ -93,7 +96,8 @@ export class ModalPage { if (otp.replace(' ', '').length !== 6) { otp = email.getOtpCodeFromBody(emailBody) } - await this.enterOTP(otp) + // Remove empy space in OTP code 111 111 + await this.enterOTP(otp.replace(' ', '')) } async loginWithEmail(email: string) { @@ -114,16 +118,14 @@ export class ModalPage { }) } - async enterOTP(otp: string) { - await expect(this.page.getByText('Confirm Email')).toBeVisible({ + async enterOTP(otp: string, headerTitle = 'Confirm Email') { + await expect(this.page.getByText(headerTitle)).toBeVisible({ timeout: 10_000 }) await expect(this.page.getByText('Enter the code we sent')).toBeVisible({ timeout: 10_000 }) const splitted = otp.split('') - // Remove empy space in OTP code 111 111 - splitted.splice(3, 1) // eslint-disable-next-line no-plusplus for (let i = 0; i < splitted.length; i++) { @@ -143,7 +145,7 @@ export class ModalPage { await input.fill(digit) } - await expect(this.page.getByText('Confirm Email')).not.toBeVisible() + await expect(this.page.getByText(headerTitle)).not.toBeVisible() } async disconnect() { @@ -226,4 +228,51 @@ export class ModalPage { async closeModal() { await this.page.getByTestId('w3m-header-close')?.click?.() } + + async updateEmail(mailsacApiKey: string) { + const email = new Email(mailsacApiKey) + const newEmailAddress = email.getNewEmailAddress(this.emailAddress) + + await this.page.getByTestId('account-button').click() + await this.page.getByTestId('w3m-account-email-update').click() + await this.page.getByTestId('wui-email-input').locator('input').focus() + await this.page.getByTestId('wui-email-input').locator('input').fill(newEmailAddress) + + // Clear messages before putting new email + await email.deleteAllMessages(this.emailAddress) + await this.page.getByTestId('wui-email-input').locator('input').press('Enter') + + // Wait until the next screen appears + await expect(this.page.getByText('Enter the code we sent')).toBeVisible({ + timeout: 10_000 + }) + const confirmCurrentEmail = await this.page.getByText(this.emailAddress).isVisible() + if (confirmCurrentEmail) { + await this.updateOtpFlow(this.emailAddress, mailsacApiKey, 'Confirm Current Email') + } + + // The new OTP will arrive in the same email address as we are using the same email +new + await this.updateOtpFlow(this.emailAddress, mailsacApiKey, 'Confirm New Email') + + expect( + this.page.getByTestId('w3m-account-email-update'), + `Expected to go to the account screen after the update` + ).toBeVisible() + } + + async updateOtpFlow(emailAddress: string, mailsacApiKey: string, headerTitle: string) { + const email = new Email(mailsacApiKey) + + const messageId = await email.getLatestMessageId(emailAddress) + + if (!messageId) { + throw new Error('No messageId found') + } + const emailBody = await email.getEmailBody(emailAddress, messageId) + const otp = email.getOtpCodeFromBody(emailBody).replace(' ', '') + + // Clear messages before putting OTP + email.deleteAllMessages(emailAddress) + await this.enterOTP(otp, headerTitle) + } } diff --git a/apps/laboratory/tests/shared/utils/email.ts b/apps/laboratory/tests/shared/utils/email.ts index 57dcff4516..1d90693e51 100644 --- a/apps/laboratory/tests/shared/utils/email.ts +++ b/apps/laboratory/tests/shared/utils/email.ts @@ -85,4 +85,10 @@ export class Email { return `tests-${index}@${EMAIL_DOMAIN}` } + + getNewEmailAddress(emailAddress: string): string { + const emailIndex = emailAddress.match(/\d{1}/u) + + return emailAddress.replace(`tests-${emailIndex}`, `tests-${emailIndex}+${Date.now()}`) + } } diff --git a/packages/scaffold/src/partials/w3m-account-default-widget/index.ts b/packages/scaffold/src/partials/w3m-account-default-widget/index.ts index 8703f0af4b..2fa3411267 100644 --- a/packages/scaffold/src/partials/w3m-account-default-widget/index.ts +++ b/packages/scaffold/src/partials/w3m-account-default-widget/index.ts @@ -232,6 +232,7 @@ export class W3mAccountDefaultWidget extends LitElement { iconVariant="overlay" icon="mail" iconSize="sm" + data-testid="w3m-account-email-update" ?chevron=${true} @click=${() => this.onGoToUpdateEmail(email)} > From 017fc6232fc167e1b2a292cec9ed46caa139d99d Mon Sep 17 00:00:00 2001 From: ignaciosantise Date: Thu, 18 Apr 2024 10:35:13 -0300 Subject: [PATCH 4/9] chore: updated email test --- apps/laboratory/tests/shared/pages/ModalPage.ts | 7 ++----- apps/laboratory/tests/shared/utils/email.ts | 6 ------ 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/apps/laboratory/tests/shared/pages/ModalPage.ts b/apps/laboratory/tests/shared/pages/ModalPage.ts index f99a26f153..4029c3f9fc 100644 --- a/apps/laboratory/tests/shared/pages/ModalPage.ts +++ b/apps/laboratory/tests/shared/pages/ModalPage.ts @@ -231,7 +231,7 @@ export class ModalPage { async updateEmail(mailsacApiKey: string) { const email = new Email(mailsacApiKey) - const newEmailAddress = email.getNewEmailAddress(this.emailAddress) + const newEmailAddress = email.getEmailAddressToUse(1) await this.page.getByTestId('account-button').click() await this.page.getByTestId('w3m-account-email-update').click() @@ -251,8 +251,7 @@ export class ModalPage { await this.updateOtpFlow(this.emailAddress, mailsacApiKey, 'Confirm Current Email') } - // The new OTP will arrive in the same email address as we are using the same email +new - await this.updateOtpFlow(this.emailAddress, mailsacApiKey, 'Confirm New Email') + await this.updateOtpFlow(newEmailAddress, mailsacApiKey, 'Confirm New Email') expect( this.page.getByTestId('w3m-account-email-update'), @@ -271,8 +270,6 @@ export class ModalPage { const emailBody = await email.getEmailBody(emailAddress, messageId) const otp = email.getOtpCodeFromBody(emailBody).replace(' ', '') - // Clear messages before putting OTP - email.deleteAllMessages(emailAddress) await this.enterOTP(otp, headerTitle) } } diff --git a/apps/laboratory/tests/shared/utils/email.ts b/apps/laboratory/tests/shared/utils/email.ts index 16b2b24519..339b0d3f9f 100644 --- a/apps/laboratory/tests/shared/utils/email.ts +++ b/apps/laboratory/tests/shared/utils/email.ts @@ -80,10 +80,4 @@ export class Email { return `${prefix}-w${index}@${EMAIL_DOMAIN}` } - - getNewEmailAddress(emailAddress: string): string { - const emailIndex = emailAddress.match(/\d{1}/u) - - return emailAddress.replace(`tests-${emailIndex}`, `tests-${emailIndex}+${Date.now()}`) - } } From 4db69ef21025920633bbcd1f0d415624b778c9bd Mon Sep 17 00:00:00 2001 From: ignaciosantise Date: Thu, 18 Apr 2024 11:13:57 -0300 Subject: [PATCH 5/9] chore: check for header instead of user email to decide which otp screen is --- apps/laboratory/tests/shared/pages/ModalPage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/laboratory/tests/shared/pages/ModalPage.ts b/apps/laboratory/tests/shared/pages/ModalPage.ts index 4029c3f9fc..3741433b10 100644 --- a/apps/laboratory/tests/shared/pages/ModalPage.ts +++ b/apps/laboratory/tests/shared/pages/ModalPage.ts @@ -246,7 +246,7 @@ export class ModalPage { await expect(this.page.getByText('Enter the code we sent')).toBeVisible({ timeout: 10_000 }) - const confirmCurrentEmail = await this.page.getByText(this.emailAddress).isVisible() + const confirmCurrentEmail = await this.page.getByText('Confirm Current Email').isVisible() if (confirmCurrentEmail) { await this.updateOtpFlow(this.emailAddress, mailsacApiKey, 'Confirm Current Email') } From f25a4827382120091e06c9e29a394e0774d959e2 Mon Sep 17 00:00:00 2001 From: ignaciosantise Date: Thu, 18 Apr 2024 11:30:13 -0300 Subject: [PATCH 6/9] chore: code improvements --- apps/laboratory/tests/shared/pages/ModalPage.ts | 10 ++++++---- apps/laboratory/tests/shared/utils/email.ts | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/laboratory/tests/shared/pages/ModalPage.ts b/apps/laboratory/tests/shared/pages/ModalPage.ts index 3741433b10..1ae452bc41 100644 --- a/apps/laboratory/tests/shared/pages/ModalPage.ts +++ b/apps/laboratory/tests/shared/pages/ModalPage.ts @@ -93,11 +93,12 @@ export class ModalPage { otp = email.getOtpCodeFromBody(emailBody) } } - if (otp.replace(' ', '').length !== 6) { + + if (otp === '') { otp = email.getOtpCodeFromBody(emailBody) } - // Remove empy space in OTP code 111 111 - await this.enterOTP(otp.replace(' ', '')) + + await this.enterOTP(otp) } async loginWithEmail(email: string) { @@ -125,6 +126,7 @@ export class ModalPage { await expect(this.page.getByText('Enter the code we sent')).toBeVisible({ timeout: 10_000 }) + const splitted = otp.split('') // eslint-disable-next-line no-plusplus @@ -268,7 +270,7 @@ export class ModalPage { throw new Error('No messageId found') } const emailBody = await email.getEmailBody(emailAddress, messageId) - const otp = email.getOtpCodeFromBody(emailBody).replace(' ', '') + const otp = email.getOtpCodeFromBody(emailBody) await this.enterOTP(otp, headerTitle) } diff --git a/apps/laboratory/tests/shared/utils/email.ts b/apps/laboratory/tests/shared/utils/email.ts index 339b0d3f9f..9ff9be8ae7 100644 --- a/apps/laboratory/tests/shared/utils/email.ts +++ b/apps/laboratory/tests/shared/utils/email.ts @@ -69,7 +69,8 @@ export class Email { getOtpCodeFromBody(body: string): string { const match = body.match(OTP_CODE_REGEX) if (match) { - return match[0] + // Remove empty space in OTP code 111 111 + return match[0].replace(' ', '') } throw new Error(`No code found in email: ${body}`) From 0bc55aa2113f8e75fa3c09f1bfda383e0ee77381 Mon Sep 17 00:00:00 2001 From: ignaciosantise Date: Thu, 18 Apr 2024 12:10:17 -0300 Subject: [PATCH 7/9] chore: revert test changes --- apps/laboratory/tests/email.spec.ts | 9 --- .../tests/shared/pages/ModalPage.ts | 60 ++----------------- apps/laboratory/tests/shared/utils/email.ts | 3 +- 3 files changed, 7 insertions(+), 65 deletions(-) diff --git a/apps/laboratory/tests/email.spec.ts b/apps/laboratory/tests/email.spec.ts index 3916bf66ce..8b20538af1 100644 --- a/apps/laboratory/tests/email.spec.ts +++ b/apps/laboratory/tests/email.spec.ts @@ -2,11 +2,6 @@ import { expect } from '@playwright/test' import { testMEmail } from './shared/fixtures/w3m-email-fixture' import { SECURE_WEBSITE_URL } from './shared/constants' -const mailsacApiKey = process.env['MAILSAC_API_KEY'] -if (!mailsacApiKey) { - throw new Error('MAILSAC_API_KEY is not set') -} - testMEmail.beforeEach(async ({ modalValidator }) => { await modalValidator.expectConnected() }) @@ -53,7 +48,3 @@ testMEmail('it should disconnect correctly', async ({ modalPage, modalValidator await modalPage.disconnect() await modalValidator.expectDisconnected() }) - -testMEmail('it should update email', async ({ modalPage }) => { - await modalPage.updateEmail(mailsacApiKey) -}) diff --git a/apps/laboratory/tests/shared/pages/ModalPage.ts b/apps/laboratory/tests/shared/pages/ModalPage.ts index 1ae452bc41..3fae7819b4 100644 --- a/apps/laboratory/tests/shared/pages/ModalPage.ts +++ b/apps/laboratory/tests/shared/pages/ModalPage.ts @@ -13,7 +13,6 @@ export class ModalPage { private readonly connectButton: Locator private readonly url: string - private emailAddress = '' constructor( public readonly page: Page, @@ -62,8 +61,6 @@ export class ModalPage { ): Promise { await this.load() - this.emailAddress = emailAddress - const email = new Email(mailsacApiKey) await email.deleteAllMessages(emailAddress) @@ -93,11 +90,9 @@ export class ModalPage { otp = email.getOtpCodeFromBody(emailBody) } } - - if (otp === '') { + if (otp.replace(' ', '').length !== 6) { otp = email.getOtpCodeFromBody(emailBody) } - await this.enterOTP(otp) } @@ -119,15 +114,16 @@ export class ModalPage { }) } - async enterOTP(otp: string, headerTitle = 'Confirm Email') { - await expect(this.page.getByText(headerTitle)).toBeVisible({ + async enterOTP(otp: string) { + await expect(this.page.getByText('Confirm Email')).toBeVisible({ timeout: 10_000 }) await expect(this.page.getByText('Enter the code we sent')).toBeVisible({ timeout: 10_000 }) - const splitted = otp.split('') + // Remove empy space in OTP code 111 111 + splitted.splice(3, 1) // eslint-disable-next-line no-plusplus for (let i = 0; i < splitted.length; i++) { @@ -147,7 +143,7 @@ export class ModalPage { await input.fill(digit) } - await expect(this.page.getByText(headerTitle)).not.toBeVisible() + await expect(this.page.getByText('Confirm Email')).not.toBeVisible() } async disconnect() { @@ -230,48 +226,4 @@ export class ModalPage { async closeModal() { await this.page.getByTestId('w3m-header-close')?.click?.() } - - async updateEmail(mailsacApiKey: string) { - const email = new Email(mailsacApiKey) - const newEmailAddress = email.getEmailAddressToUse(1) - - await this.page.getByTestId('account-button').click() - await this.page.getByTestId('w3m-account-email-update').click() - await this.page.getByTestId('wui-email-input').locator('input').focus() - await this.page.getByTestId('wui-email-input').locator('input').fill(newEmailAddress) - - // Clear messages before putting new email - await email.deleteAllMessages(this.emailAddress) - await this.page.getByTestId('wui-email-input').locator('input').press('Enter') - - // Wait until the next screen appears - await expect(this.page.getByText('Enter the code we sent')).toBeVisible({ - timeout: 10_000 - }) - const confirmCurrentEmail = await this.page.getByText('Confirm Current Email').isVisible() - if (confirmCurrentEmail) { - await this.updateOtpFlow(this.emailAddress, mailsacApiKey, 'Confirm Current Email') - } - - await this.updateOtpFlow(newEmailAddress, mailsacApiKey, 'Confirm New Email') - - expect( - this.page.getByTestId('w3m-account-email-update'), - `Expected to go to the account screen after the update` - ).toBeVisible() - } - - async updateOtpFlow(emailAddress: string, mailsacApiKey: string, headerTitle: string) { - const email = new Email(mailsacApiKey) - - const messageId = await email.getLatestMessageId(emailAddress) - - if (!messageId) { - throw new Error('No messageId found') - } - const emailBody = await email.getEmailBody(emailAddress, messageId) - const otp = email.getOtpCodeFromBody(emailBody) - - await this.enterOTP(otp, headerTitle) - } } diff --git a/apps/laboratory/tests/shared/utils/email.ts b/apps/laboratory/tests/shared/utils/email.ts index 9ff9be8ae7..339b0d3f9f 100644 --- a/apps/laboratory/tests/shared/utils/email.ts +++ b/apps/laboratory/tests/shared/utils/email.ts @@ -69,8 +69,7 @@ export class Email { getOtpCodeFromBody(body: string): string { const match = body.match(OTP_CODE_REGEX) if (match) { - // Remove empty space in OTP code 111 111 - return match[0].replace(' ', '') + return match[0] } throw new Error(`No code found in email: ${body}`) From 20ed7b323eccc9e19d8145bbe4dce90808e0d035 Mon Sep 17 00:00:00 2001 From: ignaciosantise Date: Thu, 18 Apr 2024 12:30:06 -0300 Subject: [PATCH 8/9] chore: added update email tests --- apps/laboratory/tests/email.spec.ts | 9 +++ .../tests/shared/pages/ModalPage.ts | 60 +++++++++++++++++-- apps/laboratory/tests/shared/utils/email.ts | 3 +- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/apps/laboratory/tests/email.spec.ts b/apps/laboratory/tests/email.spec.ts index 8b20538af1..3916bf66ce 100644 --- a/apps/laboratory/tests/email.spec.ts +++ b/apps/laboratory/tests/email.spec.ts @@ -2,6 +2,11 @@ import { expect } from '@playwright/test' import { testMEmail } from './shared/fixtures/w3m-email-fixture' import { SECURE_WEBSITE_URL } from './shared/constants' +const mailsacApiKey = process.env['MAILSAC_API_KEY'] +if (!mailsacApiKey) { + throw new Error('MAILSAC_API_KEY is not set') +} + testMEmail.beforeEach(async ({ modalValidator }) => { await modalValidator.expectConnected() }) @@ -48,3 +53,7 @@ testMEmail('it should disconnect correctly', async ({ modalPage, modalValidator await modalPage.disconnect() await modalValidator.expectDisconnected() }) + +testMEmail('it should update email', async ({ modalPage }) => { + await modalPage.updateEmail(mailsacApiKey) +}) diff --git a/apps/laboratory/tests/shared/pages/ModalPage.ts b/apps/laboratory/tests/shared/pages/ModalPage.ts index 3fae7819b4..1ae452bc41 100644 --- a/apps/laboratory/tests/shared/pages/ModalPage.ts +++ b/apps/laboratory/tests/shared/pages/ModalPage.ts @@ -13,6 +13,7 @@ export class ModalPage { private readonly connectButton: Locator private readonly url: string + private emailAddress = '' constructor( public readonly page: Page, @@ -61,6 +62,8 @@ export class ModalPage { ): Promise { await this.load() + this.emailAddress = emailAddress + const email = new Email(mailsacApiKey) await email.deleteAllMessages(emailAddress) @@ -90,9 +93,11 @@ export class ModalPage { otp = email.getOtpCodeFromBody(emailBody) } } - if (otp.replace(' ', '').length !== 6) { + + if (otp === '') { otp = email.getOtpCodeFromBody(emailBody) } + await this.enterOTP(otp) } @@ -114,16 +119,15 @@ export class ModalPage { }) } - async enterOTP(otp: string) { - await expect(this.page.getByText('Confirm Email')).toBeVisible({ + async enterOTP(otp: string, headerTitle = 'Confirm Email') { + await expect(this.page.getByText(headerTitle)).toBeVisible({ timeout: 10_000 }) await expect(this.page.getByText('Enter the code we sent')).toBeVisible({ timeout: 10_000 }) + const splitted = otp.split('') - // Remove empy space in OTP code 111 111 - splitted.splice(3, 1) // eslint-disable-next-line no-plusplus for (let i = 0; i < splitted.length; i++) { @@ -143,7 +147,7 @@ export class ModalPage { await input.fill(digit) } - await expect(this.page.getByText('Confirm Email')).not.toBeVisible() + await expect(this.page.getByText(headerTitle)).not.toBeVisible() } async disconnect() { @@ -226,4 +230,48 @@ export class ModalPage { async closeModal() { await this.page.getByTestId('w3m-header-close')?.click?.() } + + async updateEmail(mailsacApiKey: string) { + const email = new Email(mailsacApiKey) + const newEmailAddress = email.getEmailAddressToUse(1) + + await this.page.getByTestId('account-button').click() + await this.page.getByTestId('w3m-account-email-update').click() + await this.page.getByTestId('wui-email-input').locator('input').focus() + await this.page.getByTestId('wui-email-input').locator('input').fill(newEmailAddress) + + // Clear messages before putting new email + await email.deleteAllMessages(this.emailAddress) + await this.page.getByTestId('wui-email-input').locator('input').press('Enter') + + // Wait until the next screen appears + await expect(this.page.getByText('Enter the code we sent')).toBeVisible({ + timeout: 10_000 + }) + const confirmCurrentEmail = await this.page.getByText('Confirm Current Email').isVisible() + if (confirmCurrentEmail) { + await this.updateOtpFlow(this.emailAddress, mailsacApiKey, 'Confirm Current Email') + } + + await this.updateOtpFlow(newEmailAddress, mailsacApiKey, 'Confirm New Email') + + expect( + this.page.getByTestId('w3m-account-email-update'), + `Expected to go to the account screen after the update` + ).toBeVisible() + } + + async updateOtpFlow(emailAddress: string, mailsacApiKey: string, headerTitle: string) { + const email = new Email(mailsacApiKey) + + const messageId = await email.getLatestMessageId(emailAddress) + + if (!messageId) { + throw new Error('No messageId found') + } + const emailBody = await email.getEmailBody(emailAddress, messageId) + const otp = email.getOtpCodeFromBody(emailBody) + + await this.enterOTP(otp, headerTitle) + } } diff --git a/apps/laboratory/tests/shared/utils/email.ts b/apps/laboratory/tests/shared/utils/email.ts index 339b0d3f9f..9ff9be8ae7 100644 --- a/apps/laboratory/tests/shared/utils/email.ts +++ b/apps/laboratory/tests/shared/utils/email.ts @@ -69,7 +69,8 @@ export class Email { getOtpCodeFromBody(body: string): string { const match = body.match(OTP_CODE_REGEX) if (match) { - return match[0] + // Remove empty space in OTP code 111 111 + return match[0].replace(' ', '') } throw new Error(`No code found in email: ${body}`) From db178db939a20c20f631e08fabba942d8bbad7ae Mon Sep 17 00:00:00 2001 From: ignaciosantise Date: Mon, 22 Apr 2024 15:05:37 -0300 Subject: [PATCH 9/9] chore: get mailsac api key inside tests --- apps/laboratory/tests/email.spec.ts | 10 +++++----- .../tests/shared/fixtures/w3m-smart-account-fixture.ts | 9 ++++----- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/apps/laboratory/tests/email.spec.ts b/apps/laboratory/tests/email.spec.ts index ac5a383b01..55d075eaa5 100644 --- a/apps/laboratory/tests/email.spec.ts +++ b/apps/laboratory/tests/email.spec.ts @@ -2,11 +2,6 @@ import { expect } from '@playwright/test' import { testMEmail } from './shared/fixtures/w3m-email-fixture' import { SECURE_WEBSITE_URL } from './shared/constants' -const mailsacApiKey = process.env['MAILSAC_API_KEY'] -if (!mailsacApiKey) { - throw new Error('MAILSAC_API_KEY is not set') -} - testMEmail.beforeEach(async ({ modalValidator }) => { await modalValidator.expectConnected() }) @@ -55,5 +50,10 @@ testMEmail('it should disconnect correctly', async ({ modalPage, modalValidator }) testMEmail('it should update email', async ({ modalPage }) => { + const mailsacApiKey = process.env['MAILSAC_API_KEY'] + if (!mailsacApiKey) { + throw new Error('MAILSAC_API_KEY is not set') + } + await modalPage.updateEmail(mailsacApiKey) }) diff --git a/apps/laboratory/tests/shared/fixtures/w3m-smart-account-fixture.ts b/apps/laboratory/tests/shared/fixtures/w3m-smart-account-fixture.ts index 90fb4d22f7..bf5ce07f4c 100644 --- a/apps/laboratory/tests/shared/fixtures/w3m-smart-account-fixture.ts +++ b/apps/laboratory/tests/shared/fixtures/w3m-smart-account-fixture.ts @@ -5,11 +5,6 @@ import { ModalWalletPage } from '../pages/ModalWalletPage' import { ModalWalletValidator } from '../validators/ModalWalletValidator' import type { ModalPage } from '../pages/ModalPage' -const mailsacApiKey = process.env['MAILSAC_API_KEY'] -if (!mailsacApiKey) { - throw new Error('MAILSAC_API_KEY is not set') -} - // Test Modal + Smart Account export const testModalSmartAccount = base.extend({ library: ['wagmi', { option: true }], @@ -18,6 +13,10 @@ export const testModalSmartAccount = base.extend