Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: test improvements #1936

Merged
merged 30 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
53ac0de
feat: build project params in config
lukaisailovic Feb 16, 2024
4a37162
Merge branch 'V4' into feat/test-improvements
lukaisailovic Feb 16, 2024
1e10fc5
fix: lint
lukaisailovic Feb 16, 2024
666ffe4
Merge branch 'V4' into feat/test-improvements
lukaisailovic Feb 20, 2024
2833de4
feat: add support for deep linking
lukaisailovic Feb 20, 2024
b7d987b
feat: temp disable connect uri
lukaisailovic Feb 20, 2024
94a01ea
Merge branch 'V4' into feat/test-improvements
lukaisailovic Feb 21, 2024
8175f5a
feat: connect with deeplink on all tests
lukaisailovic Feb 21, 2024
abc2e84
feat: extract connection validation
lukaisailovic Feb 21, 2024
4ee9a7e
fix: use provided wallet url in laboratory
lukaisailovic Feb 21, 2024
ac98de3
feat: add separate test for connecting with uri
lukaisailovic Feb 21, 2024
6934771
fix: naming
lukaisailovic Feb 21, 2024
ac9c9b5
feat: handle session connection in fixture
lukaisailovic Feb 21, 2024
e2fcd13
fix: siwe deeplinking
lukaisailovic Feb 21, 2024
a8582df
fix: deeplinking not working on firefox
lukaisailovic Feb 21, 2024
012242e
fix: revert deeplinking on siwe
lukaisailovic Feb 21, 2024
5e7113e
fix: don't test disconnect on firefox
lukaisailovic Feb 21, 2024
cfda43b
feat: refactor request action
lukaisailovic Feb 21, 2024
2b3e62b
fix: wait for load state before accepting request
lukaisailovic Feb 21, 2024
4ec4e5e
Merge branch 'V4' into feat/test-improvements
lukaisailovic Feb 21, 2024
df9cfca
fix: increase timeout for session establishment
lukaisailovic Feb 21, 2024
aabcdc4
feat: open pages in new contexts
lukaisailovic Feb 21, 2024
f012345
fix: look for account button by locator
lukaisailovic Feb 21, 2024
341662c
Merge branch 'V4' into feat/test-improvements
lukaisailovic Feb 21, 2024
9d7a0c6
Merge branch 'V4' into feat/test-improvements
lukaisailovic Feb 22, 2024
44c40ce
Merge branch 'V4' into feat/test-improvements
lukaisailovic Feb 22, 2024
070219d
Merge branch 'V4' into feat/test-improvements
lukaisailovic Feb 26, 2024
d4f7764
chore: remove multiple context instances
lukaisailovic Feb 26, 2024
2264543
chore: add validation messages
lukaisailovic Feb 26, 2024
e4d0fe2
chore: add more validation messages
lukaisailovic Feb 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions apps/laboratory/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
"playwright:start": "npm run dev:laboratory",
"playwright:install": "npx playwright install --with-deps",
"playwright:test": "npx playwright test",
"playwright:test:wallet": "npx playwright test --grep connect.spec.ts",
"playwright:test:wallet": "npx playwright test --grep 'connect-qr.spec.ts|wallet.spec.ts'",
"playwright:test:siwe": "npx playwright test --grep siwe.spec.ts",
"playwright:test:canary": "npx playwright test --grep canary.spec.ts --project='Desktop Chrome/wagmi'",
"playwright:debug": "npx playwright test --debug",
"playwright:debug:wallet": "npx playwright test --debug --grep connect.spec.ts",
"playwright:debug:wallet": "npx playwright test --debug 'connect-qr.spec.ts|wallet.spec.ts'",
"playwright:debug:siwe": "npx playwright test --debug --grep siwe.spec.ts",
"playwright:debug:canary": "npx playwright test --debug --grep canary.spec.ts --project='Desktop Chrome/wagmi'"
},
"dependencies": {
Expand Down
32 changes: 12 additions & 20 deletions apps/laboratory/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
import { defineConfig, devices } from '@playwright/test'
import { defineConfig } from '@playwright/test'
import { BASE_URL } from './tests/shared/constants'

import { config } from 'dotenv'
import type { ModalFixture } from './tests/shared/fixtures/w3m-fixture'
import { getAvailableDevices } from './tests/shared/utils/device'
import { getProjects } from './tests/shared/utils/project'
import { getValue } from './tests/shared/utils/config'
config({ path: './.env.local' })
const availableDevices = getAvailableDevices()

const LIBRARIES = ['wagmi', 'ethers'] as const
const PERMUTATIONS = availableDevices.flatMap(device =>
LIBRARIES.map(library => ({ device, library }))
)

export default defineConfig<ModalFixture>({
testDir: './tests',

testIgnore: 'email.spec.ts',
fullyParallel: true,
retries: 2,
workers: 8,
reporter: process.env['CI']
? [['list'], ['html', { open: 'never' }]]
: [['list'], ['html', { host: '0.0.0.0' }]],

retries: getValue(2, 1),
workers: getValue(8, 4),
reporter: getValue(
[['list'], ['html', { open: 'never' }]],
[['list'], ['html', { host: '0.0.0.0' }]]
),
expect: {
timeout: (process.env['CI'] ? 60 : 15) * 1000
timeout: getValue(60, 15) * 1000
},
timeout: 60 * 1000,

Expand All @@ -41,10 +36,7 @@ export default defineConfig<ModalFixture>({
},

/* Configure projects for major browsers */
projects: PERMUTATIONS.map(({ device, library }) => ({
name: `${device}/${library}`,
use: { ...devices[device], library }
})),
projects: getProjects(),

/* Run your local dev server before starting the tests */
webServer: {
Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/src/pages/library/ethers-email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ const modal = createWeb3Modal({
metadata: ConstantsUtil.Metadata,
termsConditionsUrl: 'https://walletconnect.com/terms',
privacyPolicyUrl: 'https://walletconnect.com/privacy',
enableOnramp: true
enableOnramp: true,
customWallets: ConstantsUtil.CustomWallets
})

ThemeStore.setModal(modal)
Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/src/pages/library/ethers-siwe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ const modal = createWeb3Modal({
enableAnalytics: true,
metadata: ConstantsUtil.Metadata,
siweConfig,
enableOnramp: true
enableOnramp: true,
customWallets: ConstantsUtil.CustomWallets
})

ThemeStore.setModal(modal)
Expand Down
11 changes: 1 addition & 10 deletions apps/laboratory/src/pages/library/ethers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,7 @@ const modal = createWeb3Modal({
metadata: ConstantsUtil.Metadata,
termsConditionsUrl: 'https://walletconnect.com/terms',
privacyPolicyUrl: 'https://walletconnect.com/privacy',
customWallets: [
{
id: 'react-wallet-v2',
name: 'react-wallet-v2',
homepage: 'https://react-wallet-v2-git-chore-2111-walletconnect1.vercel.app',
mobile_link: 'https://react-wallet.walletconnect.com',
desktop_link: 'https://react-wallet.walletconnect.com',
webapp_link: 'https://react-wallet.walletconnect.com'
}
],
customWallets: ConstantsUtil.CustomWallets,
enableOnramp: true
})

Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/src/pages/library/wagmi-email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const modal = createWeb3Modal({
metadata: ConstantsUtil.Metadata,
termsConditionsUrl: 'https://walletconnect.com/terms',
privacyPolicyUrl: 'https://walletconnect.com/privacy',
enableOnramp: true
enableOnramp: true,
customWallets: ConstantsUtil.CustomWallets
})

ThemeStore.setModal(modal)
Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/src/pages/library/wagmi-siwe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ const modal = createWeb3Modal({
enableAnalytics: true,
metadata: ConstantsUtil.Metadata,
siweConfig,
enableOnramp: true
enableOnramp: true,
customWallets: ConstantsUtil.CustomWallets
})

ThemeStore.setModal(modal)
Expand Down
11 changes: 1 addition & 10 deletions apps/laboratory/src/pages/library/wagmi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,7 @@ const modal = createWeb3Modal({
metadata: ConstantsUtil.Metadata,
termsConditionsUrl: 'https://walletconnect.com/terms',
privacyPolicyUrl: 'https://walletconnect.com/privacy',
customWallets: [
{
id: 'react-wallet-v2',
name: 'react-wallet-v2',
homepage: 'https://react-wallet-v2-git-chore-2111-walletconnect1.vercel.app',
mobile_link: 'https://react-wallet.walletconnect.com',
desktop_link: 'https://react-wallet.walletconnect.com',
webapp_link: 'https://react-wallet.walletconnect.com'
}
],
customWallets: ConstantsUtil.CustomWallets,
enableOnramp: true
})

Expand Down
11 changes: 11 additions & 0 deletions apps/laboratory/src/utils/ConstantsUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const projectId = process.env['NEXT_PUBLIC_PROJECT_ID']
if (!projectId) {
throw new Error('NEXT_PUBLIC_PROJECT_ID is not set')
}
export const WALLET_URL = process.env['WALLET_URL'] || 'https://react-wallet.walletconnect.com/'

export const ConstantsUtil = {
SigningSucceededToastTitle: 'Signing Succeeded',
Expand All @@ -14,5 +15,15 @@ export const ConstantsUtil = {
icons: ['https://avatars.githubusercontent.com/u/37784886'],
verifyUrl: ''
},
CustomWallets: [
{
id: 'react-wallet-v2',
name: 'react-wallet-v2',
homepage: WALLET_URL,
mobile_link: WALLET_URL,
desktop_link: WALLET_URL,
webapp_link: WALLET_URL
}
],
ProjectId: projectId
}
54 changes: 28 additions & 26 deletions apps/laboratory/tests/canary.spec.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,47 @@
import { DEFAULT_SESSION_PARAMS } from './shared/constants'
import { testMW } from './shared/fixtures/w3m-wallet-fixture'
import { testConnectedMW } from './shared/fixtures/w3m-wallet-fixture'
import { uploadCanaryResultsToCloudWatch } from './shared/utils/metrics'
import { expectConnection } from './shared/utils/validation'

const ENV = process.env['ENVIRONMENT'] || 'dev'
const REGION = process.env['REGION'] || 'eu-central-1'

let startTime = 0

testMW.beforeEach(async ({ modalPage, walletPage, modalValidator, walletValidator }) => {
testConnectedMW.beforeEach(async ({ modalValidator, walletValidator }) => {
// Give us extra time in a potentially slow canary deployment
testMW.setTimeout(120_000)
testConnectedMW.setTimeout(120_000)

startTime = Date.now()
const uri = await modalPage.getConnectUri()
await walletPage.connectWithUri(uri)
await walletPage.handleSessionProposal(DEFAULT_SESSION_PARAMS)
await modalValidator.expectConnected()
await walletValidator.expectConnected()
await expectConnection(modalValidator, walletValidator)
})

testMW.afterEach(async ({ modalPage, modalValidator, walletValidator }) => {
testConnectedMW.afterEach(async ({ modalPage, modalValidator, walletValidator, browserName }) => {
if (browserName === 'firefox') {
return
}
await modalPage.disconnect()
await modalValidator.expectDisconnected()
await walletValidator.expectDisconnected()
})

testMW('it should sign', async ({ modalPage, walletPage, modalValidator, walletValidator }) => {
await modalPage.sign()
await walletValidator.expectReceivedSign({})
await walletPage.handleRequest({ accept: true })
await modalValidator.expectAcceptedSign()
testConnectedMW(
'it should sign',
async ({ modalPage, walletPage, modalValidator, walletValidator }) => {
await modalPage.sign()
await walletValidator.expectReceivedSign({})
await walletPage.handleRequest({ accept: true })
await modalValidator.expectAcceptedSign()

if (ENV !== 'dev') {
const duration: number = Date.now() - startTime
await uploadCanaryResultsToCloudWatch(
ENV,
REGION,
'https://lab.web3modal.com/',
'HappyPath.sign',
true,
duration
)
if (ENV !== 'dev') {
const duration: number = Date.now() - startTime
await uploadCanaryResultsToCloudWatch(
ENV,
REGION,
'https://lab.web3modal.com/',
'HappyPath.sign',
true,
duration
)
}
}
})
)
19 changes: 19 additions & 0 deletions apps/laboratory/tests/connect-qr.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { DEFAULT_SESSION_PARAMS } from './shared/constants'
import { testM } from './shared/fixtures/w3m-fixture'
import { WalletPage } from './shared/pages/WalletPage'
import { WalletValidator } from './shared/validators/WalletValidator'

testM('it should connect with uri', async ({ modalPage, modalValidator, context }) => {
const walletPage = new WalletPage(await context.newPage())
await walletPage.load()
const walletValidator = new WalletValidator(walletPage.page)

const uri = await modalPage.getConnectUri()
await walletPage.connectWithUri(uri)
await walletPage.handleSessionProposal(DEFAULT_SESSION_PARAMS)
await modalValidator.expectConnected()
await walletValidator.expectConnected()
await modalPage.disconnect()
await modalValidator.expectDisconnected()
await walletValidator.expectDisconnected()
})
5 changes: 0 additions & 5 deletions apps/laboratory/tests/email.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ import { Email } from './shared/utils/email'
const AVAILABLE_MAILSAC_ADDRESSES = 10

testMEmail.beforeEach(async ({ modalPage, context, modalValidator }) => {
testMEmail.skip()
// Skip wagmi as it's not working
if (modalPage.library === 'wagmi') {
return
}
// This is prone to collissions and will be improved later
const tempEmail = `web3modal${Math.floor(
Math.random() * AVAILABLE_MAILSAC_ADDRESSES
Expand Down
28 changes: 22 additions & 6 deletions apps/laboratory/tests/shared/fixtures/w3m-wallet-fixture.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { testM as base, testMSiwe as siwe } from './w3m-fixture'
import { WalletPage } from '../pages/WalletPage'
import { WalletValidator } from '../validators/WalletValidator'
import type { BrowserContext, Page } from '@playwright/test'
import { DEFAULT_SESSION_PARAMS } from '../constants'

// Declare the types of fixtures to use
interface ModalWalletFixture {
Expand All @@ -9,11 +11,11 @@ interface ModalWalletFixture {
}

// MW -> test Modal + Wallet
export const testMW = base.extend<ModalWalletFixture>({
walletPage: async ({ context }, use) => {
// Use a new page, to open alongside the modal
const walletPage = new WalletPage(await context.newPage())
await walletPage.load()
export const testConnectedMW = base.extend<ModalWalletFixture>({
walletPage: async ({ context, modalPage }, use) => {
const page = await doActionAndWaitForNewPage(modalPage.clickWalletDeeplink(), context)
const walletPage = new WalletPage(page)
await walletPage.handleSessionProposal(DEFAULT_SESSION_PARAMS)
await use(walletPage)
},
walletValidator: async ({ walletPage }, use) => {
Expand All @@ -23,7 +25,6 @@ export const testMW = base.extend<ModalWalletFixture>({
})
export const testMWSiwe = siwe.extend<ModalWalletFixture>({
walletPage: async ({ context }, use) => {
// Use a new page, to open alongside the modal
const walletPage = new WalletPage(await context.newPage())
await walletPage.load()
await use(walletPage)
Expand All @@ -33,4 +34,19 @@ export const testMWSiwe = siwe.extend<ModalWalletFixture>({
await use(walletValidator)
}
})

export async function doActionAndWaitForNewPage(
action: Promise<void>,
context: BrowserContext
): Promise<Page> {
if (!context) {
throw new Error('Browser Context is undefined')
}
const pagePromise = context.waitForEvent('page')
await action
const newPage = await pagePromise

return newPage
}

export { expect } from '@playwright/test'
30 changes: 25 additions & 5 deletions apps/laboratory/tests/shared/pages/ModalPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ export class ModalPage {
async getConnectUri(): Promise<string> {
await this.page.goto(this.url)
await this.connectButton.click()
await this.page.getByTestId('wallet-selector-walletconnect').click()
const connect = this.page.getByTestId('wallet-selector-walletconnect')
await connect.waitFor({
state: 'visible',
timeout: 5000
})
await connect.click()

// Using getByTestId() doesn't work on my machine, I'm guessing because this element is inside of a <slot>
const qrCode = this.page.locator('wui-qr-code')
Expand Down Expand Up @@ -75,8 +80,14 @@ export class ModalPage {
}

async disconnect() {
await this.page.getByTestId('account-button').click()
await this.page.getByTestId('disconnect-button').click()
const accountBtn = this.page.getByTestId('account-button')
await expect(accountBtn).toBeVisible()
await expect(accountBtn).toBeEnabled()
await accountBtn.click({ force: true })
const disconnectBtn = this.page.getByTestId('disconnect-button')
await expect(disconnectBtn).toBeVisible()
await expect(disconnectBtn).toBeEnabled()
await disconnectBtn.click({ force: true })
}

async sign() {
Expand All @@ -85,7 +96,8 @@ export class ModalPage {

async approveSign() {
await expect(
this.page.frameLocator('#w3m-iframe').getByText('requests a signature')
this.page.frameLocator('#w3m-iframe').getByText('requests a signature'),
'Web3Modal iframe should be visible'
).toBeVisible()
await this.page.waitForTimeout(2000)
await this.page
Expand All @@ -95,7 +107,9 @@ export class ModalPage {
}

async promptSiwe() {
await this.page.getByTestId('w3m-connecting-siwe-sign').click()
const siweSign = this.page.getByTestId('w3m-connecting-siwe-sign')
await expect(siweSign, 'Siwe promp sign button should be enabled').toBeEnabled()
await siweSign.click()
}

async cancelSiwe() {
Expand All @@ -108,4 +122,10 @@ export class ModalPage {
await this.page.getByTestId(`w3m-network-switch-${network}`).click()
await this.page.getByTestId(`w3m-header-close`).click()
}

async clickWalletDeeplink() {
await this.connectButton.click()
await this.page.getByTestId('wallet-selector-react-wallet-v2').click()
await this.page.getByTestId('tab-desktop').click()
}
}