Skip to content

Commit

Permalink
fix: reset sa enabled networks (#2104)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomiir authored Apr 2, 2024
1 parent 2a9075e commit c98ca1b
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 90 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ui_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,5 @@ jobs:
if: always()
with:
name: screenshots
path: ./apps/laboratory/screenshots/
path: ./apps/laboratory/test-results/
retention-days: 7
5 changes: 5 additions & 0 deletions apps/laboratory/tests/email.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,8 @@ testMEmail('it should switch network and sign', async ({ modalPage, modalValidat
await modalPage.approveSign()
await modalValidator.expectAcceptedSign()
})

testMEmail('it should disconnect correctly', async ({ modalPage, modalValidator }) => {
await modalPage.disconnect()
await modalValidator.expectDisconnected()
})
37 changes: 1 addition & 36 deletions apps/laboratory/tests/shared/fixtures/w3m-email-fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { test as base } from '@playwright/test'
import type { ModalFixture } from './w3m-fixture'
import { ModalPage } from '../pages/ModalPage'
import { ModalValidator } from '../validators/ModalValidator'
import { DeviceRegistrationPage } from '../pages/DeviceRegistrationPage'
import { Email } from '../utils/email'

const mailsacApiKey = process.env['MAILSAC_API_KEY']
Expand All @@ -17,43 +16,9 @@ export const testMEmail = base.extend<ModalFixture>({
await modalPage.load()

const email = new Email(mailsacApiKey)

const tempEmail = email.getEmailAddressToUse(testInfo.parallelIndex)

await email.deleteAllMessages(tempEmail)
await modalPage.loginWithEmail(tempEmail)

let messageId = await email.getLatestMessageId(tempEmail)

if (!messageId) {
throw new Error('No messageId found')
}
let emailBody = await email.getEmailBody(tempEmail, messageId)
let otp = ''
if (email.isApproveEmail(emailBody)) {
const url = email.getApproveUrlFromBody(emailBody)

await email.deleteAllMessages(tempEmail)

const drp = new DeviceRegistrationPage(await context.newPage(), url)
drp.load()
await drp.approveDevice()
await drp.close()

messageId = await email.getLatestMessageId(tempEmail)

emailBody = await email.getEmailBody(tempEmail, messageId)
if (!email.isApproveEmail(emailBody)) {
otp = email.getOtpCodeFromBody(emailBody)
}
}
if (otp.length !== 7) {
// eslint-disable-next-line no-console
console.log('Getting the OTP code from body', { previousOtp: otp })
otp = email.getOtpCodeFromBody(emailBody)
}
await modalPage.enterOTP(otp)

await modalPage.emailFlow(tempEmail, context)
await use(modalPage)
},
modalValidator: async ({ modalPage }, use) => {
Expand Down
62 changes: 17 additions & 45 deletions apps/laboratory/tests/shared/fixtures/w3m-smart-account-fixture.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,33 @@
import { test as base } from '@playwright/test'
import type { ModalFixture } from './w3m-fixture'
import { DeviceRegistrationPage } from '../pages/DeviceRegistrationPage'
import { Email } from '../utils/email'
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<ModalFixture>({
export const testModalSmartAccount = base.extend<ModalFixture & { slowModalPage: ModalPage }>({
library: ['wagmi', { option: true }],
modalPage: async ({ page, library, context }, use, testInfo) => {
const modalPage = new ModalWalletPage(page, library)
await modalPage.load()

const email = new Email(mailsacApiKey)

const tempEmail = email.getEmailAddressToUse(testInfo.parallelIndex)

await email.deleteAllMessages(tempEmail)
await modalPage.loginWithEmail(tempEmail)

let messageId = await email.getLatestMessageId(tempEmail)

if (!messageId) {
throw new Error('No messageId found')
}
let emailBody = await email.getEmailBody(tempEmail, messageId)
let otp = ''
if (email.isApproveEmail(emailBody)) {
const url = email.getApproveUrlFromBody(emailBody)

await email.deleteAllMessages(tempEmail)

const drp = new DeviceRegistrationPage(await context.newPage(), url)
drp.load()
await drp.approveDevice()
await drp.close()

messageId = await email.getLatestMessageId(tempEmail)

emailBody = await email.getEmailBody(tempEmail, messageId)
if (!email.isApproveEmail(emailBody)) {
otp = email.getOtpCodeFromBody(emailBody)
}
}
if (otp.length !== 6) {
otp = email.getOtpCodeFromBody(emailBody)
}
await modalPage.enterOTP(otp)
await modalPage.switchNetwork('Sepolia')
await modalPage.page.waitForTimeout(1500)
await use(modalPage)
},
modalPage: [
async ({ page, library, context }, use, testInfo) => {
const modalPage = new ModalWalletPage(page, library)
await modalPage.load()

const email = new Email(mailsacApiKey)
const tempEmail = email.getEmailAddressToUse(testInfo.parallelIndex)

await modalPage.emailFlow(tempEmail, context)
await modalPage.switchNetwork('Sepolia')
await modalPage.page.waitForTimeout(1500)
await use(modalPage)
},
{ timeout: 90_000 }
],
modalValidator: async ({ modalPage }, use) => {
const modalValidator = new ModalWalletValidator(modalPage.page)
await use(modalValidator)
Expand Down
45 changes: 45 additions & 0 deletions apps/laboratory/tests/shared/pages/ModalPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import type { BrowserContext, Locator, Page } from '@playwright/test'
import { expect } from '@playwright/test'
import { BASE_URL } from '../constants'
import { doActionAndWaitForNewPage } from '../utils/actions'
import { Email } from '../utils/email'
import { DeviceRegistrationPage } from './DeviceRegistrationPage'

const mailsacApiKey = process.env['MAILSAC_API_KEY'] || ''
if (!mailsacApiKey) {
throw new Error('MAILSAC_API_KEY is not set')
}

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

Expand Down Expand Up @@ -52,6 +59,44 @@ export class ModalPage {
return this.assertDefined(await qrCode.getAttribute('uri'))
}

async emailFlow(emailAddress: string, context: BrowserContext): Promise<void> {
await this.load()

const email = new Email(mailsacApiKey)

await email.deleteAllMessages(emailAddress)
await this.loginWithEmail(emailAddress)

let messageId = await email.getLatestMessageId(emailAddress)

if (!messageId) {
throw new Error('No messageId found')
}
let emailBody = await email.getEmailBody(emailAddress, messageId)
let otp = ''
if (email.isApproveEmail(emailBody)) {
const url = email.getApproveUrlFromBody(emailBody)

await email.deleteAllMessages(emailAddress)

const drp = new DeviceRegistrationPage(await context.newPage(), url)
drp.load()
await drp.approveDevice()
await drp.close()

messageId = await email.getLatestMessageId(emailAddress)

emailBody = await email.getEmailBody(emailAddress, messageId)
if (!email.isApproveEmail(emailBody)) {
otp = email.getOtpCodeFromBody(emailBody)
}
}
if (otp.replace(' ', '').length !== 6) {
otp = email.getOtpCodeFromBody(emailBody)
}
await this.enterOTP(otp)
}

async loginWithEmail(email: string) {
await this.page.goto(this.url)
// Connect Button doesn't have a proper `disabled` attribute so we need to wait for the button to change the text
Expand Down
9 changes: 9 additions & 0 deletions apps/laboratory/tests/shared/pages/ModalWalletPage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable no-await-in-loop */
import { expect } from '@playwright/test'
import type { Page } from '@playwright/test'
import { ModalPage } from './ModalPage'

Expand Down Expand Up @@ -29,4 +30,12 @@ export class ModalWalletPage extends ModalPage {
await this.page.getByTestId('w3m-header-close').click()
await this.page.waitForTimeout(2000)
}

override async disconnect(): Promise<void> {
this.openSettings()
const disconnectBtn = this.page.getByTestId('disconnect-button')
await expect(disconnectBtn, 'Disconnect button should be visible').toBeVisible()
await expect(disconnectBtn, 'Disconnect button should be enabled').toBeEnabled()
await disconnectBtn.click({ force: true })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ const testEmailsEOAAddresses = [
'0x8cD2c90E98309FcdeEd2bA0FdaC050e0284D1fD6',
'0x4446d7538f4CF5832604BE20535d954439Ff075d',
'0xbC6996C993d358989743bC74082B046da9d4d8fb',
'0x1216ff6012bcFcBaDFb4691cF586702Af9482F8C'
'0x1216ff6012bcFcBaDFb4691cF586702Af9482F8C',
// Non-smart account enabled address
'0x26760E9EbAcD6f4C47c095E7fd544C5AC093a4E3'
]

function formatAddress(address: string) {
Expand Down
22 changes: 21 additions & 1 deletion apps/laboratory/tests/smart-account.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { testModalSmartAccount } from './shared/fixtures/w3m-smart-account-fixtu
import type { ModalWalletPage } from './shared/pages/ModalWalletPage'
import type { ModalWalletValidator } from './shared/validators/ModalWalletValidator'

const NOT_ENABLED_SMART_ACCOUNT_INDEX = 10

testModalSmartAccount.beforeEach(async ({ modalValidator }) => {
await modalValidator.expectConnected()
})
Expand Down Expand Up @@ -45,8 +47,26 @@ testModalSmartAccount(
const walletModalValidator = modalValidator as ModalWalletValidator

await walletModalPage.togglePreferredAccountType()
await walletModalPage.switchNetwork('Polygon')
await walletModalPage.switchNetwork('Avalanche')
await walletModalPage.openSettings()
await walletModalValidator.expectEoaAddress(testInfo.parallelIndex)
}
)

testModalSmartAccount(
'it should use an eoa when disconnecting and connecting to a not enabled address',
async ({ modalPage, modalValidator, context }) => {
const walletModalPage = modalPage as ModalWalletPage
const walletModalValidator = modalValidator as ModalWalletValidator

await walletModalPage.togglePreferredAccountType()
await walletModalPage.disconnect()
await walletModalPage.page.waitForTimeout(2500)

await walletModalPage.emailFlow('[email protected]', context)
await walletModalPage.switchNetwork('Sepolia')
await walletModalPage.openSettings()

await walletModalValidator.expectEoaAddress(NOT_ENABLED_SMART_ACCOUNT_INDEX)
}
)
4 changes: 3 additions & 1 deletion packages/core/src/controllers/NetworkController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ type StateKey = keyof NetworkControllerState
// -- State --------------------------------------------- //
const state = proxy<NetworkControllerState>({
supportsAllNetworks: true,
isDefaultCaipNetwork: false
isDefaultCaipNetwork: false,
smartAccountEnabledNetworks: []
})

// -- Controller ---------------------------------------- //
Expand Down Expand Up @@ -141,6 +142,7 @@ export const NetworkController = {
}
state.approvedCaipNetworkIds = undefined
state.supportsAllNetworks = true
state.smartAccountEnabledNetworks = []
},

showUnsupportedChainUI() {
Expand Down
6 changes: 4 additions & 2 deletions packages/core/tests/controllers/ConnectorController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const emailProvider = {

const walletConnectConnector = {
id: 'walletConnect',
explorerId: 'walletConnect',
explorerId: 'walletConnectId',
type: 'WALLET_CONNECT'
} as const
const externalConnector = { id: 'external', type: 'EXTERNAL' } as const
Expand Down Expand Up @@ -78,7 +78,7 @@ describe('ConnectorController', () => {

it('should return the correct connector on getConnector', () => {
ConnectorController.addConnector(zerionConnector)
expect(ConnectorController.getConnector('walletConnect', '')).toBe(undefined)
expect(ConnectorController.getConnector('walletConnectId', '')).toBe(walletConnectConnector)
expect(ConnectorController.getConnector('', 'io.metamask.com')).toBe(metamaskConnector)
expect(ConnectorController.getConnector(zerionConnector.id, '')).toBeUndefined()
expect(ConnectorController.getConnector('unknown', '')).toBeUndefined()
Expand All @@ -98,6 +98,7 @@ describe('ConnectorController', () => {
walletConnectConnector,
externalConnector,
metamaskConnector,
zerionConnector,
emailConnector
])

Expand All @@ -123,6 +124,7 @@ describe('ConnectorController', () => {
walletConnectConnector,
externalConnector,
metamaskConnector,
zerionConnector,
emailConnector,
announcedConnector
])
Expand Down
15 changes: 14 additions & 1 deletion packages/core/tests/controllers/NetworkController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ describe('NetworkController', () => {
expect(NetworkController.state).toEqual({
_client: NetworkController._getClient(),
supportsAllNetworks: true,
isDefaultCaipNetwork: false
isDefaultCaipNetwork: false,
smartAccountEnabledNetworks: []
})
})

Expand Down Expand Up @@ -64,6 +65,7 @@ describe('NetworkController', () => {
expect(NetworkController.state.caipNetwork).toEqual(undefined)
expect(NetworkController.state.approvedCaipNetworkIds).toEqual(undefined)
expect(NetworkController.state.requestedCaipNetworks).toEqual(requestedCaipNetworks)
expect(NetworkController.state.smartAccountEnabledNetworks).toEqual([])
})

it('should update state correctly on setDefaultCaipNetwork()', () => {
Expand All @@ -78,4 +80,15 @@ describe('NetworkController', () => {
expect(NetworkController.state.approvedCaipNetworkIds).toEqual(undefined)
expect(NetworkController.state.requestedCaipNetworks).toEqual(requestedCaipNetworks)
})

it('should check correctly if smart accounts are enabled on the network', () => {
NetworkController.setSmartAccountEnabledNetworks([1])
expect(NetworkController.checkIfSmartAccountEnabled()).toEqual(true)
NetworkController.setSmartAccountEnabledNetworks([])
expect(NetworkController.checkIfSmartAccountEnabled()).toEqual(false)
NetworkController.setSmartAccountEnabledNetworks([2])
expect(NetworkController.checkIfSmartAccountEnabled()).toEqual(false)
NetworkController.setCaipNetwork({ id: 'eip155:2', name: 'Ethereum' })
expect(NetworkController.checkIfSmartAccountEnabled()).toEqual(true)
})
})
3 changes: 1 addition & 2 deletions packages/ethers/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,8 @@ export class Web3Modal extends Web3ModalScaffold {
} else if (providerType !== ConstantsUtil.EMAIL_CONNECTOR_ID) {
provider?.emit('disconnect')
} else {
this.emailProvider?.disconnect()
await this.emailProvider?.disconnect()
}
provider?.emit('disconnect')
},

signMessage: async (message: string) => {
Expand Down

0 comments on commit c98ca1b

Please sign in to comment.