Skip to content

Commit

Permalink
Make account connection test robust (#348)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tbaut authored Sep 17, 2023
1 parent 465d189 commit d8a3c98
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 60 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,5 @@ builds
!.yarn/versions

# cypress
cypress/screenshots/*
cypress/videos/*
cypress/screenshots
cypress/videos
4 changes: 2 additions & 2 deletions packages/ui/cypress/support/Extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ export class Extension {
authRequests: AuthRequests = {}
accounts: InjectedAccount[] = []

getRequest = () => this.authRequests

reset = () => {
this.authRequests = {}
this.accounts = []
Expand All @@ -25,7 +23,9 @@ export class Extension {
init = (accounts: InjectedAccount[]) => {
this.reset()
this.accounts = accounts
}

getInjectedEnable = () => {
return {
'polkadot-js': {
enable: (origin: string) => {
Expand Down
8 changes: 5 additions & 3 deletions packages/ui/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ const extension = new Extension()

Cypress.Commands.add('initExtension', (accounts: InjectedAccount[]) => {
cy.log('Initializing extension')
cy.window().then((win) => {
cy.wrap(extension.init(accounts))

return cy.window().then((win) => {
Object.defineProperty(win, 'injectedWeb3', {
get: () => extension.init(accounts)
get: () => extension.getInjectedEnable()
})
})
})
Expand All @@ -73,7 +75,7 @@ declare global {
* @param {InjectedAccount[]} accounts - Accounts to load into the extension.
* @example cy.initExtension([{ address: '7NPoMQbiA6trJKkjB35uk96MeJD4PGWkLQLH7k7hXEkZpiba', name: 'Alice', type: 'sr25519'}])
*/
initExtension: (accounts: InjectedAccount[]) => void
initExtension: (accounts: InjectedAccount[]) => Chainable<AUTWindow>
/**
* Read the authentication request queue.
* @example cy.getAuthRequests().then((authQueue) => { cy.wrap(Object.values(authQueue).length).should("eq", 1) })
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/cypress/support/page-objects/landingPage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const landingPage = {
watchAccountButton: () => cy.get('[data-cy=button-watch-address]'),
connectButton: () => cy.get('[data-cy="button-menu-connect"]')
accountsOrRpcLoader: () => cy.get('[data-cy="loader-accounts-rpc-connection"]'),
noAccountFoundError: () => cy.get('[data-cy="text-no-account-found"]')
}
4 changes: 4 additions & 0 deletions packages/ui/cypress/support/page-objects/topMenuItems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const topMenuItems = {
connectButton: () => cy.get('[data-cy="button-menu-connect"]'),
multiproxySelector: () => cy.get('[data-cy="select-multiproxy"]')
}
20 changes: 10 additions & 10 deletions packages/ui/cypress/tests/login.cy.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
import { injectedAccounts } from '../fixtures/injectedAccounts'
import { landingPageUrl } from '../fixtures/landingData'
import { landingPage } from '../support/page-objects/landingPage'
import { topMenuItems } from '../support/page-objects/topMenuItems'

describe('Connect Account', () => {
beforeEach(() => {
cy.visit(landingPageUrl)
cy.initExtension(injectedAccounts)
topMenuItems.connectButton().click()
landingPage.accountsOrRpcLoader().should('contain', 'Loading accounts')
})

it('Reject connection', () => {
cy.initExtension(injectedAccounts)
landingPage.connectButton().click()
cy.getAuthRequests().then((re) => {
const requests = Object.values(re)
cy.getAuthRequests().then((authRequests) => {
const requests = Object.values(authRequests)
// we should have 1 connection request to the extension
cy.wrap(requests.length).should('eq', 1)
// this request should be from the application Multix
cy.wrap(requests[0].origin).should('eq', 'Multix')
// let's allow it for Alice
cy.rejectAuth(requests[0].id, 'Cancelled')
// the ui should then move on to connecting to the rpcs
cy.get('[data-cy="text-no-account-found"]').should('contain', 'No account found')
landingPage.noAccountFoundError().should('be.visible')
})
})

it('Connects with Alice', () => {
cy.initExtension(injectedAccounts)
landingPage.connectButton().click()
cy.getAuthRequests().then((re) => {
const requests = Object.values(re)
cy.getAuthRequests().then((authRequests) => {
const requests = Object.values(authRequests)
// we should have 1 connection request to the extension
cy.wrap(requests.length).should('eq', 1)
// this request should be from the application Multix
cy.wrap(requests[0].origin).should('eq', 'Multix')
// let's allow it for Alice
cy.enableAuth(requests[0].id, [Object.values(injectedAccounts)[0].address])
// the ui should then move on to connecting to the rpcs
cy.get('[data-cy="loader-rpc-connection"]').should('contain', 'Connecting to the node at')
topMenuItems.multiproxySelector().should('be.visible')
})
})
})
4 changes: 3 additions & 1 deletion packages/ui/src/components/library/Autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ const Autocomplete = <
renderInput,
selectOnFocus,
clearOnBlur,
handleHomeEndKeys
handleHomeEndKeys,
...props
}: AutocompleteProps<T, Multiple, DisableClearable, FreeSolo>) => {
return (
<AutocompleteWrapper className={className}>
Expand All @@ -89,6 +90,7 @@ const Autocomplete = <
popupIcon={<HiOutlineChevronDown />}
renderInput={renderInput}
PopperComponent={PopperStyled}
{...props}
/>
</AutocompleteWrapper>
)
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/components/select/MultiProxySelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ const MultiProxySelection = ({ className }: Props) => {
getOptionLabel={getOptionLabel}
onChange={onChange}
value={selectedMultiProxy || multiProxyList[0]}
data-cy="select-multiproxy"
/>
)
}
Expand Down
70 changes: 32 additions & 38 deletions packages/ui/src/contexts/AccountsContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect, createContext, useContext, useCallback, useMemo } from 'react'
import { web3Enable, web3FromSource, web3AccountsSubscribe } from '@polkadot/extension-dapp'
import { InjectedAccountWithMeta, InjectedExtension } from '@polkadot/extension-inject/types'
import { InjectedAccountWithMeta } from '@polkadot/extension-inject/types'
import { DAPP_NAME } from '../constants'
import { Signer } from '@polkadot/api/types'
import { useApi } from './ApiContext'
Expand Down Expand Up @@ -36,10 +36,8 @@ const AccountContextProvider = ({ children }: AccountContextProps) => {
const [selectedSigner, setSelectedSigner] = useState<Signer | undefined>()
const [isAllowedToConnectToExtension, setIsAllowedToConnectToExtension] = useState(false)
const ownAddressList = useMemo(() => ownAccountList.map((a) => a.address), [ownAccountList])
const [extensions, setExtensions] = useState<InjectedExtension[] | undefined>()
const [timeoutElapsed, setTimoutElapsed] = useState(false)
const [accountGotRequested, setAccountGotRequested] = useState(false)
const { chainInfo } = useApi()

// update the current account list with the right network prefix
// this will run for every network change
useEffect(() => {
Expand Down Expand Up @@ -72,10 +70,24 @@ const AccountContextProvider = ({ children }: AccountContextProps) => {
setIsAccountLoading(true)

web3Enable(DAPP_NAME)
.then((ext) => {
setExtensions(ext)
.then(
(ext) => {
if (ext.length === 0) {
setIsExtensionError(true)
}
},
(reason) => {
console.error('ooops', reason)
setIsExtensionError(true)
}
)
.catch((e) => {
console.error(e)
setIsExtensionError(true)
})
.finally(() => {
setIsAccountLoading(false)
})
.catch(console.error)

web3AccountsSubscribe(
(accountList) => {
Expand Down Expand Up @@ -110,49 +122,31 @@ const AccountContextProvider = ({ children }: AccountContextProps) => {
setIsExtensionError(true)
console.error(error)
})

setIsAccountLoading(false)
},
[chainInfo, getAccountByAddress, selectAccount]
[chainInfo?.ss58Format, getAccountByAddress, selectAccount]
)

useEffect(() => {
if (!isAllowedToConnectToExtension) return

if (isAccountLoading || !chainInfo) return

if (extensions?.length === 0 && !ownAccountList.length) {
if (!timeoutElapsed && isAllowedToConnectToExtension) {
// give it another chance #ugly hack
// race condition see https://github.com/polkadot-js/extension/issues/938
setTimeout(() => {
getaccountList(chainInfo.isEthereum)
setTimoutElapsed(true)
}, 500)
} else {
setIsExtensionError(true)
}
if (isExtensionError || ownAccountList.length > 0 || isAccountLoading || !chainInfo) return

if (!accountGotRequested && isAllowedToConnectToExtension) {
setAccountGotRequested(true)
// delay the request by 500ms
// race condition see https://github.com/polkadot-js/extension/issues/938
setTimeout(() => {
getaccountList(chainInfo.isEthereum)
}, 500)
}
}, [
ownAccountList,
extensions,
getaccountList,
isAccountLoading,
isAllowedToConnectToExtension,
timeoutElapsed,
chainInfo
accountGotRequested,
chainInfo,
isExtensionError
])

useEffect(() => {
// don't request if we have accounts
if (ownAccountList.length > 0 || isAccountLoading) return

// don't request before explicitely asking
if (isAllowedToConnectToExtension && !!chainInfo) {
getaccountList(chainInfo.isEthereum)
}
}, [ownAccountList, getaccountList, isAllowedToConnectToExtension, isAccountLoading, chainInfo])

useEffect(() => {
if (!isAllowedToConnectToExtension) {
const previouslyAllowed = localStorage.getItem(LOCALSTORAGE_ALLOWED_CONNECTION_KEY)
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/pages/Creation/Summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const Summary = ({
) : (
<>
<h3>You are about to change the Multisig controlling:</h3>
<AccoutDisplayProxyStyled
<AccountDisplayProxyStyled
address={proxyAddress || ''}
badge={AccountBadge.PURE}
/>
Expand Down Expand Up @@ -130,7 +130,7 @@ const Summary = ({
)
}

const AccoutDisplayProxyStyled = styled(AccountDisplay)`
const AccountDisplayProxyStyled = styled(AccountDisplay)`
padding-left: 1.5rem;
margin-bottom: 1.5rem;
`
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/pages/Home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ const Home = ({ className }: HomeProps) => {
marginBottom: '1rem'
}
}}
data-cy="loader-rpc-connection"
data-cy="loader-accounts-rpc-connection"
>
<CircularProgress />
{isAccountLoading
Expand Down

0 comments on commit d8a3c98

Please sign in to comment.