Skip to content

Commit

Permalink
feat(ui-test): cover email
Browse files Browse the repository at this point in the history
  • Loading branch information
arein committed Dec 29, 2023
1 parent 6699133 commit 2d74afe
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 8 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ui_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ jobs:
env:
NEXT_PUBLIC_PROJECT_ID: ${{ secrets.NEXT_PUBLIC_PROJECT_ID }}
NEXTAUTH_SECRET: ${{ secrets.TESTS_NEXTAUTH_SECRET }}
MAILSEC_API_KEY: ${{ secrets.TESTS_MAILSEC_API_KEY }}
CI: true
working-directory: ./apps/laboratory/
run: npm run playwright:test
Expand Down
1 change: 1 addition & 0 deletions apps/laboratory/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Obtain a project ID from https://cloud.walletconnect.com
NEXT_PUBLIC_PROJECT_ID=""
NEXTAUTH_SECRET=""
MAILSEC_API_KEY=""
3 changes: 2 additions & 1 deletion apps/laboratory/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"devDependencies": {
"@playwright/test": "1.40.1",
"dotenv": "16.3.1",
"ethers": "6.9.0"
"ethers": "6.9.0",
"@mailsac/api": "1.0.5"
}
}
20 changes: 20 additions & 0 deletions apps/laboratory/tests/email.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { testMEmail } from './shared/fixtures/w3m-fixture'
import { Email } from './shared/utils/email'

testMEmail.beforeEach(async ({ modalPage }) => {
const tempEmail = `web3modal@mailsac.com` // TODO: we pay per user so need to improve this
const email = new Email(process.env['MAILSAC_API_KEY']!)
await email.deleteAllMessages(tempEmail)
await modalPage.loginWithEmail(tempEmail)

const latestMessage: any = await email.getNewMessage(tempEmail)
const messageId = latestMessage._id
const otp = await email.getCodeFromEmail(tempEmail, messageId)

await modalPage.enterOTP(otp)
})

testMEmail('it should sign', async ({ modalValidator }) => {
await modalValidator.expectConnected()
// TODO Implement sign
})
12 changes: 12 additions & 0 deletions apps/laboratory/tests/shared/fixtures/w3m-fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,16 @@ export const testMSiwe = base.extend<ModalFixture>({
await use(modalValidator)
}
})
export const testMEmail = base.extend<ModalFixture>({
library: ['wagmi', { option: true }],
modalPage: async ({ page, library }, use) => {
const modalPage = new ModalPage(page, library, 'email')
await modalPage.load()
await use(modalPage)
},
modalValidator: async ({ modalPage }, use) => {
const modalValidator = new ModalValidator(modalPage.page)
await use(modalValidator)
}
})
export { expect } from '@playwright/test'
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { testM as base, testMSiwe as siwe } from './w3m-fixture'
import { testM as base, testMSiwe as siwe, testMEmail as email } from './w3m-fixture'
import { WalletPage } from '../pages/WalletPage'
import { WalletValidator } from '../validators/WalletValidator'

Expand Down
22 changes: 19 additions & 3 deletions apps/laboratory/tests/shared/pages/ModalPage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Locator, Page } from '@playwright/test'
import { BASE_URL } from '../constants'

export type ModalFlavor = 'default' | 'siwe'
export type ModalFlavor = 'default' | 'siwe' | 'email'

export class ModalPage {
private readonly baseURL = BASE_URL
Expand All @@ -16,8 +16,8 @@ export class ModalPage {
) {
this.connectButton = this.page.getByTestId('connect-button')
this.url =
flavor === 'siwe'
? `${this.baseURL}library/${this.library}-siwe/`
flavor !== 'default'
? `${this.baseURL}library/${this.library}-${this.flavor}/`
: `${this.baseURL}library/${this.library}/`
}

Expand All @@ -33,6 +33,22 @@ export class ModalPage {
await this.page.getByTestId('copy-wc2-uri').click()
}

async loginWithEmail(email: string) {
await this.page.goto(this.url)
await this.connectButton.click()
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')
}

async enterOTP(otp: string) {
const splitted = otp.split('')
for (let i = 0; i < splitted.length; i++) {
await this.page.getByTestId('wui-otp-input').locator('input').nth(i).focus()
await this.page.getByTestId('wui-otp-input').locator('input').nth(i).fill(splitted[i]!)
}
}

async disconnect() {
await this.page.getByTestId('account-button').click()
await this.page.getByTestId('disconnect-button').click()
Expand Down
48 changes: 48 additions & 0 deletions apps/laboratory/tests/shared/utils/email.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Mailsac, type EmailMessage } from '@mailsac/api'

export class Email {
private readonly mailsac: Mailsac<any>
private messageCount: any
constructor(public readonly apiKey: string) {
this.mailsac = new Mailsac({ headers: { "Mailsac-Key": apiKey } })
this.messageCount = undefined
}

async deleteAllMessages(email: string) {
this.messageCount = 0
return await this.mailsac.messages.deleteAllMessages(email)
}

async getNewMessage(email: string) {
const timeout = new Promise((_, reject) => {
setTimeout(() => {
reject('timeout')
}, 25000)
})

const messagePoll = new Promise((resolve) => {
const interval = setInterval(async () => {
const messages = await this.mailsac.messages.listMessages(email)
if (messages.data.length > this.messageCount) {
clearInterval(interval)
this.messageCount = messages.data.length
const message = messages.data[messages.data.length - 1] as EmailMessage
return resolve(message)
}
}, 500)
})

return Promise.any([timeout, messagePoll])
}

async getCodeFromEmail(email: string, messageId: string) {
const result = await this.mailsac.messages.getBodyPlainText(email, messageId)
const regex = /\d{3}\s?\d{3}/
const match = result.data.match(regex)
if (match) {
return match[0].replace(/\s/g, '')
} else {
throw new Error('No code found in email: ' + result.data)
}
}
}
11 changes: 9 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/ui/src/composites/wui-email-input/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class WuiEmailInput extends LitElement {
size="md"
.disabled=${this.disabled}
.value=${this.value}
data-testid="wui-email-input"
></wui-input-text>
${this.templateError()}
`
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/composites/wui-otp/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class WuiOtp extends LitElement {
// -- Render -------------------------------------------- //
public override render() {
return html`
<wui-flex gap="xxs">
<wui-flex gap="xxs" data-testid="wui-otp-input">
${Array.from({ length: this.length }).map(
(_, index: number) => html`
<wui-input-numeric
Expand Down

0 comments on commit 2d74afe

Please sign in to comment.